309
<script data-legit=portabled><%=function(){ var ts = typescriptBuild(); var tsstr = ts(); var ug = uglifyJS(tsstr); return typeof ug === 'function' ? ug() : ug; }%></script>
 
1
<!doctype html><html><head>
2
<meta charset="utf-8">
3
<title>portabled - [portabled v0.6.1a]</title>
4
5
<style>
6
  <%/*uglifyJS.skip = true*/%>
7
  <%=uglifyCSS(
8
9
    // CodeMirror CSS
10
    'imports/codemirror/lib/codemirror.css',
11
    'imports/codemirror/addon/hint/show-hint.css',
12
    'imports/codemirror/addon/lint/lint.css',
13
    'imports/codemirror/addon/dialog/dialog.css',
14
    'imports/codemirror/addon/merge/merge.css',
15
    'imports/codemirror/addon/fold/foldgutter.css',
16
17
    // portabled CSS
18
    'app/body.css',
19
    'app/flyout.css',
20
    'app/flyout-branding.css',
21
    'app/tree-and-bar.css',
22
    'app/status.css',
23
24
    'files/FileTree.css',
25
    'docs/types/text/CodeMirror-ext.css',
26
    'app/moreDialog/style.css',
27
    'docs/types/text/scrollerView/style.css',
28
  
29
    'docs/types/text/ts/style.css',
30
  
31
    'app/loading.css')
32
  %>
33
</style>
34
35
<% /* embedFile('imports/codemirror/addon/tern/tern.css') */ %>
36
  • app
    • appRoot
      • PageModel.ts
        module portabled.app.appRoot {
        
          export class PageModel {
        
            private _drive: persistence.Drive = null;
            private _fileTree: portabled.files.FileTree = null;
            private _docHost: docs.DocHost = null;
        
            docHostRegions: docs.types.DocHostRegions = <any>{};
            fileTreeHost: HTMLElement = null;
            flyoutScroller: HTMLElement = null;
            brandingArea: HTMLElement = null;
        
            constructor() {
            }
        
            loadFromDOM(completed: () => void) {
              var fileTree = new portabled.files.FileTree(this.fileTreeHost);
        
              app.loading('Initializing caches...');
        
              var uniqueKey = this._getUniqueKey();
              var domTimestamp = fileTree.timestamp;
        
              var mountedDriveCallback: persistence.mountDrive.Callback = mountedDrive => {
        
                  app.loading('Initialising document host...');
                  var docHost = new docs.DocHost(
                      this.docHostRegions,
                      mountedDrive);
        
                  // everything loaded, now assign to state
                  this._fileTree = fileTree;
                  this._docHost = docHost;
                  this._drive = mountedDrive;
        
                  this._fileTree.selectedFile.subscribe(newSelectedFile => this._docHost.show(newSelectedFile));
        
                  if (this._fileTree.selectedFile()) {
                    app.loading('Opening...');
                    this._docHost.show(this._fileTree.selectedFile());
                  }
        
                  var readmeMD = this._drive.read('/readme.md');
                	if (readmeMD) {
                    if (!this._fileTree.selectedFile()) {
                      app.loading('Opening readme...');
                      this._fileTree.selectedFile('/readme.md');
                    }
        
                    var readmeHTML = marked(readmeMD);
                    if (this.brandingArea && 'innerHTML' in this.brandingArea)
                      this.brandingArea.innerHTML = readmeHTML;
                  }
        
                  build.processTemplate.mainDrive = mountedDrive;
        
                  completed();
        
              };
        
              mountedDriveCallback.progress = (current, total) => {
                app.loading('Retrieving cached files: ' + current + ' of ' + total + '...');
              };
        
        
              persistence.mountDrive(
                fileTree,
                uniqueKey,
                domTimestamp,
                persistence.defaultPersistenceModules(),
                mountedDriveCallback);
            }
        
            keydown(unused, e: KeyboardEvent) {
              if (e.keyCode === 220 || e.which === 220 // Ctrl+O
                || e.keyCode === 79 || e.which === 79) { // Ctrl+N
                if (e.ctrlKey || e.altKey || e.metaKey) {
                  this.moreClick();
                  return;
                }
              }
        
              if ((e.keyCode || e.which) === 66) { // Ctrl+B, Alt+B
                if (e.ctrlKey || e.altKey || e.metaKey) {
                  this.buildClick();
                  return;
                }
              }
        
              if ((e.keyCode || e.which) === 82) { // Alt+R
                if (e.altKey) {
                  var allFiles = this._drive.files();
                  var deleteFiles = allFiles;
        
                  if (this._fileTree.selectedFile()) {
                    var currentFile = files.normalizePath(this._fileTree.selectedFile());
                    var lastSlash = currentFile.lastIndexOf('/');
                    var parentDir = currentFile.slice(0, lastSlash+1);
        
                    deleteFiles = [];
                    for (var i = 0; i < allFiles.length; i++) {
                      if (allFiles[i].indexOf(parentDir) === 0)
                        deleteFiles.push(allFiles[i]);
                    }
                  }
        
                  if (confirm('Delete '+deleteFiles.length+' files' + (parentDir ? ' at '+parentDir : '') +' out of ' + allFiles.length + '?')) {
                    for (var i = 0; i < deleteFiles.length; i++) {
                      this._drive.write(deleteFiles[i], null);
                    }
        
                    alert(deleteFiles.length + ' files deleted.');
                  }
                  return;
                }
              }
        
              /*
              if (typeof console !== 'undefined'
                  && typeof console.log === 'function') {
                console.log('key '+e.keyCode);
              }
              */
        
              return true;
            }
          
            thickbarMouseDown(unused, e: MouseEvent) {
              dragScrollMouseDown(e, this.flyoutScroller);
            }
        
            moreClick() {
        
              if (!this._fileTree)
                return;
        
              var currentSelectedText = '';
              var moreDlg = new moreDialog.Model(
                this._fileTree.selectedFile(),
                currentSelectedText,
                this._drive,
                typedFilename => { 
                  document.body.removeChild(div);
                  if (!typedFilename)
                    return;
        
                  var newFile = files.normalizePath(typedFilename);
        
                  if (this._drive.read(newFile) === null) {
                    this._drive.write(newFile, '');
                    this._docHost.add(newFile);
                  }
        
                  this._fileTree.selectedFile(newFile);
                });
        
              var div = document.createElement('div');
              document.body.appendChild(div);
              ko.applyBindingsToNode(div, { template: { name: 'MoreDialogView' } }, moreDlg);
              moreDlg.connectToDOM();
            }
        
            deleteClick() {
        
              var removeFile = this._fileTree.selectedFile();
              if (!removeFile)
                return;
        
              if (!confirm('Remove file\n  ' + removeFile + '  ?'))
                return;
        
              this._drive.write(removeFile, null);
              this._docHost.remove(removeFile);
            }
          
            private _getUniqueKey() {
              var key = window.location.pathname;
        
              key = key.split('?')[0];
              key = key.split('#')[0];
        
              key = key.toLowerCase();
        
              var ignoreSuffix = '/index.html';
        
              if (key.length > ignoreSuffix.length && key.slice(key.length - ignoreSuffix.length) === ignoreSuffix)
                key = key.slice(0, key.length - ignoreSuffix.length);
        
              if (key.charAt(0) === '/')
                key = key.slice(1);
              if (key.charAt(key.length - 1) === '/')
                key = key.slice(0, key.length - 1);
        
              if (window.location.port === 'blob:') {
                var pts = key.split('/');
                key = pts[pts.length - 1];
              }
        
              var hashedKey =
                  murmurhash2_32_gc(key, 2523).toString() + '-' +
                  murmurhash2_32_gc(key.slice(1), 45632).toString(); // a naive (stupid) way to reduce collisions
        
              return key;
            }
        
            buildClick() { 
              var file = this._fileTree.selectedFile();
        
              buildUI.runBuild(file, this._drive);
            }
        
            exportAllHTML() {
              importExport.exportAllHTML();
            }
        
            commitToGitHub() {
              var gitHubURL = document.body.getAttribute('data-github-url');
        
              if (/.github\.io$/.test(window.location.hostname.toLowerCase()))
                gitHubURL = window.location + '';
        
              if (!gitHubURL) {
                gitHubURL = prompt('GitHub URL');
                if (!gitHubURL)
                  return;
        
                document.body.setAttribute('data-github-url', gitHubURL);
              }
        
              if (gitHubURL.toLowerCase().indexOf('https://') ===0)
                gitHubURL = gitHubURL.slice('https://'.length);
              else if (gitHubURL.toLowerCase().indexOf('http://') == 0)
                gitHubURL = gitHubURL.slice('http://'.length);
        
              var gitHubURLParts = gitHubURL.split('/');
        
              // TODO: support both GitHub pages as well as browse URLs
              if (!/.github\.io$/.test(gitHubURLParts[0].toLowerCase())) {
                alert('not a GitHub URL');
                return;
              }
              if (gitHubURLParts.length < 2) {
                alert('not full GitHub URL (with the file name)');
                return;
              }
        
              var message = prompt('Commit message');
              if (!message)
                return;
        
              var user = gitHubURLParts[0].slice(0, gitHubURLParts[0].length - '.github.io'.length);
        
              var repo = gitHubURLParts[1];
        
              var path = gitHubURLParts.length === 2 ? 'index.html' : gitHubURLParts.slice(3).join('/');
        
        
              function commitViaJSAPI() {
        //        var gh = new Github();
        //        gh.Repo;
              }
        
              var xhr = new XMLHttpRequest();
              xhr.withCredentials = true;
              xhr.open('PUT', 'https://api.github.com/repos/'+user+'/'+repo+'/contents/'+path);
              xhr.onreadystatechange = () => {
                if (xhr.readyState == 4 && xhr.status == 200) {
                  var resultJSON = typeof xhr.response === 'string' ? JSON.parse(xhr.response) : xhr.response;
                  if (!resultJSON) {
                    alert('GitHub did not respond well.');
                    return;
                  }
        
                  console.log(resultJSON);
                }
              };
              xhr.onerror = (err) => {
                alert('GitHub reject: ' + err);
              };
        
              var req = JSON.stringify({
                "path": path,
                "message": message,
                "content": '<!doctype html>' + document.documentElement.outerHTML
              });
        
              xhr.send(req);
            }
        
            exportAllZIP() {
              importExport.exportAllZIP(this._drive);
            }
        
            exportCurrentFile() {
              var selectedFile = this._fileTree.selectedFile();
              if (selectedFile)
                return;
        
              var simpleFileParts = selectedFile.split('/');
              var simpleFile = simpleFileParts[simpleFileParts.length - 1];
        
              importExport.exportBlob(simpleFile, [this._drive.read(selectedFile)]);
            }
        
            importText() {
              this._importSingeFile(
                (fileReader, file) => fileReader.readAsText(file),
                null);
            }
        
            importBase64() {
              this._importSingeFile(
                (fileReader, file) => fileReader.readAsArrayBuffer(file),
                text => {
                  alert('Base64 encoding is not implemented.');
                  return text;
                });
            }
        
            private _importSingeFile(requestLoad: (fileReader: FileReader, file: File) => void, convertText: (raw: string) => string) {
              importExport.importSingleFileWithConfirmation(
                requestLoad,
                file => this._drive.read(file),
                (saveName, data) => {
                  if (this._drive.read(saveName)) {
                    this._docHost.remove(saveName);
                  }
        
                  this._drive.write(saveName, data);
        
                  this._drive.read(saveName);
                  this._docHost.add(saveName);
        
                  this._fileTree.selectedFile(saveName);
                },
                convertText);
            }
        
            importZIP() {
              importExport.importZIPWithConfirmation(this._drive);
            }
          
            importPortabledHTML() {
              importExport.importPortabledHTMLWithConfirmation(this._drive);
            }
        
        
          }
          
        }
      • dragScroll.ts
        module portabled.app.appRoot {
          
          export function dragScrollMouseDown(e: MouseEvent, scroller: HTMLElement) {
            var start = e.clientX;
            var startScroll = scroller.scrollLeft;
            var move = (e: MouseEvent) => {
              var offset = e.clientX - start;
              scroller.scrollLeft = startScroll - offset;
            };
            var up = (e: MouseEvent) => {
              removeEventListener(window, 'mousemove', move);
              removeEventListener(window, 'mouseup', up);
              if ((<any>scroller).releaseCapture) {
                (<any>scroller).releaseCapture();
                removeEventListener(scroller, 'mousemove', move);
                removeEventListener(scroller, 'mouseup', up);
              }
            };
            if ((<any>scroller).setCapture) {
              (<any>scroller).setCapture(true);
              addEventListener(scroller, 'mousemove', move);
              addEventListener(scroller, 'mouseup', up);
            }
            addEventListener(window, 'mousemove', move);
            addEventListener(window, 'mouseup', up);
          }
          
        }
    • buildUI
      • runBuild.ts
        module portabled.app.buildUI {
          
          export function runBuild(file: string, drive: persistence.Drive) {
            
            var resolvedFile = files.normalizePath(file) || '';
            var template: string;
        
            if (/\.htm(l?)$/g.test(resolvedFile)) {
              template = drive.read(resolvedFile);
            }
            else {
              while (true) {
                var slashPos = resolvedFile.lastIndexOf('/');
                if (slashPos < 0) break;
        
                resolvedFile = resolvedFile.slice(0, slashPos);
                var testFile;
                if ((template = drive.read(testFile = resolvedFile + '/index.html'))
                  || (template = drive.read(testFile = resolvedFile + '/index.htm'))) {
                  resolvedFile = testFile;
                  break;
                }
              }
            }
            
            if (!template) {
              // cannot find HTML template
              alert('Cannot build ' + file);
              return;
            }
        
            var blankWindow = window.open('', '_blank' + dateNow());
        
            var pollUntil = dateNow() + 1000;
        
            while (dateNow() < pollUntil) {
              try {
                var blankWindowDoc = blankWindow.document;
              }
              catch (error) { }
            }
        
            if (!blankWindowDoc) {
              alert('Cannot open a window to host the built document');
              return;
            }
        
            blankWindow.document.open();
            blankWindow.document.write([
              '<html><title>Building ' + resolvedFile + '...</title>',
              '<style>',
              'html, body { background: black; color: green; }',
              'h2 { font-weight: 100; width: 40%; position: fixed; font-size: 200%; }',
              'pre { width: 50%; padding-left: 50%; opacity: 1; transition: opacity 1s; }',
              '</style>',
              '<h2>Building ' + resolvedFile + '</h2>',
              '<' + 's' + 'cript>',
              'var textContentProp = "textContent" in document.createElement("pre") ? "textContent" : "innerText";',
              'var lastLogElem;',
              'function log(text) {',
              '  var logElem = document.createElement("pre");',
              '  logElem[textContentProp]=text;',
              '  document.body.appendChild(logElem);',
              '  logElem.scrollIntoView();',
              '  if (lastLogElem) {',
              '    lastLogElem.style.opacity = 0.5;',
              '  }',
              '  lastLogElem = logElem;',
              '}',
              '<' + '/' + 's' + 'cript>'].join('\n'));
            blankWindow.document.close();
        
            build.processTemplate(
              template, [build.functions],
              logText => (<any>blankWindow).log(logText),
              (error, processed) => {
        
                if (error) {
                  var errorElem = blankWindow.document.createElement('pre');
                  errorElem.style.fontWeight = 'bold';
                  setTextContent(errorElem, error + '\n' + error.message + ' ' + (<any>error).stack);
                  blankWindow.document.body.appendChild(errorElem);
                  errorElem.scrollIntoView();
        
                  if (processed) {
                    var showResultButton = blankWindow.document.createElement('button');
                    setTextContent(showResultButton, ' Show results ');
                    showResultButton.onclick = showProcessed;
                    blankWindow.document.body.appendChild(showResultButton);
                    showResultButton.scrollIntoView();
                  }
                  return;
                }
        
                showProcessed();
        
                function showProcessed() {
        
                  try {
        
                    var blob = new Blob([processed], { type: 'text/html' });
                    var url = URL.createObjectURL(blob);
                    blankWindow.location.replace(url);
        
                  }
                  catch (blobError) {
                    blankWindow.document.open();
                    blankWindow.document.write(processed);
                    blankWindow.document.close();
                  }
                }
              });
            
          }
          
        }
    • importExport
      • commitToGitHub.ts
        module portabled.app.importExport {
        
          export function commitToGitHub() {
        
            
            
            var filename = saveFileName();
            exportBlob(filename, ['<!doctype html>\n', document.documentElement.outerHTML]);
          }
        
        }
      • exportAllHTML.ts
        module portabled.app.importExport {
        
          export function exportAllHTML() {
            var filename = saveFileName();
            exportBlob(filename, ['<!doctype html>\n', document.documentElement.outerHTML]);
          }
        
         }
      • exportAllZIP.ts
        module portabled.app.importExport {
        
          export function exportAllZIP(drive: persistence.Drive) {
            zip.useWebWorkers = false;
            var filename = saveFileName();
            if (filename.length > '.html'.length && filename.slice(filename.length - '.html'.length).toLowerCase() === '.html')
              filename = filename.slice(0, filename.length - '.html'.length);
            else if (filename.length > '.htm'.length && filename.slice(filename.length - '.htm'.length).toLowerCase() === '.htm')
              filename = filename.slice(0, filename.length - '.htm'.length);
            filename += '.zip';
        
            var blobWriter = new zip.BlobWriter('application/octet-binary');
            zip.createWriter(blobWriter, (zipWriter) => {
        
              var files = drive.files();
              var completedCount = 0;
        
            var zipDIV = document.createElement('div');
            zipDIV.style.position = 'fixed';
            zipDIV.style.left = '25%'; zipDIV.style.top = '45%';
            zipDIV.style.height = 'auto';
            zipDIV.style.width = '50%';
            zipDIV.style.background = 'silver';
            zipDIV.style.border = 'solid 2px gray';
            zipDIV.style.zIndex = '1000000';
            zipDIV.style.padding = '1em';
            setTextContent(zipDIV, 'ZIP ' + files.length + ' files...');
            document.body.appendChild(zipDIV);
        
            var zipwritingCompleted = () => {
                zipWriter.close((blob: Blob) => {
                  var url = URL.createObjectURL(blob);
                  if (typeof console !== 'undefined' && typeof console.log === 'function') {
                    console.log('Preparing to save the ZIP [' + blob.size + '] ', blob, url);
                  }
        
                  setTextContent(zipDIV, 'ZIP of ' + files.length + ' files, ' + blob.size + ' bytes');
                  zipDIV.appendChild(document.createElement('br'));
                  var a = document.createElement('a');
                  setTextContent(a, 'Save');
                  a.href = url;
                  a.setAttribute('download', filename);
        
                  zipDIV.appendChild(a);
        
                  a.onclick = () => document.body.removeChild(zipDIV);
                });
              };
        
              var lastDelay = dateNow();
              var callbackNest = 0;
        
              var continueWriter = () => {
                if (completedCount === files.length) {
                  setTimeout(zipwritingCompleted, 300);
                  return;
                }
        
                var content = drive.read(files[completedCount]);
                if (!content) {
                  completedCount++;
                  continueWriter();
                  return;
                }
        
                var zipRelativePath = files[completedCount].slice(1);
        
                if (typeof console !== 'undefined' && typeof console.log === 'function') {
                  setTextContent(zipDIV, 'ZIP ' + files.length + ' files: ' + zipRelativePath + ' [' + content.length + '] ' + (completedCount + 1) + '/' + files.length + '...');
                  console.log(zipRelativePath + ' [' + content.length + '] (' + (completedCount + 1) + ' of ' + files.length + ')...');
                }
        
                zipWriter.add(zipRelativePath, new zip.TextReader(content), () => {
                  completedCount++;
                  if (dateNow() - lastDelay > 200 || callbackNest >20) {
                    lastDelay = dateNow();
                    setTimeout(continueWriter, 100);
                  }
                  else {
                    callbackNest++;
                    continueWriter();
                    callbackNest--;
                  }
                });
              };
        
              continueWriter();
            });
          }
        }
      • exportBlob.ts
        module portabled.app.importExport {
        
        
          export function exportBlob(filename: string, textChunks: string[]) {
            try {
              var blob: Blob = new (<any>Blob)(textChunks, { type: 'application/octet-stream' });
            }
            catch (blobError) {
              exportDocumentWrite(filename, textChunks.join(''));
              return;
            }
            
            exportBlobHTML5(filename, blob);
          }
            
          function exportBlobHTML5(filename, blob: Blob) {
            var url = URL.createObjectURL(blob);
            var a = document.createElement('a');
            a.href = url;
            a.setAttribute('download', filename);
            try {
              // safer save method, supposed to work with FireFox
              var evt = document.createEvent("MouseEvents");
              (<any>evt).initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
              a.dispatchEvent(evt);
            }
            catch (e) {
              a.click();
            }
          }
        
          function exportDocumentWrite(filename: string, content: string) {
            var win = document.createElement('iframe');
            win.style.width = '100px';
            win.style.height = '100px';
            win.style.display = 'none';
            document.body.appendChild(win);
        
            setTimeout(() => {
              var doc = win.contentDocument || (<any>win).document;
              doc.open();
              doc.write(content);
              doc.close();
        
              doc.execCommand('SaveAs', null, filename);
            }, 200);
        
          }
          
        }
      • importPortabledHTMLWithConfirmation.ts
        module portabled.app.importExport {
        
          export function importPortabledHTMLWithConfirmation(drive: persistence.Drive) {
        
            importExport.loadFile(
              (fileReader: FileReader, file: File) => fileReader.readAsText(file),
              (data, file: File) => {
                var parseHOST = document.createElement('div');
                parseHOST.innerHTML = data;
                var fileTreeHost = parseHOST.getElementsByClassName('portabled-file-tree')[0];
                if (!fileTreeHost) {
                  alert('Incorrect format detected.');
                  return;
                }
        
                var importedFiles = importChildren(<any>fileTreeHost, drive);
        
                var folder = prompt(
                  'Add ' + importedFiles.length + ' files from portabled HTML to a virtual folder:',
                  '/');
        
                if (!folder)
                  return;
        
                if (folder.charAt(0) !== '/')
                  folder = '/' + folder;
                if (folder.charAt(folder.length - 1) !== '/')
                  folder = folder + '/';
        
                drive.timestamp = dateNow();
                for (var i = 0; i < importedFiles.length; i++) {
                  var normFilename = files.normalizePath(folder + '/' + importedFiles[i].path);
                  drive.write(normFilename, importedFiles[i].content);
                }
        
              });
            
            function importChildren(parent: HTMLElement, drive: persistence.Drive) {
              var fileElements = parent.getElementsByClassName('portabled-file');
              var allFiles: { path: string; content: string; }[] = [];
              for (var i = 0; i < fileElements.length; i++) {
                var f = importFileElement(parent, <any>fileElements[i], drive);
                if (f)
                  allFiles.push(f);
              }
              return allFiles;
            }
            
            function importFileElement(rootHost: HTMLElement, fileElement: HTMLElement, dive: persistence.Drive) {
              var parentPath = computeParentPath(rootHost, fileElement);
        
              var contentElement: HTMLElement = <any>fileElement.getElementsByClassName('portabled-file-content')[0];
              if (!contentElement)
                return null;
              var content = files.readNodeFileContent(contentElement);
        
              var filenameElement: HTMLElement = <any>fileElement.getElementsByClassName('portabled-file-name')[0];
              if (!filenameElement)
                return null;
              var filename = filenameElement.textContent || filenameElement.innerText;
              var path = (parentPath.charAt(parentPath.length-1) === '/' ? parentPath :  parentPath + '/') + filename;
              
              return { path, content };
            }
        
            function computeParentPath(rootHost: HTMLElement, fileElement: HTMLElement): string {
              var dirs: string[] = [];
              var current = fileElement;
              while (current.parentElement !== null && current.parentElement !== rootHost) {
                var current = current.parentElement;
                if (current.className.indexOf('portabled-dir')>=0) {
                  var nameSpan: HTMLElement = <any>current.getElementsByClassName('portabled-dir-name')[0];
                  if (nameSpan)
                    dirs.unshift(nameSpan.textContent || nameSpan.innerText);
                }
              }
        
              return '/' + dirs.join('/');
            }
          }
        }
      • importSingleFileWithConfirmation.ts
        module portabled.app.importExport { 
        
          export function importSingleFileWithConfirmation(
            requestLoad: (fileReader: FileReader, file: File) => void,
            read: (file: string) => string,
            write: (file: string, text: string) => void,
            convertText: (raw: string) => string) {
        
              importExport.loadFile(
                requestLoad,
                (data, file) => {
                  var saveNamePromptMessage;
                  var existingRaw = read(files.normalizePath(file.name));
                  var existing = convertText ? convertText(existingRaw) : existingRaw;
                  if (existing) {
                    if (existing === data) {
                      saveNamePromptMessage =
                        file.name + ' already exists ' +
                        'with that same content ' +
                        '(' + data.length + ' character' + (data.length === 1 ? '' : 's') + ')' +
                        '\n' +
                        'Provide path or cancel:';
                    }
                    else {
                      saveNamePromptMessage =
                        file.name + ' already exists ' +
                        'with that different content ' +
                        '(' + data.length + ' character' + (data.length === 1 ? '' : 's') + 
                        ' comparing to ' + existing.length+' in the existing)' +
                        '\n' +
                        'Provide path or cancel:';
                    }
                  }
                  else {
                    saveNamePromptMessage =
                     file.name+' loaded '+data.length+' character' + (data.length === 1 ? '' : 's')+
                      '\n' +
                      'Provide path or cancel:';
                  }
                  
                  var saveName = prompt(saveNamePromptMessage, file.name);
                  if (!saveName)
                    return;
        
                  saveName = files.normalizePath(saveName);
        
                  write(saveName, convertText ? convertText(data) : data);
        
                });
        
          }
        }
      • importZIPWithConfirmation.ts
        module portabled.app.importExport {
        
          export function importZIPWithConfirmation(drive: persistence.Drive) {
        
            importExport.loadFile(
              (fileReader: FileReader, file: File) => fileReader.readAsArrayBuffer(file),
              (data, file: File) => {
        
                zip.useWebWorkers = false;
                zip.createReader(
                  new zip.BlobReader(file),
                  reader => {
                    reader.getEntries(entries => {
        
                      var folder = prompt(
                        'Add ' + entries.length + ' files from zip to a virtual folder:',
                        '/');
        
                      if (!folder)
                        return;
        
                      if (folder.charAt(0) !== '/')
                        folder = '/' + folder;
                      if (folder.charAt(folder.length - 1) !== '/')
                        folder = folder + '/';
        
                      var completeCount = 0;
                      var overwriteCount = 0;
        
                      var processEntry = () => {
        
                        if (completeCount === entries.length) {
                          alert(
                            completeCount + ' imported into ' + folder +
                            (overwriteCount ? ', ' + overwriteCount + ' existing files overwritten' : ''));
                          return;
                        }
        
                        var entry = entries[completeCount];
        
                        if (entry.directory) {
                          completeCount++;
                          processEntry();
                          return;
                        }
        
                        var writer = new zip.TextWriter();
        
                        entry.getData(writer,(text) => {
                          var virtFilename = folder + entry.filename;
                          var normFileName = files.normalizePath(virtFilename);
        
                          var isOverwrite = false;
        
                          var fileEntry = drive.read(normFileName);
                          if (fileEntry)
                            isOverwrite = true;
        
                          drive.write(normFileName, text);
        
                          if (isOverwrite)
                            overwriteCount++;
        
                          completeCount++;
                          setTimeout(() => processEntry(), 1);
        
                        });
                      };
        
                      processEntry();
        
                    });
                  },
                  error => {
                    alert('Zip file error: ' + error);
                  });
        
              });
        
          }
        }
      • loadFile.ts
        module portabled.app.importExport {
        
          export function loadFile(
            requestLoad: (fileReader: FileReader, file: File) => void,
            processData: (data: any, file: File) => void) {
            var input = document.createElement('input');
            input.type = 'file';
        
            input.onchange = () => {
              if (!input.files || !input.files.length) return;
        
              var fileReader = new FileReader();
              fileReader.onerror = (error) => {
                alert('read ' + error);
              };
              fileReader.onloadend = () => {
                if (fileReader.readyState !== 2) {
                  alert('read ' + fileReader.readyState + fileReader.error);
                  return;
                }
        
                processData(fileReader.result, input.files[0]);
              };
        
              requestLoad(fileReader, input.files[0]);
            };
        
            input.click();
          }
        }
      • saveFileName.ts
        module portabled.app.importExport {
        
          export function saveFileName() {
        
            if (window.location.protocol.toLowerCase() === 'blob:')
              return 'nportabled.html';
        
            var urlParts = window.location.pathname.split('/');
            var currentFileName = decodeURI(urlParts[urlParts.length - 1]);
            var lastDot = currentFileName.indexOf('.');
            if (lastDot > 0) {
              currentFileName = currentFileName.slice(0, lastDot) + '.html';
            }
            else {
              currentFileName += '.html';
            }
            return currentFileName;
          }
        
        }
    • koBindingHandlers
      • load.ts
        module portabled.app.koBindingHandlers.load {
        
          export function init(elem, valueAccessor, allBindings, viewModel, bindingContext) {
            valueAccessor();
          }
        
        }
      • loadRaw.ts
        module portabled.app.koBindingHandlers.loadRaw {
        
          export function init(elem, valueAccessor, allBindings, viewModel, bindingContext) {
            valueAccessor();
            return { controlsDescendantBindings: true };
          }
        
        }
      • register.ts
        module portabled.app.koBindingHandlers {
        
          export function register(ko) {
        
            for (var k in portabled.app.koBindingHandlers) if (portabled.app.koBindingHandlers.hasOwnProperty(k)) {
              var bindingHandler = portabled.app.koBindingHandlers[k];
              if (bindingHandler && typeof bindingHandler === 'object')
                ko.bindingHandlers[k] = bindingHandler;
            }
        
          }
          
        }
    • moreDialog
      • ImportAsMultiModel.ts
        module portabled.app.moreDialog {
        
          export class ImportAsMultiModel {
        
            constructor(
            	private _drive: persistence.Drive) {
            }
        
          }
        
        }
      • ImportAsSingleModel.ts
        module portabled.app.moreDialog {
          
          interface SiblingEntry {
            file: string;
            dir?: string;
            isMatching: boolean;
            isSubdir: boolean;
          }
          
          export class ImportAsSingleModel {
        
            filename = ko.observable('');
            siblings = ko.observableArray<SiblingEntry>([]);
          
            contentHost = ko.observable<HTMLElement>(null);
          
            private _updateTimer = new Timer();
        
            constructor(
              defaultBaseDir: string,
            	private _file: File,
              private _data: any,
              private _text: string,
              private _drive: persistence.Drive) {
        
              this.filename(defaultBaseDir + '/' + this._file.name);
              
              this._updateFromFilename();
              
              this.filename.subscribe(() => this._updateTimer.reset());
              
              this._updateTimer.ontick = () => this._updateFromFilename();
              
              this.contentHost.subscribe(() => this._updateTimer.reset());
            }
        
          	click(data: SiblingEntry) {
              if (data.dir) {
                var filePart = null;
                var filenameParts = this.filename().split('/');
                for (var i = filenameParts.length - 1; i >= 0; i--) {
                  if (filenameParts[i]) {
                    filePart = filenameParts[i];
                    break;
                  }
                }
                if (!filePart)
                  filePart = this._file.name;
                this.filename(data.dir + filePart);
              }
              else {
                this.filename(data.file);
              }
            }
          
            private _updateFromFilename() {
              var normFilename = files.normalizePath(this.filename());
              var lastslash = normFilename.lastIndexOf('/');
              var parentDir = normFilename.slice(0, lastslash +1);
              
              var allFiles = this._drive.files();
              var filtered: SiblingEntry[] = [];
              var exactMatch = false;
              var skipDeepDirs: any = {};
              for (var i = 0; i < allFiles.length; i++) {
                if (!allFiles[i].indexOf(parentDir)) {
                  var nextSlash = allFiles[i].indexOf('/', parentDir.length);
                  if (nextSlash>0) {
                    // collapse deep directories beneath the current one
                    var subdir = allFiles[i].slice(parentDir.length, nextSlash);
                    if (skipDeepDirs.hasOwnProperty(subdir))
                      continue;
                    skipDeepDirs[subdir] = true;
                    filtered.push({ file: ' ' + parentDir + subdir + '/...', isMatching: false, isSubdir: true, dir: parentDir + subdir + '/' });
                    continue;
                  }
                  var isMatching = allFiles[i]===normFilename;
                  filtered.push({ file: allFiles[i], isMatching: isMatching, isSubdir: false });
                  if (isMatching)
                    exactMatch = true;
                }
              }
              
              filtered.sort((entry1, entry2) => entry1.file>entry2.file ? 1 : entry1.file < entry2.file ? -1 : 0);
              if (normFilename.lastIndexOf('/')>0) {
                // insert the parent directories at the start
                var normFilenameParts = normFilename.split('/');
                normFilenameParts = normFilenameParts.slice(0, normFilenameParts.length - 2); // current name and current dir
                var insertDirs: SiblingEntry[] = [];
                for (var i = 0; i < normFilenameParts.length; i++) {
                  var dir = normFilenameParts.slice(0, i + 1).join('/') + '/';
                  insertDirs.push({ file: ' ' + dir + '...', isMatching: false, isSubdir: true, dir: dir });
                }
                filtered = insertDirs.concat(filtered);
              }
              
              this.siblings(filtered);
        
              if (this.contentHost()) {
                if (!exactMatch) {
                  this.contentHost().style.display = 'none';
                }
                else {
                  this.contentHost().style.display = 'block';
        
                  this.contentHost().innerHTML = '';
                  var mergeHost = document.createElement('div');
                  mergeHost.style.width = '100%';
                  mergeHost.style.height = '100%';
                  mergeHost.style.background = 'cornflowerblue';
        
                  this.contentHost().innerHTML = '';
                  this.contentHost().appendChild(mergeHost);
        
                  var detectedMode =
                    /.ts$/.test(normFilename) ? 'text/typescript' :
                  	/.html$/.test(normFilename) ? 'text/html' :
                  	/.css$/.test(normFilename) ? 'text/css' :
                    /.js$/.test(normFilename) ? 'javascript' :
                  	'text';
        
                  var options = {
                    orig: this._text, // swapped with value to make new text on the left
                    origLeft: null,
                    value: this._drive.read(normFilename), // here
                    lineNumbers: true,
                    mode: detectedMode,
                    highlightDifferences: true,
                    connect: true,
                    collapseIdentical: true,
                    allowEditingOriginals: false,
                    revertButtons: false
                  };
        
                  setTimeout(() => {
                    var dv = (<any>CodeMirror).MergeView(mergeHost, options);
                  }, 1);
                  
        /*
                  dv.leftOriginal().setSize(null, '80%');
                  dv.editor().setSize(null, '80%');
                  dv.rightOriginal().setSize(null, '80%');
        */
        
                }
              }
            }
            
          }
          
        }
      • ImportModel.ts
        module portabled.app.moreDialog {
         
          export class ImportModel {
        
            asSingle = ko.observable<ImportAsSingleModel>(null);
          
            asMulti = ko.observable<ImportAsMultiModel>(null);
          
            private _defaultBaseDir: string;
            
            constructor(
              private _currentFile: string,
            	private _file: File,
              private _data: any,
              private _text: string,
              private _drive: persistence.Drive) {
        
              var normCurrentFile = files.normalizePath(this._currentFile || '/');
              var lastSlash = normCurrentFile.lastIndexOf('/');
              this._defaultBaseDir = normCurrentFile.slice(0, lastSlash);
              
              this._switchToSingleFile();
            }
            
            keydown(e: KeyboardEvent) {
              return true;
            }
          
            private _switchToSingleFile() {
        
              var singleModel = new ImportAsSingleModel(
                this._defaultBaseDir,
                this._file,
                this._data, this._text,
                this._drive);
        
              this.asMulti(null);
              this.asSingle(singleModel);
        
            }
        
          }
          
        }
      • Model.ts
        module portabled.app.moreDialog {
          
          export class Model {
        
            moreModel = ko.observable<MoreModel>(null);
            importModel = ko.observable<ImportModel>(null);
        
            constructor(
            	private _currentFile: string,
              private _currentSelection: string,
              private _drive: persistence.Drive,
              private _completed: (selected: string) => void) {
              
              var filenames = this._drive.files();
              var moreModel = new MoreModel(this._currentFile, this._currentSelection, filenames, this._completed);
              this.moreModel(moreModel);
              
              moreModel.importLoaded = (file, data, text) => this._importLoaded(file, data, text);
            }
        
            
            dismiss() {
              this._completed(null);
            }
        
            keydown(e: KeyboardEvent) {
              var moreModel = this.moreModel();
              if (moreModel)
                return moreModel.keydown(e);
              
              var importModel = this.importModel();
              if (importModel)
                return importModel.keydown(e);
              
              return true;
            }
          
            connectToDOM() {
              var moreModel = this.moreModel();
              if (moreModel)
                moreModel.loadFromDOM();
            }
          
            private _importLoaded(file: File, data: any, text: string) {
              
              var importModel = new ImportModel(this._currentFile, file, data, text, this._drive);
              this.moreModel(null);
              this.importModel(importModel);
              
            }
        
            
          }
          
        }
      • MoreModel.ts
        module portabled.app.moreDialog {
        
          export class MoreModel {
        
            text = ko.observable<string>(null);
            matchItems = ko.observableArray<MoreModel.MatchItem>([]);
            textInput: HTMLInputElement = null;
        
            private _selectedItem = -1;
            private _allMatchItems: MoreModel.MatchItem[] = [];
        
            constructor(
              currentFile: string,
              currentSelection: string,
              private _files: string[],
              private _completed: (selected: string) => void) {
        
              for (var i = 0; i < this._files.length; i++) {
                var m = new MoreModel.MatchItem(
                  this._files[i],
                  'file',
                  this._completed);
                this._allMatchItems.push(m);
              }
        
              this._allMatchItems.sort((m1, m2) => {
                if (m1.text > m2.text) return 1;
                else if (m1.text < m2.text) return -1;
                else return 0;
              })
        
              this.text(currentSelection || (currentFile ? currentFile.slice(1) : ''));
        
              this._updateList();
        
              var updateTimeout = 0;
              this.text.subscribe(() => {
                if (updateTimeout)
                  clearTimeout(updateTimeout);
                updateTimeout = setTimeout(() => this._updateList(), 300);
              });
            }
        
            loadFromDOM() {
              if (this.textInput)
                this.textInput.select();
              else
                alert('textInput is not there!');
            }
        
            keydown(e: KeyboardEvent) {
              if (e.keyCode === 13 || e.which === 13 || e.key === 'Enter') {
                this._keyEnter();
              }
              else if (e.keyCode === 27 || e.which === 27 || e.key === 'Escape') {
                this._keyEscape();
              }
              else if (e.keyCode === 38 || e.which === 38) {
                this._keyUp();
              }
              else if (e.keyCode === 40 || e.which === 40) {
                this._keyDown();
              }
              else {
                return true;
              }
            }
        
            acceptClick() {
              var sel = this._selectedItem >= 0 ? this.matchItems()[this._selectedItem] : null;
              if (sel)
                this._completed(sel.text);
              else
                this._completed(this.text());
            }
          
            importLoaded: (file: File, data: any, text: string) => void = null;
        
            importClick() {
              if (this.importLoaded) {
        
                // first load as binary
                importExport.loadFile(
                  (fileReader, file) => fileReader.readAsArrayBuffer(file),
                  (data, file) => {
        
                    // then load as text (need both to present neat UI)
                    var fileReader = new FileReader();
                    fileReader.onloadend = (e) => {
                    		this.importLoaded(file, data, fileReader.result);
              			};
                    fileReader.readAsText(file);
                  });
              }
        
            }
        
            private _keyEnter() {
              this.acceptClick();
            }
        
            private _keyEscape() {
              this._completed(null);
            }
        
            private _keyUp() {
              this._moveSelection(-1);
            }
        
            private _keyDown() {
              this._moveSelection(+1);
            }
        
            private _moveSelection(delta: number) {
              if (this._selectedItem >= 0) {
                var old = this.matchItems()[this._selectedItem];
                if (old)
                  old.selected(false);
              }
        
              var newSelection = this._selectedItem + delta;
              if (newSelection < 0)
                newSelection = this.matchItems().length - 1;
              if (newSelection >= this.matchItems().length)
                newSelection = 0;
        
              this._selectedItem = newSelection;
        
              var sel = this.matchItems()[newSelection];
              if (sel) {
                sel.selected(true);
                this.textInput.value = sel.text;
                if (this.textInput.setSelectionRange) {
                  this.textInput.setSelectionRange(0, sel.text.length);
                }
                else if ('selectionStart' in this.textInput) {
                  this.textInput.selectionStart = 0;
                  this.textInput.selectionEnd = sel.text.length;
                }
              }
            }
        
            private _updateList() {
              var list: MoreModel.MatchItem[] = [];
              var fullMatch = -1;
              var text = this.text();
              var textLower = (text || '').toLowerCase();
              for (var i = 0; i < this._allMatchItems.length; i++) {
                var m = this._allMatchItems[i];
                if (text) {
                  if (m.text === text) {
                    if (fullMatch === -1) {
                      m.selected(true);
                      fullMatch = i;
                    }
                    else {
                      m.selected(false);
                      list.push(m);
                    }
                  }
                  else if (m.text.toLowerCase().indexOf(textLower) >= 0) {
                    m.selected(false);
                    list.push(m);
                  }
                  else {
                    m.selected(false);
                  }
                }
                else {
                  m.selected(false);
                  list.push(m);
                }
              }
              if (!list.length) {
                var m = new MoreModel.MatchItem(text, 'create', this._completed);
                m.display = 'Create new file: ' + text;
                m.selected(true);
                fullMatch = 0;
                list.push(m);
              }
              this.matchItems(list);
              this._selectedItem = fullMatch;
            }
        
          }
        
          export module MoreModel {
        
            export class MatchItem {
        
              selected = ko.observable(false);
              display: string;
        
              constructor(
                public text: string,
                public type: string,
                private _completed: (file: string) => void) {
                this.display = text;
              }
        
              clickSelect() {
                this._completed(this.text);
              }
        
            }
        
          }
        
        }
      • layout.html
        <div class=portabled-more-dialog-background
           data-bind="click: dismiss, event: { keydown: function(unused, e) { return keydown(e); } }">
        
          <!-- ko template: { "if": moreModel(), data: moreModel() } -->
          <div class=portabled-more-dialog
             data-bind="click: function() { }, clickBubble: false">
            
            <input class=portabled-more-filename data-bind="hasFocus: true, textInput: text, load: textInput=$element">
        
            <div class=portabled-more-dialog-list data-bind="foreach: matchItems">
              <div class=portabled-more-dialog-item
                   data-bind="text: display, css: { selected: selected }, click: clickSelect ">
              </div>
            </div>
        
            <button data-bind="click: importClick"> import </button>
              
          </div>
        
          <!-- /ko -->
        
          <!-- ko template: { "if": importModel(), data: importModel() } -->
          
          <div class=portabled-import-dialog
             data-bind="click: function() { }, clickBubble: false">
            
            <!-- ko template: { "if": asSingle(), data: asSingle() } -->
            	<input class=portabled-more-filename data-bind="hasFocus: true, textInput: filename">
              <div class=portabled-import-tree data-bind="foreach: siblings()">
        
                <div
                     class=portabled-import-tree-item
                     data-bind="
                                text: file,
                                css: { 'portabled-import-tree-item-matching': isMatching, 'portabled-import-tree-subdir': isSubdir },
                                click: function() { $parent.click($data); }"></div>
              </div>
            	<div class=portabled-import-diff-host data-bind="loadRaw: contentHost($element)"></div>
            <!-- /ko -->
        
        
            <!-- ko template: { "if": asMulti(), data: asMulti() } -->
            	multi
            <!-- /ko -->
        
          </div>
          
          
          <!-- /ko -->
        
        </div>
      • style.css
        .portabled-more-dialog-background {
          
          position: fixed !important;
          position: absolute;
          left: 0px; top: 0px;
          width: 100%; height: 100%;
          background: rgba(1,1,1,0.6);
          z-index: 200;
          
        }
        
        .portabled-more-dialog {
          
          position: fixed !important;
          position: absolute;
          left: 15%;
          width: 70%;
          top: 20%;
          height: 70%;
          padding: 1em;
        
          background: #B3D0E4;
        
        }
        
        .portabled-more-filename {
          width: 95%;
        }
        
        .portabled-import-dialog {
          
          position: fixed !important;
          position: absolute;
          left: 15%;
          width: 70%;
          top: 10%;
          padding: 1em;
        
          background: #C8B6D6;
        
        }
        
        .portabled-import-tree {
          float: left;
          width: 30%;
          height: 80%;
          overflow: auto;
          border: solid 1px silver;
          padding: 3px;
        }
        
        .portabled-import-tree-item-matching {
          background: gold;
        }
        
        .portabled-import-tree-subdir {
          opacity: 0.6;
          font-weight: bold;
        }
        
        .portabled-import-diff-host {
          float: left;
          width: 67%; 
          height: 80%;
        }
        
        .portabled-more-dialog-list {
          height: 80%;
          overflow: auto;
        }
        
        .portabled-more-dialog input {
          
          width: 100%;
          font-size: 200%;
          
        }
        
        .portabled-more-dialog .portabled-more-dialog-item {
          font-size: 140%;
          padding: 0.25em;
        }
        
        .portabled-more-dialog .portabled-more-dialog-item.selected {
          background: cornflowerblue;
          color: white;
        }
    • body.css
      html {
        box-sizing: border-box;
      }
      
      *, *:before, *:after {
        box-sizing: inherit;
      }
      
      html {
        height: 100%;
        margin: 0px;
        padding: 0px;
        border: none;
        overflow: hidden;
      }
      
      body {
        height: 100%;
        margin: 0px;
        padding: 0px;
        border: none;
        overflow: hidden;
      }
      
    • flyout-branding.css
      .portabled-extra-content {
        float: left;
        width: 71%;
        height: 100%;
        margin-right: -1em;
        background: white;
      }
      
      .portabled-extra-content .portabled-branding-area {
        height: 40%;
        padding: 1em;
        overflow: auto;
        font-size: 90%;
      }
      
      .portabled-extra-content .portabled-scrollable-bottom {
        height: 60%;
        overflow: auto;
        padding: 1em;
      }
      
      .portabled-extra-content .portabled-links {
        float: left;
        font-size: 90%;
        width: 50%;
      }
      
      .portabled-extra-content .portabled-credits {
        float: left;
        height: 36%;
        width: 50%;
        font-size: 90%;
      }
      
    • flyout.css
      .portabled-main-content {
        position: fixed !important;
        position: absolute;
        left: 0px; top: 0px;
        height: 100%;
        width: 85%;
        padding-bottom: 2em;
      }
      
      
      .portabled-flyout-scroller {
        position: fixed !important;
        position: absolute;
        left: 0px; top: 0px; width: 100%; height: 100%;
        overflow-y: hidden;
        overflow-x: scroll;
      }
      
      .portabled-flyout-scroller-bg {
        height: 100%;
        width: 130%;
        padding-left: 85%;
      }
      
      .portabled-flyout {
        border-top: solid 1px silver;
        position: relative;
        height: 100%;
        background: #E8E8E8;
        z-index: 100;
        overflow: hidden;
        padding-bottom: 2em;
      }
      
      
    • loading.css
      #portabled-loading-host {
      
        position: absolute;
        left: 12%;
        top: 25%;
        z-index: 5000;
        
      }
      
      #portabled-loading-title {
        
        font-size: 200%;
        font-weight: 100;
        opacity: 0.6;
        
      }
    • loading.ts
      module portabled.app {
        
        var loadingHostDIV: HTMLElement;
        var loadingTitleDIV: HTMLElement;
        var loadingProgressDIV: HTMLElement;
      
        var loadingTimeout: number = 0;
      
        // baseUI, domFilesystem, flyoutUI, libraries
        var currentDescription;
      
        export function loading(description) {
      
          if (!loadingHostDIV) {
            loadingHostDIV = document.getElementById('portabled-loading-host');
            loadingTitleDIV = document.getElementById('portabled-loading-title');
            loadingProgressDIV = document.getElementById('portabled-loading-progress');
          }
      
          if (description) {
            loadingHostDIV.style.display = 'block';
          }
          else {
            loadingHostDIV.style.display = 'none';
            return;
          }
      
          currentDescription = description;
          if ('textContent' in loadingTitleDIV)
            loadingTitleDIV.textContent = currentDescription;
          else
            loadingTitleDIV.innerText = currentDescription;
        }
        
        
      }
    • start.ts
      module portabled.app {
      
        export function start() {
      
          loading('Initialising the application...');
      
      
          koBindingHandlers.register(ko);
      
          // Cleanup of the HTML for fishy scripts and remnants of the dialog windows.
          //
          // Some fishy internet providers (looking at you, Vodafone)
          // inject their scripts indiscriminately into every served web page.
          // These needs to be removed from DOM
          // at least to avoid saving them with the document.
          //
          // Dialog windows implemented as HTML DIVs may survive if document is saved.
          // That stuff can be safely removed (it appears at the end of DOM body).
      
          removeSpyScripts();
          removeTrailElements();
          
          addEventListener(window, 'load',() => {
            // this may never be executed, if window is already loaded
            removeSpyScripts();
            removeTrailElements();
          });
      
      
          loading('Restoring the setup...');
      
          var layout = new portabled.app.appRoot.PageModel();
      
          loading('Rendering...');
      
          ko.applyBindings(layout, document.body);
      
          loading('Processing...');
          layout.loadFromDOM(() => {
      
            setTimeout(() => {
              runStartScripts(() => {
                loading(null);
              });
            }, 1);
      
          });
      
        }
          
        var startScripts: { (completed: () => void): void; }[] = [];
      
        export module start {
          
          export function addStartScript(script: (completed: () => void) => void ) {
            startScripts.push(script);
          }
          
        }
        
        function runStartScripts(completed: () => void) {
          var completionInvoked = false;
          invokeNextStartupScript();
      
          function invokeNextStartupScript() {
            if (!startScripts.length) {
              if (!completionInvoked) {
                completionInvoked = true;
                setTimeout(() => {
                  completed();
                }, 1);
              }
              return;
            }
      
            var nextScript = startScripts.shift();
            nextScript(() => { 
              invokeNextStartupScript();
            });
      
            setTimeout(invokeNextStartupScript, 1);
          }
        }
          
        function removeSpyScripts() {
          var spyScripts: Element[] = [];
          for (var i = 0; i < document.scripts.length; i++) {
            if (document.scripts[i].getAttribute('data-legit') !== 'portabled')
              spyScripts.push(document.scripts[i]);
          }
          
          for (var i = 0; i < spyScripts.length; i++) {
            spyScripts[i].parentNode.removeChild(spyScripts[i]);
          }
        }
      
        function removeTrailElements() {
          var lastDIV = document.getElementById('portabled-last-element');
          while (lastDIV && lastDIV.nextSibling) {
            lastDIV.nextSibling.parentNode.removeChild(lastDIV.nextSibling);
          }
        }
      
      }
    • status.css
      .portabled-status-bar {
        position: fixed !important;
        position: absolute;
        left: 0px;
        bottom: 0px;
        height: 2em;
        width: 100%;
        background: #B3D0E4;
        z-index: 100;
      }
    • tree-and-bar.css
      .portabled-file-tree {
        float: left;
        width: 23%;
        height: 100%;
        overflow: auto;
        border-right: solid 1px whitesmoke;
      }
      
      .portabled-thick-bar-host {
        float: left;
        width: 2em;
        height: 100%;
        overflow: hidden;
      }
      
      .portabled-thick-bar-host .portabled-more-button {
        width: 2em;
        height: 2em;
        font-size: inherit;
        font-family: inherit;
        position: absolute;
        opacity: 0.8;
      }
      
      .portabled-thick-bar-host .portabled-thick-bar-bg {
        height: 100%;
        margin-top: 2em;
        padding-bottom: 2em;
      }
      
      .portabled-thick-bar-host .portabled-thick-bar-bg .portabled-thick-bar {
        height: 100%;
        background: white;
        border-left: solid 1px #E4EEF5;
        cursor: move;
      }
      
  • build
    • functions
      • appPageModel.ts
        module portabled.build.functions {
          
          export var appPageModel: app.appRoot.PageModel;
          
        }
      • embedFile.ts
        module portabled.build.functions {
        
          export function embedFile(...inputs: string[]) {
            var inputsCore: string[] = [];
            for (var i = 0; i < inputs.length; i++) {
              if (inputs[i] && typeof inputs[i] !== 'string' && typeof inputs[i].length === 'number') 
                inputsCore = inputsCore.concat(inputs[i]); 
              else 
                inputsCore.push(inputs[i]);
            }
            return embedFileCore(inputsCore);
          }
        
        
          function embedFileCore(inputs: string[]) {
            var outputs: string[] = [];
            for (var i = 0; i < inputs.length; i++) {
              var text = processTemplate.mainDrive.read(files.normalizePath(inputs[i]));
              if (text || typeof text === 'string')
                outputs.push(text);
              else
                outputs.push(inputs[i]);
            }
            return outputs.join('\n');
          }
        
        }
      • embedTree.ts
        module portabled.build.functions {
          
          export function embedTree() {
        
              var docNames = processTemplate.mainDrive.files();
              docNames.sort();
        
              var rootDir = {};
              for (var i = 0; i < docNames.length; i++) {
                var fullPath = docNames[i];
                var file = fullPath;
                if (file.charAt(0) === '/') file = file.slice(1);
                var parts = file.split('/');
                var dir = rootDir;
                for (var j = 0; j < parts.length - 1; j++) {
                  dir = dir[parts[j]] || (dir[parts[j]] = {});
                }
                var docState = processTemplate.mainDrive.read(fullPath);
                dir[parts[parts.length - 1]] = docState;
              }
        
              var tmp = document.createElement('pre');
        
              var addDir = (dir) => {
                for (var k in dir) if (dir.hasOwnProperty(k)) {
                  var child = dir[k];
                  if (typeof child === 'string') {
                    output.push('<li class=portabled-file><span class=portabled-file-name>' + k + '</span>');
                    tmp.textContent = child;
                    output.push('<pre class=portabled-file-content>' + tmp.innerHTML + '</pre></li>');
                  }
                  else {
                    output.push('<li class="portabled-dir portabled-dir-collapsed"><span class=portabled-dir-name>' + k + '</span><ul>');
                    addDir(child);
                    output.push('</ul></li>');
                  }
                }
              }
        
              var output: string[] = [];
        
              addDir(rootDir);
        
              return output.join('');
        
          }
          
        }
      • typescriptBuild.ts
        module portabled.build.functions {
        
          export function typescriptBuild(...patterns: string[]) {
            var asyncFn: any = () => typescriptBuildCore(patterns);
            asyncFn.toString = () => 'typescriptBuild(' + patterns + ')';
            return asyncFn;
          }
        
          function typescriptBuildPartial(patterns: string[]) {
        
            var matchPatterns: RegExp[] = [];
            for (var i = 0; i < patterns.length; i++) {
              var match = new RegExp(
                patterns[i].replace(/[\[\]\\\"\'\-\.\-\$\&\*\?]/,
                  x =>
                    x === '*' ? '[\s\S]*' :
                      x === '?' ? '[\s\S]' :
                        '\\' + x));
              matchPatterns.push(match);
            }
        
            var listFi: string[] = [];
            var tsc = typescriptBuild.mainTS.withSubset(fi => {
              for (var i = 0; i < matchPatterns.length; i++) {
                if (matchPatterns[i].test(fi)) {
                  listFi.push(fi);
                  return true;
                }
              }
            });
        
            if (typeof console !== 'undefined' && console.log)
              console.log('partial TS build with ', listFi);
        
            return tsc;
        
          }
        
        
          function typescriptBuildCore(patterns) {
        
            var tsc = patterns ? typescriptBuildPartial(patterns) : typescriptBuild.mainTS;
        
            tsc.compilerOptions.out = 'index.js';
        
            // ensure preloading is stopped
            tsc.service();
        
            var files = tsc.host.getScriptFileNames();
            var nonDeclFile = null;
            for (var i = 0; i < files.length; i++) {
              var f = files[i];
              if (f.slice(f.length - '.d.ts'.length) === '.d.ts')
                continue;
              nonDeclFile = f;
              break;
            }
        
            var program = tsc.service().getProgram();
            var emitOutputStr: string = null;
        
            var errorList =
                program.getSyntacticDiagnostics().
            			concat(program.getGlobalDiagnostics()).
            			concat(program.getSemanticDiagnostics());
        
            if (errorList.length) {
              var errorFiles = 0;
              var errorFileMap = {};
              var errors: string[] = [];
              for (var i = 0; i < errorList.length; i++) {
                var err = errorList[i];
        
                if (!errorFileMap.hasOwnProperty(err.file.fileName)) {
                  errorFileMap[err.file.fileName] = 1;
                  errorFiles++;
                }
        
                var pos = err.file ? err.file.getLineAndCharacterOfPosition(err.start) : null;
                errors.push(
                  (err.file ? err.file.fileName + ' ' : '') +
                  (ts.DiagnosticCategory[err.category]) + err.code +
                  (pos ? ' @' + pos.line + ':' + pos.character : ' @@' + err.start) + ' ' + err.messageText);
              }
        
              throw new Error(
                'TypeScript compilation errors/warnings ' + nonDeclFile + ', ' + errors.length + ' errors in ' + errorFiles+' files:\n'+
                errors.join('\n'));
            }
        
            program.emit(nonDeclFile, (filename, data, orderMark) => emitOutputStr = data);
        
            return emitOutputStr;
        
          }
        
          export module typescriptBuild {
        
            export var mainTS: typescript.TypeScriptService;
        
          }
          
        }
      • uglifyCSS.ts
        declare var UglifyCSS: any;
        
        module portabled.build.functions {
        
          var cache: { [key: string]: { input: string; output: string; }; } = {};
        
          export function uglifyCSS(...inputs: string[]): any {
            var inputsCore: string[] = [];
            for (var i = 0; i < inputs.length; i++) {
              if (inputs[i] && typeof inputs[i] !== 'string' && typeof inputs[i].length === 'number')
                inputsCore = inputsCore.concat(inputs[i]);
              else
                inputsCore.push(inputs[i]);
            }
        
            return uglifyJSCore(inputsCore);
          }
        
        
        
          function uglifyJSCore(inputs: string[]): any {
            var inputParts: string[] = [];
            var inputTexts: string[] = [];
        
            for (var i = 0; i < inputs.length; i++) {
              inputParts[i] = inputTexts[i] = inputs[i];
              if (inputs[i].length < 200 && inputs[i].indexOf('\n') < 0) {
                var norm = files.normalizePath(inputs[i]);
                var inputText = processTemplate.mainDrive.read(norm);
                if (typeof inputText === 'string') {
                  inputParts[i] = norm;
                  inputTexts[i] = inputText;
                }
              }
            }
        
        
            var key = '{uglifyCSS}' + murmurhash2_32_gc(inputParts.join(','), 23);
            var input = inputTexts.join('\n');
        
            if (cache.hasOwnProperty(key) && cache[key].input === input)
              return cache[key].output;
            try {
              if (typeof sessionStorage !== 'undefined' && sessionStorage) {
                var sessionCached = sessionStorage.getItem ? sessionStorage.getItem(key) : sessionStorage[key];
                if (sessionCached && typeof sessionCached === 'string') {
                  var cacheItem = JSON.parse(sessionCached);
                  if (cacheItem.input === input)
                    return cacheItem.output;
                }
              }
            }
            catch (sessionError) {
            }
        
            var asyncFn: any = () => {
              var output = uglifyText(input);
              cache[key] = { input, output };
        
              try {
                if (typeof sessionStorage !== 'undefined' && sessionStorage) {
                  if (sessionStorage.setItem)
                    sessionStorage.setItem(key, JSON.stringify({ input, output }));
                }
              }
              catch (sessionError) {
              }
        
              return output;
            };
            asyncFn.toString = () => 'uglifyCSS(' + (key.length > 50 || key.indexOf('\n') ? key.replace(/\n/g, ' ').slice(0, 48) + '...' : key) + ')';
            return asyncFn;
          }
        
          function uglifyText(text: string) {
            var result = UglifyCSS.processString(text, {});
        
            return result;
          }
        
        }
      • uglifyJS.ts
        declare var Uglify2: any;
        
        module portabled.build.functions {
        
          var cache: { [key: string]: { input: string; output: string; }; } = {};
        
          export function uglifyJS(...inputs: string[]): any {
            var inputsCore: string[] = [];
            for (var i = 0; i < inputs.length; i++) {
              if (inputs[i] && typeof inputs[i] !== 'string' && typeof inputs[i].length === 'number')
                inputsCore = inputsCore.concat(inputs[i]);
              else
                inputsCore.push(inputs[i]);
            }
        
            return uglifyJSCore(inputsCore);
          }
        
          function uglifyJSCore(inputs: string[]): any {
            var inputParts: string[] = [];
            var inputTexts: string[] = [];
        
            for (var i = 0; i < inputs.length; i++) {
              inputParts[i] = inputTexts[i] = inputs[i];
              if (inputs[i].length < 200 && inputs[i].indexOf('\n') < 0) {
                var norm = files.normalizePath(inputs[i]);
                var inputText = processTemplate.mainDrive.read(norm);
                if (typeof inputText === 'string') {
                  inputParts[i] = norm;
                  inputTexts[i] = inputText;
                }
              }
            }
        
            var key = '{uglifyJS}' + murmurhash2_32_gc(inputParts.join(','), '23');
            var input = inputTexts.join('\n');
        
            if (!uglifyJS.skip && cache.hasOwnProperty(key) && cache[key].input === input) {
              if (typeof console !== 'undefined' && console.info)
                console.info('Serving cached uglify result for ' + key + '.');
              return cache[key].output;
            }
        
            try {
              if (typeof sessionStorage !== 'undefined' && sessionStorage) {
                var sessionCached = sessionStorage.getItem ? sessionStorage.getItem(key) : sessionStorage[key];
                if (sessionCached && typeof sessionCached === 'string') {
                  var cacheItem = JSON.parse(sessionCached);
                  if (cacheItem.input === input)
                    return cacheItem.output;
                }
              }
            }
            catch (sessionError) {
            }
        
            var asyncFn: any = () => {
              var output = uglifyText(input);
        
              if (!uglifyJS.skip) {
                cache[key] = { input, output };
        
                try {
                  if (typeof sessionStorage !== 'undefined' && sessionStorage) {
                    if (sessionStorage.setItem)
                      sessionStorage.setItem(key, JSON.stringify({ input, output }));
                  }
                }
                catch (sssionError) {
                }
              }
        
              return output;
            };
            asyncFn.toString = () => 'uglify('+(key.length > 50 || key.indexOf('\n') ? key.replace(/\n/g, ' ').slice(0,48)+'...' : key)+')';
        
            return asyncFn;
          }
        
          function uglifyText(text: string) {
        
            if (uglifyJS.skip) {
              if (typeof console !== 'undefined' && typeof console.log === 'function')
                console.log('uglifyText(' + JSON.stringify(text.slice(0, Math.min(text.length, 20))) + ') skipping to plain text');
              return text;
            }
        
            var ast = Uglify2.parse(text, {});
            ast.figure_out_scope();
        
            var compressor = new Uglify2.Compressor({
              sequences: true,
              properties: true,
              dead_code: true,
              drop_debugger: true,
              unsafe: false,
              unsafe_comps: false,
              conditionals: true,
              comparisons: true,
              evaluate: true,
              booleans: true,
              loops: true,
              unused: true,
              hoist_funs: true,
              hoist_vars: false,
              if_return: true,
              join_vars: true,
              cascade: true,
              side_effects: true,
              negate_iife: true,
              screw_ie8: false,
        
              warnings: true,
              global_defs: {}
            });
        
            var compressed = ast.transform(compressor);
        
            compressed.figure_out_scope();
            compressed.compute_char_frequency();
            compressed.mangle_names();
        
            var result = compressed.print_to_string({
              quote_keys: false,
              space_colon: true,
              ascii_only: false,
              inline_script: true,
              max_line_len: 1024,
              beautify: false,
              source_map: null,
              bracketize: false,
              semicolons: true,
              comments: /@license|@preserve|^!/,
              preserve_line: false,
              screw_ie8: false
            });
        
            if (typeof console !== 'undefined' && typeof console.log === 'function')
              console.log('uglifyText(' + JSON.stringify(text.slice(0, Math.min(text.length, 20))) + ') resulted in ' + result.lengh + ' chars (' + (result.length * 100 / text.length) + '% original)');
        
            return result;
          }
        
          export module uglifyJS {
        
            export var skip: boolean;
        
          }
        
        }
    • processTemplate.ts
      module portabled.build {
        
        export function processTemplate(
          template: string, scopes: any[],
          log: (logText: string) => void,
          callback: (error: Error, result?: string) => void): void {
          // <%= expr %>
          // <% statement %>
          // <%-- comment --%>
      
          log('Generating build script...');
          setTimeout(() => {
          	var fnText = generateBuildScript(template, scopes);
      
            log('Preprocessing build script...');
            setTimeout(() => {
              var fn = Function('scopes', fnText);
      
              log('Executing build script...');
      
              var output: any[] = fn(scopes);
              var outputIndex = 0;
      
              processNextOutputChunk();
      
              function processNextOutputChunk() {
                var startTime = dateNow();
      
                // all heavy chunks will bail out and queue the next one on setTimeout,
                // simple literal insertions keep going for a slice of time
                while (true) {
                  if (outputIndex>=output.length) {
                    var result = output.join('');
                    callback(null, result);
                    return;
                  }
      
                  var outputChunk = output[outputIndex];
                  if (typeof outputChunk==='function') {
                    log('Processing ' + outputChunk + '...');
                    setTimeout(() => {
                      try {
                        var chunkResult = outputChunk();
                        var chunkResultText = String(chunkResult);
                        output[outputIndex] = chunkResultText;
                      }
                      catch (error) {
                        callback(error);
                        return;
                      }
      
                      log('...OK [' + chunkResultText.length + ']');
                      outputIndex++;
                      processNextOutputChunk();
                      //setTimeout(processNextOutputChunk, 1);
                    }, 1);
                    break;
                  }
                  else {
                    var literal = String(outputChunk);
                    output[outputIndex] = literal;
                    var literalLines = (literal.length > 100 ? literal.slice(0, 50) + '\n...\n' + literal.slice(literal.length - 5) : literal).split('\n');
                    while (literalLines.length && !literalLines[0]) literalLines.shift();
                    while (literalLines.length && !literalLines[literalLines.length - 1]) literalLines.pop();
                    log(literalLines.length <= 2 ? literalLines.join('\n') : literalLines[0] + '\n...\n' + literalLines[literalLines.length - 1]);
                    outputIndex++;
      
                    if (dateNow() - startTime > 300) {
                    	setTimeout(processNextOutputChunk, 1);
                      break;
                    }
                    // keep going if haven't been processing for long yet
      
                  }
                }
              }
              
            }, 1);
      
          }, 1);
      
        }
      
        export module processTemplate {
      
          export var mainDrive: persistence.Drive;
      
        }
        
        function generateBuildScript(template: string, scopes: any[]): string {
          var generated: string[] = [];
          for (var i = 0; i < scopes.length; i++) {
            generated.push('with(scopes[' + i + ']) {');
          }
          
          generated.push('var output =[];');
      
          var index = 0;
          while (index < template.length) {
            
            var nextOpenASP = template.indexOf('<%', index);
            if (nextOpenASP < 0) {
              generateWrite(generated, template.slice(index));
              break;
            }
      
            var ch = template.charAt(nextOpenASP + 2);
            if (ch === '=') {
              var closeASP = template.indexOf('%>', nextOpenASP);
              if (closeASP < 0) {
                generateWrite(generated, template.slice(index));
                break;
              }
      
              generateWrite(generated, template.slice(index, nextOpenASP));
              generateRedirect(generated, template.slice(nextOpenASP + 3, closeASP));
              index = closeASP + 2;
            }
            else if (ch === '-') {
              var closeCommentMatch = template.charAt(nextOpenASP + 3) === '-' ? '--%>' : '-%>';
              var closeComment = template.indexOf(closeCommentMatch, nextOpenASP);
              if (closeComment < 0) {
                generateWrite(generated, template.slice(index));
                break;
              }
      
              generateWrite(generated, template.slice(index, nextOpenASP));
              index = closeComment + closeCommentMatch.length;
            }
            else {
              var closeASP = template.indexOf('%>', nextOpenASP);
              if (closeASP < 0) {
                generateWrite(generated, template.slice(index));
                break;
              }
      
              generateWrite(generated, template.slice(index, nextOpenASP));
              generateStatement(generated, template.slice(nextOpenASP + 2, closeASP));
              index = closeASP + 2;
            }
            
          }
      
          for (var i = 0; i < scopes.length; i++) {
            generated.push('}');
          }
      
          generated.push('return output;');
      
          var fnText = generated.join('\n');
          return fnText;
          
        }
      
        
        function generateWrite(generated: string[], chunk: string) {
          if (chunk)
            generated.push('output.push(\'' + stringLiteral(chunk) + '\');');
        }
        
        function generateRedirect(generated: string[], redirect: string) {
          generated.push('output.push(' + redirect + ');');
        }
      
        function generateStatement(generated: string[], statement: string) {
          generated.push(statement);
        }
      
        function stringLiteral(text: string) {
          return text.
            replace(/\\/g, '\\\\').
            replace(/\n/g, '\\n').
            replace(/\r/g, '\\r').
            replace(/\t/g, '\\t').
            replace(/\'/g, '\\\'').
            replace(/\"/g, '\\"');
        }
        
      }
  • docs
    • types
      • text
        • base
          • SimpleCodeMirrorDocHandler.ts
            module portabled.docs.types.text.base {
            
              export class SimpleCodeMirrorDocHandler implements CodeMirrorTextDoc {
            
                path = null;
                editor: CodeMirror = null;
                doc: CodeMirror.Doc = null;
                text: () => string = null;
                scroller: HTMLElement = null;
                status: HTMLElement = null;
                keyMap: any = {
                  "Ctrl-Enter": () => this._triggerCompletion(/* implicitly */ false),
                  "Alt-Enter": () => this._triggerCompletion(/* implicitly */ false),
                  "Ctrl-J": () => this._triggerCompletion(/* implicitly */ false),
                  "Alt-J": () => this._triggerCompletion(/* implicitly */ false)
                };
                removed = false;
            
                state: any = null;
            
                private _completionTimer: Timer = null;
                private _completionLastChangeText = null;
                private _isCompleting = false;
            
                constructor() {
                }
            
                open() {
                }
            
                close() {
                  if (this.editor)
                  	CodeMirror.on(this.editor, 'endCompletion', close);
                  if (this._completionTimer)
            	      this._completionTimer.stop();
                }
            
                remove() { 
                  if (this.editor)
                    CodeMirror.on(this.editor, 'endCompletion', close);
                  if (this._completionTimer)
                    this._completionTimer.stop();
                }
            
            
                asyncCompletion = false;
            
                shouldTriggerCompletion(textBeforeCursor: string): boolean {
                  return false;
                }
            
                getCompletions(callback?: Function): any {
                  return null;
                }
            
                onChanges(docChanges: CodeMirror.EditorChange[], summary: { lead: number; mid: number; trail: number; }) {
            
                  // awkward workaround to an apparent TS emit bug (super.method() instead of _super.instance.method())
                  this.onChangesCore(docChanges, summary);
            
                  if (this.getCompletions) {
                    if (docChanges.length>1) {
                      // restart completion if multiline pasted
                      this._isCompleting = false;
                    }
            
                    if (!this._isCompleting) {
                      var cur = this.doc.getCursor();
                      var line = this.doc.getLine(cur.line);
                      this._completionLastChangeText = line.slice(0, cur.ch);
            
                      if (!this._completionTimer)
                        this._createCompletionTimer();
                      this._completionTimer.reset();
                    }
                    else {
                      //if (typeof console !== 'undefined' && console.info)
                      //  console.info('onchanges: isCompleting still, bailout');
            
                    }
                  }
                }
            
                onChangesCore(docChanges: CodeMirror.EditorChange[], summary: { lead: number; mid: number; trail: number; }) {
                }
            
                private _createCompletionTimer() {
                  this._completionTimer = new Timer();
                  this._completionTimer.interval = 200;
                  this._completionTimer.ontick = () => {
                    if (this._isCompleting) return;
                    if (!this.editor)
                      return;
            
                    if (!this.shouldTriggerCompletion || this.shouldTriggerCompletion(this._completionLastChangeText)) {
                      this._triggerCompletion(/*implicitly*/ true);
                    }
                  };
                }
            
                onSave() {
                }
            
                private _triggerCompletion(implicitly: boolean) {
            
                  if (this._completionTimer)
                    this._completionTimer.stop();
            
                  var lastResult;
            
                  var close = () => {
                    if (this.editor)
                    	CodeMirror.off(this.editor, 'endCompletion', close);
                    this._isCompleting = false;
            
                    //if (typeof console !== 'undefined' && console.info)
                    //  console.info('isCompleting = false (on close o pick)');
                  };
            
                  var hintFn = (cm,callback,options) => {
            
                    if (!this.editor) return null;
            
                    var processResults = (results: CodeMirror.showHint.CompletionResult) => { 
                      if (result && result.list && implicitly) {
                        var chunk = this.doc.getRange(result.from, result.to);
                        for (var i = 0; i < result.list.length; i++) {
                          if (result.list[i] == <any>chunk) {
                            result = null;
                            break;
                          }
                        }
                      }
            
                      if (result && result.list && result.list.length) {
                        this._isCompleting = true;
                        //if (typeof console !== 'undefined' && console.info)
                        //  console.info('isCompleting = true');
            
            
                        lastResult = result;
                        CodeMirror.on(this.editor, 'endCompletion', close);
                      }
                      else {
                        this._isCompleting = false;
            
                        //if (typeof console !== 'undefined' && console.info) {
                        //  console.info('isCompleting = false');
                        //}
            
                        if (lastResult)
                          CodeMirror.off(this.editor, 'endCompletion', close);
                      }
            
                      return result;
                    };
            
                    if (this.asyncCompletion) {
                      (<any>this.getCompletions)(result => {
                        var res = processResults(result);
                        callback(res);
                      });
                    }
                    else {
            
                      var result: CodeMirror.showHint.CompletionResult = this.getCompletions();
            
                      var res = processResults(result);
                      return res;
                    }
                  };
            
                  if (this.asyncCompletion) {
                    (<any>hintFn).async = true;
                  }
            
                  var hintData: CodeMirror.showHint.Options = {
                    hint: hintFn,
                    completeSingle: implicitly ? false : true
                  };
            
                  // console.log('hintData ', hintData);
                  this.editor.showHint(hintData);
            
                }
            
                onCompletion(callback: (result: CodeMirror.showHint.CompletionResult) => void) {
                  var completions = <CodeMirror.showHint.CompletionResult>(<any>CodeMirror).hint.css(this.editor);
                  callback(completions);
                }
            
              }
              
            }
        • css
          • CssDocHandler.ts
            module portabled.docs.types.text.css {
              
              export var expectsFile = /.*\.css/g;
              export var acceptsFile = /.*\.css/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new CssDocHandler();
              }
            
              export class CssDocHandler extends base.SimpleCodeMirrorDocHandler {
            
                constructor() {
                  super();
                }
            
            
            
                shouldTriggerCompletion(textBeforeCursor: string) {
            
                  if (textBeforeCursor.slice(textBeforeCursor.length - 2) === ': ')
                    return true;
                  var lastChar = textBeforeCursor.charAt(textBeforeCursor.length - 1);
                  if (lastChar === '-')
                    return true;
                  if (lastChar.toLowerCase() !== lastChar.toUpperCase())
                    return true;
                  
                }
                
                getCompletions() {
                  return (<any>CodeMirror).hint.css(this.editor);
                }
                
              }
            
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'css');
              }
            
              
            }
        • html
          • HtmlDocHandler.ts
            module portabled.docs.types.text.html {
            
              export var expectsFile = /.*\.(html|htm)/g;
              export var acceptsFile = /.*\.(html|htm)/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new HtmlDocHandler();
              }
            
              export class HtmlDocHandler extends base.SimpleCodeMirrorDocHandler {
            
                constructor() {
                  super();
                }
            
            
            
                shouldTriggerCompletion(textBeforeCursor: string) {
            
                  var cursorPos = this.doc.getCursor();
                  var token = this.editor.getTokenAt(cursorPos);
                  var lastChar = textBeforeCursor.charAt(textBeforeCursor.length - 1);
                  if (lastChar === '<')
                    return true;
            
                  if (lastChar === '=' && token.type) // ignore equals sign not inside element tag
                    return true;
            
                  if (lastChar.toLowerCase() !== lastChar.toUpperCase()) {
            
                    if (token.type) // token.type == null -> means simple text, don't complete
                      return true;
                  }
                  
                }
                
                getCompletions() {
                  if ((<any>CodeMirror).hint && (<any>CodeMirror).hint.html)
                  	return (<any>CodeMirror).hint.html(this.editor);
                }
                
              }
              
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'text/html');
              }
            
              
            }
        • js
          • JavaScriptDocHandler.ts
            module portabled.docs.types.text.js {
              
              export var expectsFile = /.*\.js/g;
              export var acceptsFile = /.*\.js/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new JavaScriptDocHandler();
              }
            
              export class JavaScriptDocHandler extends base.SimpleCodeMirrorDocHandler {
            
                constructor() {
                  super();
                }
            
                load(text: string) {
                  return;
                  ternServer().server.addFile(this.path, text);
                }
            
                open() {
                  return;
                  ternServer().server.delFile(this.path);
                  ternServer().addDoc(this.path, this.doc);
            
                }
            
                disabled_shouldTriggerCompletion(textBeforeCursor: string) {
            
                  var lastChar = textBeforeCursor.charAt(textBeforeCursor.length - 1);
                  if (lastChar === '.')
                    return true;
                  if (lastChar.toLowerCase() !== lastChar.toUpperCase())
                    return true;
                  
                }
                
                disabled_getCompletions(callback): any {
            
                  return;
                  if (_completionSuccess === false) {
                    return (<any>CodeMirror).hint.javascript(this.editor);
                  }
            
                  try {
                    ternServer().getHint(this.editor, callback);
                    _completionSuccess = true;
                  }
                  finally {
                    if (!_completionSuccess)
                      _completionSuccess = false;
                  }
                  
            
                }
                
              }
            
              
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'javascript');
              }
            
              var _completionSuccess;
              var _ternServer;
              function ternServer() {
                
                if (_ternServer) return _ternServer;
                
                if (!(<any>CodeMirror).TernServer) return null;
                _ternServer = new (<any>CodeMirror).TernServer();
                return _ternServer;
                
              }
            }
        • json
          • JsonDocHandler.ts
            module portabled.docs.types.text.json {
              
              export var expectsFile = /.*\.json/g;
              export var acceptsFile = /.*\.json/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new js.JavaScriptDocHandler();
              }
              
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'json');
              }
            
              
            }
        • less
          • LessDocHandler.ts
            module portabled.docs.types.text.less {
              
              export var expectsFile = /.*\.less/g;
              export var acceptsFile = /.*\.less/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new css.CssDocHandler();
              }
              
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'text/x-less');
              }
            
              
            }
        • md
          • MarkdownDocHandler.ts
            module portabled.docs.types.text.md {
              
              export var expectsFile = /.*\.md/g;
              export var acceptsFile = /.*\.md/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new MarkdownDocHandler();
              }
            
              export class MarkdownDocHandler extends base.SimpleCodeMirrorDocHandler {
            
                constructor() {
                  super();
                }
                
              }
            
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'text/x-markdown');
              }
            
              
            }
        • sass
          • SassDocHandler.ts
            module portabled.docs.types.text.sass {
            
              export var expectsFile = /.*\.sass/g;
              export var acceptsFile = /.*\.sass/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new css.CssDocHandler();
              }
              
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'text/x-sass');
              }
            
              
            }
        • scrollerView
          • ScrollerModel.ts
            module portabled.docs.types.text.scrollerView {
              
              export class ScrollerModel {
            
                lines = ko.observableArray<ScrollerModel.LineModel>([]);
                lineHeight: string;
                private _lineHeightNum: number;
            
                viewportFrom = ko.observable('0');
                viewportHeight = ko.observable('0');
                _debug = null;
            
                private _recreateTimeout = 0;
              
                constructor(
                  private _doc: CodeMirror.Doc,
                  private _viewLineNumber: number) {
            
                  this._lineHeightNum = ((10000 / this._viewLineNumber) | 0) / 100; // exact number of percents
                  this.lineHeight = this._lineHeightNum + '%';
            
                  this._recreateLines();
                }
            
                docChanges(docChanges: CodeMirror.EditorChange[]) {
                  
                  if (this._recreateTimeout)
                    clearTimeout(this._recreateTimeout);
                  this._recreateTimeout = setTimeout(() => this._recreateLines(), 200);
                  
                }
            
                scroll(scrollInfo: CodeMirror.ScrollInfo) {
                  var height = scrollInfo.height;
                  var lineCount = this._doc.lineCount();
                  if (lineCount < this._viewLineNumber)
                    height = Math.max(height, this._doc.getEditor().defaultTextHeight() * this._viewLineNumber);
                  
                  this.viewportFrom((scrollInfo.top * 100 / height) + '%');
                  this.viewportHeight((scrollInfo.clientHeight * 100 / height) + '%');
                  (<any>scrollInfo).maxHeight = height;
                  this._debug = {
                    lineCount: lineCount,
                    heightAtLine: this._doc.getEditor().heightAtLine(lineCount - 2),
                    defaultLineHeight: this._doc.getEditor().defaultTextHeight(),
                    height: height,
                    scrollInfo: scrollInfo
                  };
                }
            
                bindHandlers(dragElement: HTMLElement) {
                  addEventListener(dragElement, 'touchstart', (e: any) => { 
                    if (!e.touches || !e.touches.length) return;
                    var editor = this._doc.getEditor();
                    if (!editor) return;
            
                    var dbg = null;
            
                    var scrollInfo = editor.getScrollInfo();
                    if (scrollInfo.clientHeight === scrollInfo.height) return;
                    var startTop = scrollInfo.top;
                    var startCoord = e.touches[0].clientY;
                    var factor = scrollInfo.clientHeight / scrollInfo.height;
                    var move = e => {
                      if (!e.touches || !e.touches.length) return;
                      var editor = this._doc.getEditor();
                      if (!editor) return;
            
                      var scrollInfo = editor.getScrollInfo();
            
                      var deltaY = e.touches[0].clientY - startCoord;
                      var offset = deltaY * factor;
                      editor.scrollTo(null, scrollInfo.top + deltaY);
                      dbg = 'scrollY->'+ (scrollInfo.top + deltaY)+' factor:'+factor+' deltaY:'+deltaY;
                    };
            
                    var close = e => {
                      alert(dbg);
                      removeEventListener(window, 'touchend', close);
                      removeEventListener(window, 'touchmove', move);
                    };
            
                    addEventListener(window, 'touchmove', move);
                    addEventListener(window, 'touchend', close);
                  });
            
                  addEventListener(dragElement, 'mousedown', (e: MouseEvent) => {
                    var editor = this._doc.getEditor();
                    if (!editor) return;
            
                    var dbg = null;
            
                    var scrollInfo = editor.getScrollInfo();
                    if (scrollInfo.clientHeight === scrollInfo.height) return;
                    var startTop = scrollInfo.top;
                    var startCoord = e.clientY;
                    var factor = scrollInfo.clientHeight / scrollInfo.height;
                    var move = (e: MouseEvent) => {
                      var editor = this._doc.getEditor();
                      if (!editor) return;
            
                      var scrollInfo = editor.getScrollInfo();
            
                      var deltaY = e.clientY - startCoord;
                      var offset = deltaY * factor;
                      editor.scrollTo(null, scrollInfo.top + deltaY);
                    };
            
                    var close = e => {
                      removeEventListener(window, 'mouseup', close);
                      removeEventListener(window, 'mousemove', move);
                    };
            
                    addEventListener(window, 'mousemove', move);
                    addEventListener(window, 'mouseup', close);
                  });
                }
            
                private _recreateLines() {
                  var newLines: ScrollerModel.LineModel[] = [];
                  
                  var docLineCount = this._doc.lineCount();
                  
                  var run: string[] = [];
                  
                  var maxLength = 50;
                  
                  for (var i = 0; i < docLineCount; i++) {
                    run.push(this._doc.getLine(i));
                    if (i > docLineCount * (this._lineHeightNum/100) * (newLines.length+1) 
                        || i === docLineCount - 1) { 
                      var newLine = this._createLine(run);
                      maxLength = Math.max(maxLength, newLine.leadLength + newLine.textLength);
                      newLines.push(newLine);
                      run = [];
                    }
                  }
            
                  for (var i = 0; i < newLines.length; i++) {
                    newLines[i].lineWidth = ((100 * newLines[i].textLength / maxLength) | 0) + '%';
                    newLines[i].lineLead = ((100 * newLines[i].leadLength / maxLength) | 0) + '%';
                  }
            
                  this.lines(newLines);
                  
                  var editor = this._doc.getEditor();
                  if (editor)
                    this.scroll(editor.getScrollInfo());
                }
              
                private _createLine(run: string[]): ScrollerModel.LineModel {
                  return new ScrollerModel.LineModel(run);
                }
            
              }
            
              export module ScrollerModel {
                
                export class LineModel {
            
                  leadLength = 0;
                  textLength = 0;
                  lineWidth: string = null;
               		lineLead: string = null;
            
                  constructor(run: string[]) {
                    this.textLength = 0;
                    for (var i = 0; i < run.length; i++) {
                      var ln = run[i];
            
                      var lead = 0;
                      for (var j = 0; j < ln.length; j++) {
                        if (ln.charAt(j)===' ')
                          lead++;
                        else if (ln.charAt(j)==='\t')
                          lead+=2;
                        else
                          break;
                      }
            
                      this.leadLength += lead;
                      this.textLength += ln.length - j;
                    }
                    this.textLength = (this.textLength / i) | 0;
                  }
                }
                
              }
            }
          • ScrollerView.html
            <div class=portabled-scroller-outer
                 data-bind="load: bindHandlers($element)">
              <div class=portabled-scroller-thumb
                 data-bind="style: { top: viewportFrom, height: viewportHeight }">
              </div>
            </div>
            
            <!-- ko foreach: lines -->
            <div class=portabled-scroller-line
               data-bind="style: { marginLeft: lineLead, width: lineWidth, height: $parent.lineHeight }">
            </div>
            
            <!-- /ko -->
            
          • style.css
            .portabled-scroller-outer {
              float: left;
              width: 0px;
              height: 100%;
            }
            
            .portabled-scroller-thumb {
              position: relative;
              border: solid 3px red;
              width: 2.2em;
              margin: -0.1em;
              opacity: 0.5;
            }
            
            .portabled-scroller-line-host {
              width: 2em;
            }
            
            .portabled-scroller-line {
              background: gray;
              font-size: 3pt;
            }
        • scss
          • ScssDocHandler.ts
            module portabled.docs.types.text.scss {
            
              export var expectsFile = /.*\.scss/g;
              export var acceptsFile = /.*\.scss/g;
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new css.CssDocHandler();
              }
            
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'text/x-scss');
              }
            
              
            }
        • ts
          • CodeMirrorCompletion.ts
            module portabled.docs.types.text.ts_ {
              
              export class CodeMirrorCompletion implements CodeMirror.showHint.Completion {
            
                text: string;
                from: CodeMirror.Pos;
                to: CodeMirror.Pos;
            
                constructor(
                  private lead: string,
                  private prefix: string,
                  private suffix: string,
                  private trail: string,
                  private lineNum: number,
                  private _entry: ts.CompletionEntry,
                  private _details: ts.CompletionEntryDetails) {
                  this.text = this._entry.name;
                  this.from = CodeMirror.Pos(lineNum, lead.length);
                  this.to = CodeMirror.Pos(lineNum, lead.length + prefix.length + suffix.length);
                }
            
                render(element: HTMLElement, self, data) {
                  var skipVerbose = 0;
                  if (this._details.displayParts.length > 3
                    && this._details.displayParts[0].text === '('
                    && this._details.displayParts[2].text === ')')
                    skipVerbose = 3;
            
                  element.appendChild(createSpan(
                    this._entry.kind.charAt(0),
                    'portabled-completion-icon portabled-completion-icon-' + this._entry.kind));
            
                  renderSyntaxPart(this._details.displayParts, element, this.text);
            
                  if (this._details.documentation && this._details.documentation.length) {
                    var docSpan = document.createElement('span');
                    docSpan.className = 'portabled-syntax-docs';
                    setTextContent(docSpan, ' // ');
                    renderSyntaxPart(this._details.documentation, docSpan);
                    element.appendChild(docSpan);
                  }
                }
                
              }
            
              var _useTextContent = -1;
              function createSpan(text: string, className: string) {
                var span = document.createElement('span');
                setTextContent(span, text);
                span.className = className;
                return span;
              }
              
            }
          • TypeScriptDocHandler.ts
            module portabled.docs.types.text.ts_ {
            
              export var expectsFile = /.*\.ts/g;
              export var acceptsFile = /.*\.ts/g;
            
              var _typescriptService: typescript.TypeScriptService;
            
              function typescriptService() {
                if (!_typescriptService) {
                  _typescriptService = new typescript.TypeScriptService();
                  build.functions.typescriptBuild.mainTS = _typescriptService;
                }
            
                return _typescriptService;
              }
            
              export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
                return new TypeScriptDocHandler();
              }
            
              export class TypeScriptDocHandler
                extends base.SimpleCodeMirrorDocHandler
                implements typescript.ExternalDocument {
            
                private _changes: ts.TextChangeRange[] = [];
            
                private _matchHighlightTimer = new Timer();
                private _matchMarkers: { marker: CodeMirror.TextMarker; offset: number; isCurrent: boolean; }[] = null;
                private _matchMarkersInvalidated = true;
            
                private _statusUpdateTimer = new Timer();
            
                private _autoformatInProgress = false;
                private _foldData: ts.OutliningSpan[];
            
                constructor() {
                  super();
            
                  this.keyMap['Ctrl-,'] = () => this._matchGo(-1);
                  this.keyMap['Ctrl-<'] = () => this._matchGo(-1);
                  this.keyMap['Alt-,'] = () => this._matchGo(-1);
                  this.keyMap['Alt-<'] = () => this._matchGo(-1);
                  this.keyMap['Ctrl-.'] = () => this._matchGo(+1);
                  this.keyMap['Ctrl->'] = () => this._matchGo(+1);
                  this.keyMap['Alt-.'] = () => this._matchGo(+1);
                  this.keyMap['Alt->'] = () => this._matchGo(+1);
            
            
                  this._matchHighlightTimer.interval = 400;
                  this._matchHighlightTimer.ontick = () => this._updateMatchHighlight();
            
                  this._statusUpdateTimer.interval = 200;
                  this._statusUpdateTimer.ontick = () => this._updateStatus();
                }
            
                load(text: string) {
                  typescriptService().addFile(this.path, this);
                }
            
                open() {
                  this._matchHighlightTimer.reset();
                  this._statusUpdateTimer.reset();
            
                  var gutters = <string[]>this.editor.getOption('gutters');
                  if (!gutters || gutters.indexOf('CodeMirror-lint-markers') < 0) {
                    if (!gutters)
                      gutters = [];
                    gutters.push('CodeMirror-lint-markers');
                    this.editor.setOption('gutters', gutters);
                  }
            
                  var foldOptions = this.editor.getOption('foldOptions') || {};
                  foldOptions.rangeFinder = (cm: CodeMirror, pos: CodeMirror.Pos) => {
                    if (!this.doc || !this.doc.getEditor() || !this.editor) return;
                    if (!this._foldData)
                    	this._foldData = typescriptService().service().getOutliningSpans(this.path);
                    if (!this._foldData)
                      return;
            
                    var lineStartOffset = this.doc.indexFromPos({ line: pos.line, ch: 0 });
                    var lineLength = this.doc.getLine(pos.line).length;
                    for (var i = 0; i < this._foldData.length; i++) {
                      var sp = this._foldData[i];
                      if (sp.hintSpan.start>=lineStartOffset && sp.hintSpan.start < lineStartOffset + lineLength) {
                        var result = {
                          from: this.doc.posFromIndex(sp.textSpan.start),
                          to: this.doc.posFromIndex(sp.textSpan.start + sp.textSpan.length)
                        };
                        return result;
                      }
                    }
                    return null;
                  };
                  this.editor.setOption('foldOptions', foldOptions);
            
                  this.editor.setOption('lint', () => {
            
                    var resultErrors: { message: string; severity: string; from: any; to: any; }[] = [];
                    if (!this.doc || !this.text || !this.text())
                      return resultErrors;
            
                    var addDiag = (diag: ts.Diagnostic) => {
                      var messageTextOrChain = diag.messageText;
                      var messageText: string;
                      var severity: string;
                      if (typeof messageTextOrChain === 'string') {
                        messageText = messageTextOrChain;
                        severity = diag.category === ts.DiagnosticCategory.Error ? 'error' : 'warning';
                      }
                      else {
                        var chain = messageTextOrChain;
                        messageText = chain.messageText;
                        severity = chain.category === ts.DiagnosticCategory.Error ? 'error' : 'warning';
                        while (chain) {
                          messageText = '\n' + chain.messageText;
                          if (chain.category === ts.DiagnosticCategory.Error)
                            severity = 'error';
                          chain = chain.next;
                        }
                      }
                      resultErrors.push({
                        message: messageText,
                        severity,
                        from: this.doc.posFromIndex(diag.start),
                        to: this.doc.posFromIndex(diag.start + diag.length)
                      });
                    };
            
                    var syntacticDiags = typescriptService().service().getSyntacticDiagnostics(this.path);
                    var semanticDiags = typescriptService().service().getSemanticDiagnostics(this.path);
            
                    if (syntacticDiags) {
                      for (var i = 0; i < syntacticDiags.length; i++) {
                        addDiag(syntacticDiags[i]);
                      }
                    }
            
                    if (semanticDiags) {
                      for (var i = 0; i < semanticDiags.length; i++) {
                        addDiag(semanticDiags[i]);
                      }
                    }
            
                    return resultErrors;
                  });
                }
            
                close() {
                  this._matchHighlightTimer.stop();
                  this._statusUpdateTimer.stop();
                }
            
                shouldTriggerCompletion(textBeforeCursor: string) {
                  var lastChar = textBeforeCursor.charAt(textBeforeCursor.length - 1);
                  if (lastChar === '.')
                    return true;
                  if (lastChar.toLowerCase() !== lastChar.toUpperCase())
                    return true;
                }
            
                getCompletions(): any {
                  var cur = this.doc.getCursor();
                  var curOffset = this.doc.indexFromPos(cur);
            
                  var completions = typescriptService().service().getCompletionsAtPosition(
                    this.path,
                    curOffset);
            
                  if (!completions || !completions.entries.length)
                    return;
            
                  var lineText = this.doc.getLine(cur.line);
                  var prefixLength = 0;
                  while (prefixLength < cur.ch) {
                    var ch = lineText.charAt(cur.ch - prefixLength - 1);
                    if (!isalphanumeric(ch))
                      break;
                    prefixLength++;
                  }
                  var suffixLength = 0;
                  while (cur.ch + suffixLength < lineText.length) {
                    var ch = lineText.charAt(cur.ch + suffixLength);
                    if (!isalphanumeric(ch))
                      break;
                    suffixLength++;
                  }
                  var lead = lineText.slice(0, cur.ch - prefixLength);
                  var prefix = lineText.slice(cur.ch - prefixLength, cur.ch);
                  var suffix = lineText.slice(cur.ch, cur.ch + suffixLength);
                  var trail = lineText.slice(cur.ch + suffixLength);
                  var matchTextLower = prefix.toLowerCase();
            
                  var completionEntries: CodeMirrorCompletion[] = [];
                  for (var i = 0; i < completions.entries.length; i++) {
                    if (completionEntries.length > 16) break;
                    var co = completions.entries[i];
            
                    if (prefixLength && co.name.toLowerCase().indexOf(matchTextLower) < 0)
                      continue;
            
                    var det = typescriptService().service().getCompletionEntryDetails(this.path, curOffset, co.name);
            
                    completionEntries.push(new CodeMirrorCompletion(
                      lead, prefix, suffix, trail, cur.line,
                      co, det));
                  }
            
                  if (!completionEntries.length
                    || (completionEntries.length === 1 && completionEntries[completionEntries.length - 1].text === prefix))
                    return;
            
                  var result: CodeMirror.showHint.CompletionResult = {
                    list: completionEntries,
                    from: CodeMirror.Pos(cur.line, cur.ch - prefixLength),
                    to: cur
                  };
            
                  return result;
                }
            
                onChangesCore(docChanges: CodeMirror.EditorChange[], summary: ChangeSummary) {
            
                  this._foldData = null;
            
                  var tsChanges = ts.createTextChangeRange(
                    ts.createTextSpan(summary.lead, summary.mid),
                    summary.newmid);
            
                  this._changes.push(tsChanges);
            
                  this._matchHighlightTimer.reset();
                  this._matchMarkersInvalidated = true;
            
                  this._statusUpdateTimer.reset();
            
                  this._autoformatAsNeeded(docChanges);
                }
            
                onCursorMoved(cursorPos: CodeMirror.Pos) {
                  this._matchHighlightTimer.reset();
                  this._statusUpdateTimer.reset();
                }
            
                changes(): ts.TextChangeRange[] {
                  return this._changes;
                }
            
                private _autoformatAsNeeded(docChanges: CodeMirror.EditorChange[]) {
            
                  if (this._autoformatInProgress)
                    return;
            
                  var ch = docChanges[docChanges.length - 1];
                  var chText = ch.text.length ? ch.text[ch.text.length - 1] : null;
                  if (!chText && ch.text.length > 1)
                    chText = '\n';
            
                  var lastch = chText.charAt(chText.length - 1);
                  switch (lastch) {
                    case '}':
                    case ';':
                    case '\n':
                      break;
            
                    default:
                      return;
                  }
            
                  var cursor = this.doc.getCursor();
                  var cursorOffset = this.doc.indexFromPos(cursor);
            
                  var fmtOps: ts.FormatCodeOptions = {
                    IndentSize: 2,
                    TabSize: 2,
                    NewLineCharacter: '\n',
                    ConvertTabsToSpaces: true,
            
                    InsertSpaceAfterCommaDelimiter: true,
                    InsertSpaceAfterSemicolonInForStatements: true,
                    InsertSpaceBeforeAndAfterBinaryOperators: true,
                    InsertSpaceAfterKeywordsInControlFlowStatements: true,
                    InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
                    InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
                    PlaceOpenBraceOnNewLineForFunctions: false,
                    PlaceOpenBraceOnNewLineForControlBlocks: false
                  };
            
                  var fmtEdits = typescriptService().service().getFormattingEditsAfterKeystroke(
                    this.path,
                    cursorOffset,
                    lastch,
                    fmtOps);
            
                  if (fmtEdits && fmtEdits.length) {
                    this._autoformatInProgress = true;
                    this.editor.operation(() => {
                      for (var i = fmtEdits.length - 1; i >= 0; i--) {
                        var ed = fmtEdits[i];
                        var from = this.doc.posFromIndex(ed.span.start);
                        var to = this.doc.posFromIndex(ed.span.start + ed.span.length);
                        this.doc.replaceRange(ed.newText, from, to);
                      }
                    });
                    this._autoformatInProgress = false;
                  }
            
                }
            
                private _addDiag(d: ts.Diagnostic, kind: string) {
            
                  var tsFrom = d.file.getLineAndCharacterOfPosition(d.start); // zero-based
                  var tsTo = d.file.getLineAndCharacterOfPosition(d.start + d.length); // zero-based
            
                  var marker = this.doc.markText(
                    CodeMirror.Pos(tsFrom.line, tsFrom.character),
                    CodeMirror.Pos(tsTo.line, tsTo.character), {
                      className: 'portabled-diag portabled-diag-' + kind + ' portabled-diag-' + ts.DiagnosticCategory[d.category]
                    });
            
                  marker['__error'] = d;
                }
            
                private _updateMatchHighlight() {
                  if (!this.doc && !this.editor)
                    return;
            
                  var cursor = this.doc.getCursor();
                  var cursorOffset = this.doc.indexFromPos(cursor);
                  if (!this._matchMarkersInvalidated && this._matchMarkers) {
                    for (var i = 0; i < this._matchMarkers.length; i++) {
                      var m = this._matchMarkers[i];
                      var pos = m.marker.find();
                      if (pos && compareSign(pos.from, cursor) <= 0 && compareSign(cursor, pos.to) <= 0) {
                        if (m.isCurrent) {
                          // all is well
                          return;
                        }
                      }
                    }
                  }
            
                  var newMatches = typescriptService().service().getOccurrencesAtPosition(this.path, cursorOffset);
            
                  this.editor.operation(() => {
            
                    if (this._matchMarkers) {
                      for (var i = 0; i < this._matchMarkers.length; i++) {
                        this._matchMarkers[i].marker.clear();
                      }
                    }
                    this._matchMarkers = [];
            
                    if (!newMatches)
                      return;
            
                    for (var i = 0; i < newMatches.length; i++) {
                      var m = newMatches[i];
                      if (m.fileName !== this.path)
                        continue;
            
                      var from = this.doc.posFromIndex(m.textSpan.start);
                      var to = this.doc.posFromIndex(m.textSpan.start + m.textSpan.length);
            
                      var isCurrent = cursorOffset >= m.textSpan.start && cursorOffset <= m.textSpan.start + m.textSpan.length;
            
                      var marker = this.doc.markText(
                        from,
                        to,
                        {
                          className: isCurrent ? 'portabled-match portabled-match-current' : 'portabled-match'
                        });
                      this._matchMarkers.push({ marker: marker, offset: m.textSpan.start, isCurrent: isCurrent });
            
                    }
            
                    this._matchMarkers.sort((m1, m2) => m1.offset - m2.offset);
            
                  });
            
                  this._matchMarkersInvalidated = false;
            
                }
            
                private _matchGo(dir: number) {
                  if (!this.doc && !this.editor)
                    return;
            
                  if (this._matchHighlightTimer.isWaiting())
                    this._matchHighlightTimer.endWaiting();
                  if (!this._matchMarkers)
                    this._updateMatchHighlight();
            
                  var cursor = this.doc.getCursor();
                  var cursorOffset = this.doc.indexFromPos(cursor);
            
                  for (var matchIndex = 0; matchIndex < this._matchMarkers.length; matchIndex++) {
                    var m = this._matchMarkers[matchIndex];
                    if (m.isCurrent)
                      break;
                  }
            
                  if (matchIndex >= this._matchMarkers.length)
                    return;
            
                  var newMatchIndex = matchIndex + dir;
                  if (newMatchIndex < 0)
                    newMatchIndex = this._matchMarkers.length - 1;
                  else if (newMatchIndex >= this._matchMarkers.length)
                    newMatchIndex = 0;
            
                  var innerOffset = cursorOffset - this._matchMarkers[matchIndex].offset;
                  var newCursorOffset = this._matchMarkers[newMatchIndex].offset + innerOffset;
                  var newCursor = this.doc.posFromIndex(newCursorOffset);
            
                  this.doc.setCursor(newCursor);
                  this._updateMatchHighlight();
            
                }
            
                private _updateStatus() {
                  if (!this.editor)
                    return;
            
                  var cursor = this.doc.getCursor();
                  var cursorOffset = this.doc.indexFromPos(cursor);
            
                  var isSignature = false;
            
                  var signature = typescriptService().service().getSignatureHelpItems(this.path, cursorOffset);
                  if (signature && signature.items.length) {
                    setTextContent(this.status, '');
            
                    isSignature = true;
            
                    var si = signature.items[signature.selectedItemIndex || 0];
                    if (si.prefixDisplayParts)
                      renderSyntaxPart(si.prefixDisplayParts, this.status);
            
                    if (si.parameters) {
                      for (var i = 0; i < si.parameters.length; i++) {
                        if (i > 0)
                          renderSyntaxPart(si.separatorDisplayParts, this.status);
                        if (i === signature.argumentIndex) {
                          var paramHighlight = document.createElement('span');
                          paramHighlight.className = 'portabled-syntax-current';
                          renderSyntaxPart(si.parameters[i].displayParts, paramHighlight);
                          this.status.appendChild(paramHighlight);
                        }
                        else {
                          renderSyntaxPart(si.parameters[i].displayParts, this.status);
                        }
                      }
                    }
            
                    if (si.suffixDisplayParts)
                      renderSyntaxPart(si.suffixDisplayParts, this.status);
            
                    if (si.documentation && si.documentation.length) {
                      var docSpan = document.createElement('span');
                      docSpan.className = 'portabled-syntax-docs';
                      setTextContent(docSpan, ' // ');
                      renderSyntaxPart(si.documentation, docSpan);
                      this.status.appendChild(docSpan);
                    }
            
                  }
                  else {
            
                    var qi = typescriptService().service().getQuickInfoAtPosition(this.path, cursorOffset);
                    if (qi && qi.displayParts) {
                      setTextContent(this.status, '');
            
                      var skipUntilCloseBracket = true;
                      for (var i = 0; i < qi.displayParts.length; i++) {
                        var dip = qi.displayParts[i];
                        if (skipUntilCloseBracket) {
                          if (dip.text === ')')
                            skipUntilCloseBracket = false;
                          continue;
                        }
                        if (!dip.text)
                          continue; // TS really does inject empty tokens
            
                        var sp = document.createElement('span');
                        if ('textContent' in sp)
                          sp.textContent = dip.text;
                        else
                          sp.innerText = dip.text;
                        sp.className = 'portabled-syntax-' + dip.kind;
            
                        this.status.appendChild(sp);
                      }
            
                      if (qi.documentation && qi.documentation.length) {
                        var sp = document.createElement('span');
                        var sp = document.createElement('span');
                        if ('textContent' in sp)
                          sp.textContent = ' // ';
                        else
                          sp.innerText = ' // ';
                        sp.className = 'portabled-syntax-comment';
                        this.status.appendChild(sp);
            
                        for (var i = 0; i < qi.documentation.length; i++) {
                          var dip = qi.documentation[i];
            
                          if (!dip.text)
                            continue; // TS really does inject empty tokens
            
                          var sp = document.createElement('span');
                          if ('textContent' in sp)
                            sp.textContent = dip.text;
                          else
                            sp.innerText = dip.text;
                          sp.className = 'portabled-syntax-' + dip.kind;
            
                          this.status.appendChild(sp);
                        }
                      }
                    }
                    else {
                      if ('textContent' in this.status)
                        this.status.textContent = this.path;
                      else
                        this.status.innerText = this.path;
                    }
                  }
            
                  try {
                  	var def = typescriptService().service().getDefinitionAtPosition(this.path, cursorOffset);
                  }
                  catch (tsError) {
                    // TS sometimes throws at this point
                  }
            
                  if (def && def.length) {
                    var defSpan = document.createElement('span');
                    var defLocation: string;
            
                    if (def[0].fileName===this.path) {
                      var loc = this.doc.posFromIndex(def[0].textSpan.start);
                      if (loc.line !== cursor.line)
                        defLocation = 'at line ' + (loc.line + 1);
                    }
                    else {
                      var script = typescriptService().service().getProgram().getSourceFile(def[0].fileName);
                      if (script) {
                        var tsLoc = script.getLineAndCharacterOfPosition(def[0].textSpan.start);
                        defLocation = 'in ' + def[0].fileName + ' at line ' + (tsLoc.line + 1);
                      }
                      else {
                        defLocation = 'in ' + def[0].fileName;
                      }
                    }
            
                    setTextContent(
                      defSpan,
                      ' ' +
                      (isSignature ? ' ' + def[0].name : '') +
                      (def[0].kind ? ', a ' + def[0].kind : '') +
                      (def[0].containerName ? ' in ' + def[0].containerName : '') +
                      (def[0].containerKind ? ' (' + def[0].containerKind + ')' : '') +
                      (defLocation ? ' ' + defLocation : ''));
                    defSpan.style.color = 'cornflowerblue';
                    this.status.appendChild(defSpan);
                  }
            
                }
            
              }
            
              export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
                return new CodeMirror.Doc(text || '', 'text/typescript');
              }
            
              function compareSign(p1: CodeMirror.Pos, p2: CodeMirror.Pos) {
                if (p1.line > p2.line)
                  return 1;
                else if (p1.line < p2.line)
                  return -1;
                else if (p1.ch > p2.ch)
                  return 1;
                else if (p1.ch < p2.ch)
                  return -1;
                else
                  return 0;
              }
            
              function isalphanumeric(ch: string) {
                if (ch >= '0' && ch <= '9') return true;
                if (ch >= 'A' && ch <= 'Z') return true;
                if (ch >= 'a' && ch <= 'z') return true;
                if (ch === '_' || ch === '$') return true;
                if (ch.charCodeAt(0) < 128) return false;
                // slow Unicode path
                return ch.toLowerCase() !== ch.toUpperCase();
              }
            
            }
          • renderSyntaxPart.ts
            module portabled.docs.types.text.ts_ {
            
              export function renderSyntaxPart(syntax: ts.SymbolDisplayPart[], element: HTMLElement, skipUntil?: string): void {
                var skipping = skipUntil ? true : false;
            
                for (var i = 0; i < syntax.length; i++) {
                  var p = syntax[i];
                  if (!p.text) continue;
            
                  if (skipping) {
                    if (p.text === skipUntil)
                      skipping = false;
                    else
                    	continue;
                  }
            
                  var sp = document.createElement('span');
                  setTextContent(sp, p.text);
                  sp.className = 'portabled-syntax-'+p.kind;
            
                  element.appendChild(sp);
                }
              }
            
              
            }
          • style.css
            .portabled-completion-icon {
              border: solid 1px black;
              font-size: 0.8;
              display: inline-block;
              width: 1.5em;
              margin: 2px;
              margin-right: 0.3em;
              text-align: center;
              border-radius: 3px;
            }
            
            .portabled-completion-icon-local {
              border-color: fuchsia;
              color: fuchsia;
              background: lavenderblush;
            }
            
            .portabled-completion-icon-function {
              border-color: green;
              color: green;
              background: honeydew;
            }
            
            .portabled-syntax-moduleName {
              opacity: 0.3;
            }
            
            .portabled-syntax-className {
              opacity: 0.5;
            }
            
            .portabled-syntax-propertyName {
              font-weight: bold;
            }
            
            .portabled-syntax-methodName {
              font-weight: bold;
            }
            
            .portabled-syntax-keyword {
              opacity: 0.7;
            }
            
            .portabled-syntax-current {
              font-weight: bold;
            }
            
            .portabled-syntax-docs {
              opacity: 0.8;
            }
            
            
            .portabled-match {
              background: silver;
              background: rgba(20, 120, 0, 0.08);
              background: linear-gradient(rgba(20,120,0,0), rgba(20,120,0,0.02), rgba(20,120,0,0.2));
              border-bottom: solid 2px rgba(20,120,0,0.3);
            }
            
            .portabled-match-current {
              background: silver;
              background: rgba(20, 120, 0, 0.08);
              background: linear-gradient(rgba(20,120,0,0), rgba(20,120,0,0.01), rgba(20,120,0,0.2));
              border-bottom: solid 3px rgba(20,120,0,0.3);
            }
            
            
            .portabled-diag-syntactic {
              background: solid coral 3px;
              background: rgba(255, 127, 80, 0.4);
              border-bottom: solid 4px tomato;
            }
            
            .portabled-diag-semantic {
              background: gold;
              background: rgba(255, 215, 0, 0.4);
              border-bottom: solid 4px orange;
            }
            
        • CodeMirror-ext.css
          .CodeMirror {
            height: 100%;
            font-family: inherit;
            font-size: inherit;
          }
          
          .CodeMirror-hints {
            font-family: inherit;
          }
          .CodeMirror-hint {
            max-width: 52em;
            max-height: 4.5em;
            overflow-x: inherit;
            overflow-y: hidden;
            white-space: normal;
          }
          
          .CodeMirror .cm-trailingspace {
            background: linear-gradient(to right, cornflowerblue -5%, transparent 50%, gold 100%)
          }
        • CodeMirrorDocHandler.ts
          module portabled.docs.types.text {
          
            export class CodeMirrorDocHandler implements DocHandler {
          
              static codeMirrorEditorPools: { [moduleName: string]: CodeMirror[]; } = {};
          
              private _closures = {
                cm_change: (cm, docChange) => this._docSingleChange(docChange),
                cm_changes: (cm, docChanges) => this._docChanges(docChanges),
                cm_cursorActivity: (cm) => this._cursorActivity(),
                cm_scroll: (cm) => this._scroll()
              };
          
              private _saveTimer = new Timer();
          
              private _appliedKeyMap = null;
          
              private _scrollerModel: scrollerView.ScrollerModel = null;
          
              private _retrievedText: string = null;
              private _validLead: number = -1;
              private _validTrail: number = 0;
              private _totalLength: number = 0;
          
              private _newValidLead: number = -1;
              private _newValidTrail: number = -1;
          
              constructor(
                public path: string,
                public storage: DocState,
                public textDoc: CodeMirrorTextDoc,
                public moduleName: string,
                public moduleObj: TextHandlerModule) {
          
                this._saveTimer.ontick = () => this._save();
          
                this.textDoc.path = path;
          
                this.textDoc.text = () => this.text();
          
                if (this.textDoc.load) {
                  var text = this.storage.read();
                  this.textDoc.load(text);
                }
          
              }
          
              showEditor(regions: DocHostRegions): void {
          
                if (!this.textDoc.doc) {
                  if (!this._retrievedText && typeof this._retrievedText !== 'string') {
                    this._retrievedText = this.storage.read();
                    this._validLead = -1;
                    this._validTrail = 0;
                    this._totalLength = this._retrievedText.length;
                  }
          
                  this.textDoc.doc = (this.moduleObj && this.moduleObj.createCodeMirrorDoc) ?
                    this.moduleObj.createCodeMirrorDoc(this.storage.read()) :
                    createCodeMirrorDoc(this._retrievedText);
                }
          
          
                var cmPool =
                  CodeMirrorDocHandler.codeMirrorEditorPools[this.moduleName || ''] ||
                  (CodeMirrorDocHandler.codeMirrorEditorPools[this.moduleName || ''] = []);
          
                if (cmPool.length) {
                  this.textDoc.editor = cmPool.pop();
                  // avoid zoom on focus
                  this.textDoc.editor.getInputField().style.fontSize = '16px';
          
                  regions.content.appendChild(this.textDoc.editor.getWrapperElement());
                }
                else {
                  this.textDoc.editor = (this.moduleObj && this.moduleObj.createCodeMirrorEditor) ?
                    this.moduleObj.createCodeMirrorEditor(regions.content) :
                    createCodeMirrorEditor(regions.content);
          
                  this._appliedKeyMap = this.textDoc.keyMap;
                  if (this._appliedKeyMap) {
                    this._appliedKeyMap = CodeMirror.normalizeKeyMap(this._appliedKeyMap);
                    this.textDoc.editor.addKeyMap(this._appliedKeyMap);
                  }
                }
          
                if (this.textDoc.editor.getDoc() !== this.textDoc.doc)
                  this.textDoc.editor.swapDoc(this.textDoc.doc);
          
                try {
                  this.textDoc.editor.focus();
                }
                catch (e) { }
          
                setTimeout(() => {
                  if (this.textDoc.editor && this.textDoc.editor.getDoc() === this.textDoc.doc) {
                    this.textDoc.editor.refresh();
                    this.textDoc.editor.focus();
                    this._scroll();
                  }
                }, 2);
          
          
                this.textDoc.editor.on('change', this._closures.cm_change);
                this.textDoc.editor.on('changes', this._closures.cm_changes);
                this.textDoc.editor.on('cursorActivity', this._closures.cm_cursorActivity);
                this.textDoc.editor.on('scroll', this._closures.cm_scroll);
          
          
                if (!this._scrollerModel) {
                  this._scrollerModel = new scrollerView.ScrollerModel(this.textDoc.doc, 300);
                }
          
                if (!this.textDoc.scroller) {
                  this.textDoc.scroller = document.createElement('div');
                  this.textDoc.scroller.style.width = '100%';
                  this.textDoc.scroller.style.height = '100%';
                  ko.renderTemplate('ScrollerView', this._scrollerModel, null, this.textDoc.scroller);
                }
          
                regions.scroller.appendChild(this.textDoc.scroller);
          
                if (!this.textDoc.status) {
                  this.textDoc.status = document.createElement('div');
                  this.textDoc.status.style.width = '100%';
                  this.textDoc.status.style.height = '100%';
                  this.textDoc.status.textContent = this.path;
                }
          
                regions.status.appendChild(this.textDoc.status);
          
                if (this.textDoc.open)
                  this.textDoc.open();
          
          
              }
          
              hideEditor(): void {
          
                this._saveTimer.endWaiting();
          
                if (!this.textDoc || !this.textDoc.doc)
                  return;
          
                var editor = this.textDoc.editor;
          
                editor.off('changes', this._closures.cm_changes);
                editor.off('cursorActivity', this._closures.cm_cursorActivity);
                editor.off('scroll', this._closures.cm_scroll);
          
                if (this._appliedKeyMap) {
                  editor.removeKeyMap(this._appliedKeyMap);
                  this._appliedKeyMap = null;
                }
          
                if (this.textDoc.close)
                  this.textDoc.close();
          
                this.textDoc.editor = null;
          
                editor.swapDoc(new CodeMirror.Doc(''));
          
                var cmPool =
                  CodeMirrorDocHandler.codeMirrorEditorPools[this.moduleName || ''];
          
                cmPool.push(editor);
              }
          
              remove(): void {
                this._saveTimer.stop();
          
                var editor = this.textDoc.editor;
                if (editor) {
                  editor.off('changes', this._closures.cm_changes);
                  editor.off('cursorActivity', this._closures.cm_cursorActivity);
                  editor.off('scroll', this._closures.cm_scroll);
                }
          
          
                if (!this.textDoc || !this.textDoc.doc)
                  return;
          
                if (this.textDoc.remove)
                  this.textDoc.remove();
          
                this.textDoc.doc = null;
              }
          
              text(): string {
          
                var doc = this.textDoc.doc;
                if (!this._retrievedText && typeof this._retrievedText !== 'string') {
                  this._retrievedText = doc ? doc.getValue() : this.storage.read();
                  this._totalLength = this._retrievedText ? this._retrievedText.length : 0;
                  this._validLead = -1;
                  return this._retrievedText;
                }
          
                if (this._validLead < 0)
                  return this._retrievedText;
          
                var lineCount = doc.lineCount();
                var totalLength = doc.indexFromPos({
                  line: lineCount - 1,
                  ch: doc.getLine(lineCount - 1).length
                });
          
                if (this._validLead + this._validTrail === this._retrievedText.length
                  && this._retrievedText.length === totalLength)
                  return this._retrievedText;
          
                if (this._validLead + this._validTrail < totalLength / 4) { // if more than 0.75 of the document is modified
                  this._retrievedText = doc.getValue();
                  this._validLead = -1;
                  return this._retrievedText;
                }
          
                var mid = doc.getRange(
                  doc.posFromIndex(this._validLead),
                  doc.posFromIndex(totalLength - this._validTrail));
          
                this._retrievedText =
                this._retrievedText.slice(0, this._validLead) +
                mid +
                this._retrievedText.slice(this._retrievedText.length - this._validTrail);
                this._validLead = -1;
          
          
                return this._retrievedText;
              }
          
              private _docSingleChange(docChange: CodeMirror.EditorChange) {
                var doc = this.textDoc.doc;
                if (!doc) return; // potential race conditions on deletion
          
                var newValidLead = doc.indexFromPos(docChange.from);
                var newValidTrail = this._totalLength - newValidLead - totalLength(docChange.removed);
          
                if (this._newValidLead < 0 || this._newValidLead > newValidLead)
                  this._newValidLead = newValidLead;
                if (this._newValidTrail < 0 || this._newValidTrail > newValidTrail)
                  this._newValidTrail = newValidTrail;
              }
          
              private _docChanges(docChanges: CodeMirror.EditorChange[]) {
          
                var doc = this.textDoc.doc;
          
                var lineCount = doc.lineCount();
                var newTotalLength = doc.indexFromPos({
                  line: lineCount - 1,
                  ch: doc.getLine(lineCount - 1).length
                });
          
                var changeLead = this._newValidLead;
                var changeTrail = this._newValidTrail;
          
                this._newValidLead = -1;
                this._newValidTrail = -1;
          
          
                if (this._validLead < 0) {
                  this._validLead = changeLead;
                  this._validTrail = changeTrail;
                }
                else {
                  this._validLead = Math.min(this._validLead, changeLead);
                  this._validTrail = Math.min(this._validTrail, changeTrail);
                }
          
                var changeSummary = {
                  lead: changeLead,
                  mid: this._totalLength - changeLead - changeTrail,
                  newmid: 0,
                  trail: changeTrail
                };
                changeSummary.newmid = newTotalLength - changeLead - changeTrail;
          
                this._totalLength = newTotalLength;
          
                if (this.textDoc.onChanges) {
                  this.textDoc.onChanges(docChanges, changeSummary);
                }
          
                if (this._scrollerModel)
                  this._scrollerModel.docChanges(docChanges);
          
                this._saveTimer.interval = (this.moduleObj && this.moduleObj.saveDelay) || saveDelay;
                this._saveTimer.reset();
          
              }
          
              private _cursorActivity() {
                if (!this.textDoc.editor) return; // possible race condition on document removal
                if (this.textDoc.onCursorMoved) {
                  var cursorPos = this.textDoc.doc.getCursor();
                  //this.textDoc.status.textContent = 'token '+this.textDoc.editor.getTokenAt(cursorPos).type;
                  this.textDoc.onCursorMoved(cursorPos);
                }
          
                // TODO: scroller/thickBar cursor activity
          
              }
          
              private _scroll() {
                if (!this.textDoc.editor) return; // possible race condition on document removal
          
                var scr = this.textDoc.editor.getScrollInfo();
                if (this.textDoc.onScroll)
                  this.textDoc.onScroll(scr);
          
                if (this._scrollerModel)
                  this._scrollerModel.scroll(scr);
          
              }
          
              private _save() {
                this.storage.write(this.text());
              }
          
            }
          
            function totalLength(lines: string[]): number {
              var length = 0;
              for (var i = 0; i < lines.length; i++) {
                length += lines[i].length;
              }
              if (lines.length > 1)
                length += lines.length - 1;
              return length;
            }
          }
        • api.ts
          module portabled.docs.types.text {
            
            export interface TextHandlerModule {
          
              loadText(path: string, storage: DocState): CodeMirrorTextDoc;
              
              expectsFile: RegExp;
              acceptsFile?: RegExp;
          
              createCodeMirrorEditor?: (host: HTMLElement) => CodeMirror;
              createCodeMirrorDoc?: (text: string) => CodeMirror.Doc;
              
              saveDelay?: number;
          
            }
            
            export function loadText(path: string, storage: DocState): CodeMirrorTextDoc {
              return {
                path: null,
                editor: null,
                doc: null,
                text: null,
                scroller: null,
                status: null,
                state: null,
                open: null,
                close: null,
                remove: null
              };
            }
          
            export interface CodeMirrorTextDoc {
          
              path: string;
              editor: CodeMirror;
              doc: CodeMirror.Doc;
              text: () => string;
              scroller: HTMLElement;
              status: HTMLElement;
              removed?: boolean;
          
              state: any;
          
              load?: (text: string) => void;
          
              open();
              close();
              remove();
          
              onCursorMoved?: (cursorPos: CodeMirror.Pos) => void;
              onScroll?: (scrollInfo: CodeMirror.ScrollInfo) => void;
          
              onChanges?: (
                docChanges: CodeMirror.EditorChange[],
                summary: ChangeSummary) => void;
          
              onSave?: () => void;
          
              keyMap?: any;
            }
          
            export interface ChangeSummary {
              lead: number;
              mid: number;
              newmid: number;
              trail: number;
            }
          
            export function createCodeMirrorEditor(host: HTMLElement): CodeMirror {
              return new CodeMirror(host, {
                  lineNumbers: true,
                  matchBrackets: true,
                  autoCloseBrackets: true,
                  matchTags: true,
                  showTrailingSpace: true,
                  autoCloseTags: true,
                	foldGutter: true,
              		gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
                  //highlightSelectionMatches: {showToken: /\w/},
                  styleActiveLine: true,
                  tabSize: 2
                });
            }
            
            export function createCodeMirrorDoc(text: string): CodeMirror.Doc {
              return new CodeMirror.Doc(text || '');
            }
          
          }
        • load.ts
          module portabled.docs.types.text {
          
            export var expectsFile = /.*\.txt/g;
            export var acceptsFile = /.*/g;
            
            export var saveDelay = 700;
          
            export function load(path: string, storage: DocState): DocHandler {
          
              var submodules = listSubmodules<TextHandlerModule>(portabled.docs.types.text, 'loadText');
              for (var i = 0; i < submodules.length; i++) {
          
                var match = path.match(submodules[i].moduleObj.expectsFile);
                if (match && match.length && match[0] === path) {
                  var textDoc = submodules[i].moduleObj.loadText(path, storage);
                  if (textDoc)
                    return new CodeMirrorDocHandler(path, storage, textDoc, submodules[i].moduleName, submodules[i].moduleObj);
                }
          
              }
              
              for (var i = 0; i < submodules.length; i++) {
          
                if (submodules[i].moduleObj.acceptsFile) { 
                  var match = path.match(submodules[i].moduleObj.acceptsFile);
                  if (!match || !match.length || match[0] !== path) continue;
                }
          
                var textDoc = submodules[i].moduleObj.loadText(path, storage);
                if (textDoc)
                  return new CodeMirrorDocHandler(path, storage, textDoc, submodules[i].moduleName, submodules[i].moduleObj);
              }
          
              var textDoc = portabled.docs.types.text.loadText(path, storage);
              return new CodeMirrorDocHandler(
                path, storage, textDoc,
                null, null);
              
            }
            
            
            
          
            
          }
      • api.ts
        /**
         * Add your generic document type handlers to nested modules
         * inside 'types' module.
         * Define load function in the same way load function is defined here below.
         */
        module portabled.docs.types {
        
          /**
           * Document handlers modules are expected to export these members.
           */
          export interface DocHandlerModule {
            
            load(path: string, storage: DocState): DocHandler;
            
            expectsFile: RegExp;
            acceptsFile?: RegExp;
        
          }
          
          /**
           * Default type loading.
           * Other handlers should conform to the same signature, and be on the child modules, like so:
           * module portabled.docs.types.text { function load(...); }
           */
          declare function load(path: string, storage: DocState): DocHandler;
        
          export interface DocHandler {
        
            showEditor(regions: DocHostRegions): void;
            hideEditor(): void;
        
            // TODO: implement icons like this:
            //
            // load(context: { iconText(text: string): void; iconColor(color: string): void; }): void;
        
            remove();
        
          }
        
          export interface DocHostRegions {
            content: HTMLElement;
            scroller: HTMLElement;
            status: HTMLElement;
          }
        
          
          export interface DocState {
            read(): string;
            write(content: string);
            
            readState(): any;
            writeState(state: any);
          }
        
        
        }
      • listSubmodules.ts
        module portabled.docs.types {
          
          export function listSubmodules<T>(
            parentModule: any,
            loadFunctionName: string) {
            
            var result: { moduleName: string; moduleObj: T; }[] = parentModule.__cachedSubmoduleList;
        
            if (!result) {
              result = parentModule.__cachedSubmoduleList = [];
        
              for (var moduleName in parentModule) if (parentModule.hasOwnProperty(moduleName)) {
                var moduleObj = parentModule[moduleName];
                if (moduleObj && typeof moduleObj === 'object'
                  && moduleName.charAt(0).toUpperCase() !== moduleName.charAt(0)
                  && moduleObj[loadFunctionName] && typeof moduleObj[loadFunctionName] === 'function'
                  && moduleObj.expectsFile) {
                  result.push({ moduleName: moduleName, moduleObj: moduleObj });
                }
              }
              
              parentModule.__cachedSubmoduleList = result;
            }
        
            return result;
          }
          
        }
      • load.ts
        module portabled.docs.types {
          
          export function load(path: string, storage: DocState): DocHandler {
           
            var submodules = listSubmodules<DocHandlerModule>(portabled.docs.types, 'load');
            for (var i = 0; i < submodules.length; i++) {
        
              var match = path.match(submodules[i].moduleObj.expectsFile);
              if (match && match.length && match[0] === path) {
                var docHandler = submodules[i].moduleObj.load(path, storage);
                if (docHandler)
                  return docHandler;
              }
        
            }
            
            for (var i = 0; i < submodules.length; i++) {
        
              if (submodules[i].moduleObj.acceptsFile) { 
                var match = path.match(submodules[i].moduleObj.acceptsFile);
                if (!match || !match.length || match[0] !== path) continue;
              }
        
              var docHandler = submodules[i].moduleObj.load(path, storage);
              if (docHandler)
                return docHandler;
            }
        
            return null;
          }
          
        }
    • DocHost.ts
      module portabled.docs {
        
        export class DocHost {
      
          private _docs: { [file: string]: docs.types.DocHandler; } = {};
      
          private _activeHandler: docs.types.DocHandler = null;
      
          constructor(
            private _regions: docs.types.DocHostRegions,
            private _drive: persistence.Drive) {
      
            var files = this._drive.files();
            for (var i = 0; i < files.length; i++) {
              this.add(files[i]);
            }
      
          }
        
          show(file: string) {
      
            var oldHandler = this._activeHandler;
            var oldElements: Element[] = [];
      
            if (this._regions.content) {
              for (var i = 0; i < this._regions.content.children.length; i++) {
                oldElements.push(this._regions.content.children[i]);
              }
            }
      
            if (this._regions.scroller) {
              for (var i = 0; i < this._regions.scroller.children.length; i++) {
                oldElements.push(this._regions.scroller.children[i]);
              }
            }
      
             if (this._regions.status) {
              for (var i = 0; i < this._regions.status.children.length; i++) {
                oldElements.push(this._regions.status.children[i]);
              }
            }
      
            try {
              this._activeHandler = this._docs[file];
              if (!this._activeHandler) {
      
                if (file === null)
                  return; // one of expected values here
      
                // TODO: handle unopenable file
                return;
              }
      
              this._activeHandler.showEditor(this._regions);
            }
            finally {
      
              if (oldHandler && oldHandler.hideEditor) {
                oldHandler.hideEditor();
              }
      
              for (var i = 0; i < oldElements.length; i++) {
                oldElements[i].parentNode.removeChild(oldElements[i]);
              }
      
            }
          }
      
          add(file: string) {
            var docState = new DocState(file, this._drive);
            var docHandler = docs.types.load(file, docState);
            this._docs[file] = docHandler;
          }
      
          remove(file: string) {
      
            var openAnotherFile = false;
            
            var docHandler = this._docs[file];
            if (docHandler) {
      
              openAnotherFile = true;
      
              if (this._activeHandler === docHandler) {
                this.show(null);
              }
      
              docHandler.remove();
      
              delete this._docs[file];
            }
            
            if (openAnotherFile) {
              // TODO: show another file
            }
          }
          
        }
      
        class DocState implements docs.types.DocState {
          
          constructor(private _file: string, private _drive: persistence.Drive) {
          }
      
          read(): string {
            return this._drive.read(this._file);
          }
      
          write(content: string) {
            this._drive.timestamp = Date.now ? Date.now() : +new Date();
            this._drive.write(this._file, content);
          }
          
          readState(): any {
            // TODO...
          }
      
          writeState(state: any) {
            // TODO...
          }
          
        }
        
      }
  • files
    • FileTree.css
      .portabled-file-tree {
        padding-left: 0.1em;
      }
      
      .portabled-file-tree ul {
        margin: 1px;
        margin-left: 0px;
        padding-left: 0.4em;
      }
      
      .portabled-file-tree ul li {
        margin: 0px;
        padding: 0px;
      }
      
      .portabled-file-tree li .portabled-file-name {
        padding: 1px;
        margin-left: -1em;
        padding-left: 1em;
        cursor: pointer;
        border: solid 1px transparent;
      }
      
      .portabled-file-tree ul li .portabled-file-name:hover {
        border: solid 1px gold;
      }
      
      .portabled-file-tree li .portabled-dir-name {
        padding: 1px;
        margin-left: -1em;
        padding-left: 1em;
        font-weight: bold;
        cursor: pointer;
        border: solid 1px transparent;
      }
      
      .portabled-file-tree ul li .portabled-dir-name:hover {
        border: solid 1px gold;
      }
      
      
      .portabled-file-tree li.portabled-dir {
        list-style: none;
        cursor: default;
      }
      
      .portabled-file-tree li.portabled-dir::before {
        content: "\25bc";
      }
      
      .portabled-file-tree li.portabled-dir-collapsed::before {
        content: "\25ba";
      }
      
      .portabled-file-tree .portabled-dir-collapsed ul {
        display: none;
      }
      
      
      
      .portabled-file-tree li.portabled-file {
        list-style: none;
      }
      
      .portabled-file-tree li.portabled-file::before {
        content: "\25a1";
        padding-right: 0.2em;
      }
      
      .portabled-file-tree .portabled-file-selected .portabled-file-name {
        background: cornflowerblue;
        background: rgba(100,149,237,0.5);
      }
      
      
      .portabled-file-content {
        display: none;
      }
      
    • FileTree.ts
      module portabled.files {
        
        export class FileTree implements persistence.Drive {
      
          private _virtualRoot: Node;
          private _allFiles: { [file: string]: Node; } = {};
          private _selectedFileNode = ko.observable<Node>(null);
      
          selectedFile = ko.computed<string>({
            read: () => {
              var n = this._selectedFileNode();
              return n ? n.fullPath : null;
            },
            write: (value) => {
              var node = this._allFiles[value] || null;
              if (node || value === null || value === undefined)
                this._selectFileNode(node);
            }
          });
          
          timestamp: number = 0;
      
          constructor(private _host: HTMLElement) {
      
            var domSelection = { selectedFile: null };
            this._virtualRoot = new Node(null, <any>this._host, this._allFiles, domSelection);
            
            if (domSelection.selectedFile)
              this.selectedFile(domSelection.selectedFile);
            
            try {
              var timestamStr = this._virtualRoot.readAttr('timestamp');
              this.timestamp = timestamStr ? parseInt(timestamStr) : 0;
            }
            catch (parseError) {
              this.timestamp = 0;
            }
      
            addEventListener(this._host, 'click', e => this._onClick(<any>e));
          }
      
          files(): string[] {
            return objectKeys(this._allFiles);
          }
      
          read(file: string): string {
            var n = this._allFiles[file];
            if (n)
              return n.read();
            else
              return null;
          }
      
          write(file: string, content: string) {
            var n = this._allFiles[file];
            if (!n) {
              file = normalizePath(file);
              n = this._allFiles[file];
            }
      
            if (n) {
              if (content || typeof content === 'string') {
                n.write(content);
              }
              else {
                n.parent.remove(n);
                delete this._allFiles[file];
              }
            }
            else {
              if (!content && typeof content !== 'string')
                return;
      
              var newFile = this._createFile(file);
              newFile.write(content);
            }
            
            this._virtualRoot.writeAttr('timestamp', this.timestamp + '');
          }
          
          private _createFile(file: string): Node {
            var lastSlashPos = file.lastIndexOf('/');
            if (lastSlashPos) { // slash in position other than lead
              var parentDir = file.slice(1, lastSlashPos);
              var fileName = file = file.slice(lastSlashPos + 1);
              var parent = this._virtualRoot.findOrCreateDir(parentDir);
              var node = parent.createFile(fileName);
              this._allFiles[node.fullPath] = node;
              return node;
            }
            else { 
              var node = this._virtualRoot.createFile(file.slice(1));
              this._allFiles[node.fullPath] = node;
              return node;
            }
          }
          
          private _onClick(e: MouseEvent) {
            var node = this._getNode(<any>e.target || <any>e.srcElement);
            if (!node) return;
            if (node === this._virtualRoot) return;
            
            if (node.isDir) {
              node.toggleCollapse();
            }
            else {
              this._selectFileNode(node);
            }
            
          }
          
          private _selectFileNode(node: Node) {
            var oldSelected = this._selectedFileNode();
            if (oldSelected) {
              oldSelected.setSelectClass(false);
            }
            
            if (node)
              node.setSelectClass(true);
            
            this._selectedFileNode(node);
          }
          
          private _getNode(elem: HTMLElement): Node {
            while (elem) {
              var node = (<any>elem)._portabled_node;
              if (node) return node;
              elem = elem.parentElement;
              if (!elem)
                return null;
            }
          }
      
        }
      
        class Node {
      
          isDir: boolean = false;
          name: string = null;
          fullPath: string = null;
      
          private _contentPRE: HTMLPreElement = null;
          private _subDirs: Node[] = [];
          private _files: Node[] = [];
          private _ul: HTMLUListElement = null;
          
          constructor(
            public parent: Node,
            public li: HTMLElement,
            allFiles: { [file: string]: Node; },
            selection: { selectedFile: string; }) {
              
            (<any>li)._portabled_node = this;
            
            var childLIs: HTMLLIElement[] = [];
            for (var i = 0; i < this.li.children.length; i++) {
      
              var child = this.li.children[i];
              if ((<HTMLLIElement>child).tagName === 'LI') childLIs.push(<HTMLLIElement>child);
              if ((<HTMLUListElement>child).tagName === 'UL') {
                this._ul = <HTMLUListElement>child;
                for (var j = 0; j < this._ul.children.length; j++) {
                  var ulLI = <HTMLLIElement>this._ul.children[j];
                  if (ulLI.tagName === 'LI') childLIs.push(ulLI);
                }
              }
              
      
              if (((<HTMLDivElement>child).tagName === 'DIV' || (<HTMLDivElement>child).tagName === 'SPAN') && (<HTMLDivElement>child).className) {
                if ((<HTMLDivElement>child).className.indexOf('portabled-file-name') >= 0) {
                  this.isDir = false;
                  this.name = child.textContent || (<HTMLDivElement>child).innerText;
                }
                else if ((<HTMLDivElement>child).className.indexOf('portabled-dir-name') >= 0) {
                  this.isDir = true;
                  this.name = child.textContent || (<HTMLDivElement>child).innerText;
                }
              }
      
              if ((<HTMLPreElement>child).tagName === 'PRE' && (<HTMLPreElement>child).className 
                && (<HTMLPreElement>child).className.indexOf('portabled-file-content') >= 0) {
                
                if (this._contentPRE) {
                  // double content?
                }
                else {
                  this._contentPRE = <HTMLPreElement>child;
                }
                
              }
      
            }
            
            if (this.parent) {
              this.fullPath = this.parent.fullPath + '/' + this.name;
            }
            else { 
              this.name = '';
              this.fullPath = '';
            }
            
            if (selection) {
              if (li.className.indexOf('portabled-file-selected') >= 0) {
                if (selection.selectedFile)
                  li.className = li.className.replace(/portabled\-file\-selected/g, '');
                else
                  selection.selectedFile = this.fullPath;
              }
            }
            else { 
              if (li.className.indexOf('portabled-file-selected') >= 0)
                li.className = li.className.replace(/portabled\-file\-selected/g, '');
            }
      
            if (allFiles)
              this._createChildNodesAndSort(childLIs, allFiles, selection);
      
          }
      
          read(): string {
            if (this.isDir)
              return null; // DEBUG
      
            return readNodeFileContent(this._contentPRE);
          }
      
          write(content: string) {
            if (this.isDir)
              return; // DEBUG
      
            if (!this._contentPRE) {
              this._contentPRE = document.createElement('pre');
              this._contentPRE.className = 'portabled-file-content';
              this.li.appendChild(this._contentPRE);
            }
            
            this._contentPRE.textContent = content || '';
          }
        
          readAttr(prop: string) {
            if (this.li)
              return this.li.getAttribute(getSafeAttributeName(prop));
            else
              return this._ul.getAttribute(getSafeAttributeName(prop));      
          }
        
          writeAttr(prop: string, value: string) {
            if (value === null || value === undefined) {
              if (this.li)
                this.li.removeAttribute(getSafeAttributeName(prop));
              else
                this._ul.removeAttribute(getSafeAttributeName(prop));      
            }
            else {
              if (this.li)
                this.li.setAttribute(getSafeAttributeName(prop), value);
              else
                this._ul.setAttribute(getSafeAttributeName(prop), value);
            }
          }
        
          remove(childNode: Node) {
            var nodeList = childNode.isDir ? this._subDirs : this._files;
            var index = nodeList.indexOf(childNode);
            nodeList.splice(index, 1);
            this._ul.removeChild(childNode.li);
            
            if (!this.parent || this._files.length + this._subDirs.length)
              return;
      
            this.parent.remove(this);
          }
      
          findOrCreateDir(relativePath: string): Node {
            
            var slashPos = relativePath.indexOf('/');
            var subdirName = slashPos > 0 ? relativePath.slice(0, slashPos) : relativePath;
            var restPath = slashPos > 0 ? relativePath.slice(slashPos + 1) : null;
            
            var matchIndex = this._binarySearchNode(subdirName, this._subDirs);
            var subdir: Node;
            if (matchIndex >= 0) {
              subdir = this._subDirs[matchIndex];
            }
            else {
              //return this._subDirs[matchIndex];
              var insertIndex = -matchIndex - 100;
      
              var newLI = document.createElement('li');
              newLI.className = 'portabled-dir';
              var fnameDIV = document.createElement('span');
              fnameDIV.className = 'portabled-dir-name';
              if ('textContent' in fnameDIV)
                fnameDIV.textContent = subdirName;
              else
                fnameDIV.innerText = subdirName;
              newLI.appendChild(fnameDIV);
              var ul = document.createElement('ul');
              newLI.appendChild(ul);
              subdir = new Node(this, newLI, /*allFiles*/ null, /*selection*/ null);
              
              var insertSibling =
                insertIndex < this._subDirs.length ? this._subDirs[insertIndex].li    :
                this._files.length ? this._files[0].li :
                null;
              
              this._subDirs.splice(insertIndex, 0, subdir);
              if (!this._ul) {
                this._ul = document.createElement('ul');
                this.li.appendChild(this._ul);
              }
      
              this._ul.insertBefore(subdir.li, insertSibling);
            }
            
            if (restPath)
              return subdir.findOrCreateDir(restPath);
            else
              return subdir;
          }
        
          createFile(fileName: string): Node {
            var newLI = document.createElement('li');
            newLI.className = 'portabled-file';
            var fnameDIV = document.createElement('span');
            fnameDIV.className = 'portabled-file-name';
            if ('textContent' in fnameDIV)
              fnameDIV.textContent = fileName;
            else
              fnameDIV.innerText = fileName;
              
            newLI.appendChild(fnameDIV);
            var newNode = new Node(this, newLI, /*allFiles*/ null, /*selection*/ null);
            this._insertChildNode(
              this._files,
              newNode,
                /*forceRerootingEvenIfOrdered*/ true,
                /*insertBeforeElement*/null);
            return newNode;
          }
        
          toggleCollapse() {
            if (this.li.className && this.li.className.indexOf('portabled-dir-collapsed') >= 0) {
              this.li.className = this.li.className.replace(/portabled\-dir\-collapsed/g, '');
            }
            else { 
              this.li.className = (this.li.className || '') + ' portabled-dir-collapsed';
            }
          }
        
          setSelectClass(selected: boolean) {
            if (selected) {
              this.li.className = (this.li.className || '') + ' portabled-file-selected';
            }
            else { 
              this.li.className = this.li.className ? this.li.className.replace(/portabled\-file\-selected/g, '') : null;
            }
          }
      
          private _createChildNodesAndSort(
            childLIs: HTMLLIElement[],
            allFiles: { [file: string]: Node; },
            selection: { selectedFile: string; }) {
            
            for (var i = 0; i < childLIs.length; i++) {
              var node = new Node(this, childLIs[i], allFiles, selection);
              
              if (node.isDir) {
                this._insertChildNode(
                  this._subDirs, node,
                  /*forceRerootingEvenIfOrdered*/ <any>this._files.length,
                  this._files.length ? this._files[0].li : node.li);
              }
              else {
                allFiles[node.fullPath] = node;
                this._insertChildNode(
                  this._files, node,
                  /*forceRerootingEvenIfOrdered*/ false,
                  node.li);
              }
            }
            
          }
      
          private _insertChildNode(
            nodeList: Node[],
            node: Node,
            forceRerootingEvenIfOrdered: boolean,
            insertBeforeElement: HTMLElement) {
            
            var insertIndex = this._binarySearchNode(node.name, nodeList);
            if (insertIndex >= 0)
              alert('Node should not exist: we are inserting it.');
      
            insertIndex = -insertIndex - 100;
            
            if (insertIndex >= nodeList.length) {      
              nodeList.push(node);
              if (forceRerootingEvenIfOrdered)
                this._ul.insertBefore(node.li, insertBeforeElement);
              return;
            }
      
            this._ul.insertBefore(node.li, nodeList[insertIndex].li);
            nodeList.splice(insertIndex, 0, node);
            
          }
        
          /** returns match index, or (-100 - insertionIndex) */
          private _binarySearchNode(name: string, list: Node[]): number {
            if (!list.length)
              return -100;
            
            if (name > list[list.length - 1].name)
              return -100 - list.length;
            if (name == list[list.length - 1].name)
              return list.length - 1;
            
            if (name < list[0].name)
              return -100;
            if (name === list[0].name)
              return 0;
            
            var rangeStart = 1;
            var rangeLength = list.length - 2;
            while (true) {
              if (!rangeLength)
                return -100 - rangeStart;
      
              var mid = rangeStart + (rangeLength >> 1);
              if (name === list[mid].name)
                return mid;
      
              if (name < list[mid].name) {
                rangeLength = mid - rangeStart;
              }
              else {
                rangeLength -= mid - rangeStart + 1;
                rangeStart = mid + 1;
              }
            }
          }
      
        }
      
        export function normalizePath(path: string) : string {
      
          if (!path) return '/'; // empty paths converted to root
      
          while (' \n\t\r'.indexOf(path.charAt(0))>=0) // removing leading whitespace
            path = path.slice(1);
      
          while ('\n\t\r\\'.indexOf(path.charAt(path.length - 1))>=0) // removing trailing whitespace and trailing slashes
            path = path.slice(0, path.length - 1);
      
          if (path.charAt(0) !== '/') // ensuring leading slash
            path = '/' + path;
      
          path = path.replace(/\/\/*/g, '/'); // replacing duplicate slashes with single
      
          return path;
        }
      
        export function getSafeAttributeName(caseSensitiveName: string): string {
          if (caseSensitiveName.toLowerCase() === caseSensitiveName
             && caseSensitiveName.indexOf('^')<0)
            return caseSensitiveName;
          var result: string[] = [];
          for (var i = 0; i < caseSensitiveName.length; i++) {
            var c = caseSensitiveName.charAt(i);
            if (c === '^' || c.toLowerCase() !== c)
              result.push('^');
      
            result.push(c);
          }
          return result.join('');
        }
      
      	export function readNodeFileContent(node: HTMLElement) {
          return node ? node.textContent || (node.innerText ? node.innerText.replace(/\r\n/g, '\n') : '') : '';
        }
      
      }
  • imports
    • codemirror
      • addon
        • comment
          • comment.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var noOptions = {};
              var nonWS = /[^\s\u00a0]/;
              var Pos = CodeMirror.Pos;
            
              function firstNonWS(str) {
                var found = str.search(nonWS);
                return found == -1 ? 0 : found;
              }
            
              CodeMirror.commands.toggleComment = function(cm) {
                var minLine = Infinity, ranges = cm.listSelections(), mode = null;
                for (var i = ranges.length - 1; i >= 0; i--) {
                  var from = ranges[i].from(), to = ranges[i].to();
                  if (from.line >= minLine) continue;
                  if (to.line >= minLine) to = Pos(minLine, 0);
                  minLine = from.line;
                  if (mode == null) {
                    if (cm.uncomment(from, to)) mode = "un";
                    else { cm.lineComment(from, to); mode = "line"; }
                  } else if (mode == "un") {
                    cm.uncomment(from, to);
                  } else {
                    cm.lineComment(from, to);
                  }
                }
              };
            
              CodeMirror.defineExtension("lineComment", function(from, to, options) {
                if (!options) options = noOptions;
                var self = this, mode = self.getModeAt(from);
                var commentString = options.lineComment || mode.lineComment;
                if (!commentString) {
                  if (options.blockCommentStart || mode.blockCommentStart) {
                    options.fullLines = true;
                    self.blockComment(from, to, options);
                  }
                  return;
                }
                var firstLine = self.getLine(from.line);
                if (firstLine == null) return;
                var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1);
                var pad = options.padding == null ? " " : options.padding;
                var blankLines = options.commentBlankLines || from.line == to.line;
            
                self.operation(function() {
                  if (options.indent) {
                    var baseString = firstLine.slice(0, firstNonWS(firstLine));
                    for (var i = from.line; i < end; ++i) {
                      var line = self.getLine(i), cut = baseString.length;
                      if (!blankLines && !nonWS.test(line)) continue;
                      if (line.slice(0, cut) != baseString) cut = firstNonWS(line);
                      self.replaceRange(baseString + commentString + pad, Pos(i, 0), Pos(i, cut));
                    }
                  } else {
                    for (var i = from.line; i < end; ++i) {
                      if (blankLines || nonWS.test(self.getLine(i)))
                        self.replaceRange(commentString + pad, Pos(i, 0));
                    }
                  }
                });
              });
            
              CodeMirror.defineExtension("blockComment", function(from, to, options) {
                if (!options) options = noOptions;
                var self = this, mode = self.getModeAt(from);
                var startString = options.blockCommentStart || mode.blockCommentStart;
                var endString = options.blockCommentEnd || mode.blockCommentEnd;
                if (!startString || !endString) {
                  if ((options.lineComment || mode.lineComment) && options.fullLines != false)
                    self.lineComment(from, to, options);
                  return;
                }
            
                var end = Math.min(to.line, self.lastLine());
                if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end;
            
                var pad = options.padding == null ? " " : options.padding;
                if (from.line > end) return;
            
                self.operation(function() {
                  if (options.fullLines != false) {
                    var lastLineHasText = nonWS.test(self.getLine(end));
                    self.replaceRange(pad + endString, Pos(end));
                    self.replaceRange(startString + pad, Pos(from.line, 0));
                    var lead = options.blockCommentLead || mode.blockCommentLead;
                    if (lead != null) for (var i = from.line + 1; i <= end; ++i)
                      if (i != end || lastLineHasText)
                        self.replaceRange(lead + pad, Pos(i, 0));
                  } else {
                    self.replaceRange(endString, to);
                    self.replaceRange(startString, from);
                  }
                });
              });
            
              CodeMirror.defineExtension("uncomment", function(from, to, options) {
                if (!options) options = noOptions;
                var self = this, mode = self.getModeAt(from);
                var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);
            
                // Try finding line comments
                var lineString = options.lineComment || mode.lineComment, lines = [];
                var pad = options.padding == null ? " " : options.padding, didSomething;
                lineComment: {
                  if (!lineString) break lineComment;
                  for (var i = start; i <= end; ++i) {
                    var line = self.getLine(i);
                    var found = line.indexOf(lineString);
                    if (found > -1 && !/comment/.test(self.getTokenTypeAt(Pos(i, found + 1)))) found = -1;
                    if (found == -1 && (i != end || i == start) && nonWS.test(line)) break lineComment;
                    if (found > -1 && nonWS.test(line.slice(0, found))) break lineComment;
                    lines.push(line);
                  }
                  self.operation(function() {
                    for (var i = start; i <= end; ++i) {
                      var line = lines[i - start];
                      var pos = line.indexOf(lineString), endPos = pos + lineString.length;
                      if (pos < 0) continue;
                      if (line.slice(endPos, endPos + pad.length) == pad) endPos += pad.length;
                      didSomething = true;
                      self.replaceRange("", Pos(i, pos), Pos(i, endPos));
                    }
                  });
                  if (didSomething) return true;
                }
            
                // Try block comments
                var startString = options.blockCommentStart || mode.blockCommentStart;
                var endString = options.blockCommentEnd || mode.blockCommentEnd;
                if (!startString || !endString) return false;
                var lead = options.blockCommentLead || mode.blockCommentLead;
                var startLine = self.getLine(start), endLine = end == start ? startLine : self.getLine(end);
                var open = startLine.indexOf(startString), close = endLine.lastIndexOf(endString);
                if (close == -1 && start != end) {
                  endLine = self.getLine(--end);
                  close = endLine.lastIndexOf(endString);
                }
                if (open == -1 || close == -1 ||
                    !/comment/.test(self.getTokenTypeAt(Pos(start, open + 1))) ||
                    !/comment/.test(self.getTokenTypeAt(Pos(end, close + 1))))
                  return false;
            
                // Avoid killing block comments completely outside the selection.
                // Positions of the last startString before the start of the selection, and the first endString after it.
                var lastStart = startLine.lastIndexOf(startString, from.ch);
                var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length);
                if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false;
                // Positions of the first endString after the end of the selection, and the last startString before it.
                firstEnd = endLine.indexOf(endString, to.ch);
                var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch);
                lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart;
                if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false;
            
                self.operation(function() {
                  self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)),
                                    Pos(end, close + endString.length));
                  var openEnd = open + startString.length;
                  if (pad && startLine.slice(openEnd, openEnd + pad.length) == pad) openEnd += pad.length;
                  self.replaceRange("", Pos(start, open), Pos(start, openEnd));
                  if (lead) for (var i = start + 1; i <= end; ++i) {
                    var line = self.getLine(i), found = line.indexOf(lead);
                    if (found == -1 || nonWS.test(line.slice(0, found))) continue;
                    var foundEnd = found + lead.length;
                    if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length;
                    self.replaceRange("", Pos(i, found), Pos(i, foundEnd));
                  }
                });
                return true;
              });
            });
            
          • continuecomment.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              var modes = ["clike", "css", "javascript"];
            
              for (var i = 0; i < modes.length; ++i)
                CodeMirror.extendMode(modes[i], {blockCommentContinue: " * "});
            
              function continueComment(cm) {
                if (cm.getOption("disableInput")) return CodeMirror.Pass;
                var ranges = cm.listSelections(), mode, inserts = [];
                for (var i = 0; i < ranges.length; i++) {
                  var pos = ranges[i].head, token = cm.getTokenAt(pos);
                  if (token.type != "comment") return CodeMirror.Pass;
                  var modeHere = CodeMirror.innerMode(cm.getMode(), token.state).mode;
                  if (!mode) mode = modeHere;
                  else if (mode != modeHere) return CodeMirror.Pass;
            
                  var insert = null;
                  if (mode.blockCommentStart && mode.blockCommentContinue) {
                    var end = token.string.indexOf(mode.blockCommentEnd);
                    var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found;
                    if (end != -1 && end == token.string.length - mode.blockCommentEnd.length && pos.ch >= end) {
                      // Comment ended, don't continue it
                    } else if (token.string.indexOf(mode.blockCommentStart) == 0) {
                      insert = full.slice(0, token.start);
                      if (!/^\s*$/.test(insert)) {
                        insert = "";
                        for (var j = 0; j < token.start; ++j) insert += " ";
                      }
                    } else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 &&
                               found + mode.blockCommentContinue.length > token.start &&
                               /^\s*$/.test(full.slice(0, found))) {
                      insert = full.slice(0, found);
                    }
                    if (insert != null) insert += mode.blockCommentContinue;
                  }
                  if (insert == null && mode.lineComment && continueLineCommentEnabled(cm)) {
                    var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment);
                    if (found > -1) {
                      insert = line.slice(0, found);
                      if (/\S/.test(insert)) insert = null;
                      else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\s*/)[0];
                    }
                  }
                  if (insert == null) return CodeMirror.Pass;
                  inserts[i] = "\n" + insert;
                }
            
                cm.operation(function() {
                  for (var i = ranges.length - 1; i >= 0; i--)
                    cm.replaceRange(inserts[i], ranges[i].from(), ranges[i].to(), "+insert");
                });
              }
            
              function continueLineCommentEnabled(cm) {
                var opt = cm.getOption("continueComments");
                if (opt && typeof opt == "object")
                  return opt.continueLineComment !== false;
                return true;
              }
            
              CodeMirror.defineOption("continueComments", null, function(cm, val, prev) {
                if (prev && prev != CodeMirror.Init)
                  cm.removeKeyMap("continueComment");
                if (val) {
                  var key = "Enter";
                  if (typeof val == "string")
                    key = val;
                  else if (typeof val == "object" && val.key)
                    key = val.key;
                  var map = {name: "continueComment"};
                  map[key] = continueComment;
                  cm.addKeyMap(map);
                }
              });
            });
            
        • dialog
          • dialog.css
            .CodeMirror-dialog {
              position: absolute;
              left: 0; right: 0;
              background: inherit;
              z-index: 15;
              padding: .1em .8em;
              overflow: hidden;
              color: inherit;
            }
            
            .CodeMirror-dialog-top {
              border-bottom: 1px solid #eee;
              top: 0;
            }
            
            .CodeMirror-dialog-bottom {
              border-top: 1px solid #eee;
              bottom: 0;
            }
            
            .CodeMirror-dialog input {
              border: none;
              outline: none;
              background: transparent;
              width: 20em;
              color: inherit;
              font-family: monospace;
            }
            
            .CodeMirror-dialog button {
              font-size: 70%;
            }
            
          • dialog.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Open simple dialogs on top of an editor. Relies on dialog.css.
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              function dialogDiv(cm, template, bottom) {
                var wrap = cm.getWrapperElement();
                var dialog;
                dialog = wrap.appendChild(document.createElement("div"));
                if (bottom)
                  dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
                else
                  dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
            
                if (typeof template == "string") {
                  dialog.innerHTML = template;
                } else { // Assuming it's a detached DOM element.
                  dialog.appendChild(template);
                }
                return dialog;
              }
            
              function closeNotification(cm, newVal) {
                if (cm.state.currentNotificationClose)
                  cm.state.currentNotificationClose();
                cm.state.currentNotificationClose = newVal;
              }
            
              CodeMirror.defineExtension("openDialog", function(template, callback, options) {
                if (!options) options = {};
            
                closeNotification(this, null);
            
                var dialog = dialogDiv(this, template, options.bottom);
                var closed = false, me = this;
                function close(newVal) {
                  if (typeof newVal == 'string') {
                    inp.value = newVal;
                  } else {
                    if (closed) return;
                    closed = true;
                    dialog.parentNode.removeChild(dialog);
                    me.focus();
            
                    if (options.onClose) options.onClose(dialog);
                  }
                }
            
                var inp = dialog.getElementsByTagName("input")[0], button;
                if (inp) {
                  if (options.value) {
                    inp.value = options.value;
                    if (options.selectValueOnOpen !== false) {
                      inp.select();
                    }
                  }
            
                  if (options.onInput)
                    CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);});
                  if (options.onKeyUp)
                    CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
            
                  CodeMirror.on(inp, "keydown", function(e) {
                    if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
                    if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) {
                      inp.blur();
                      CodeMirror.e_stop(e);
                      close();
                    }
                    if (e.keyCode == 13) callback(inp.value, e);
                  });
            
                  if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
            
                  inp.focus();
                } else if (button = dialog.getElementsByTagName("button")[0]) {
                  CodeMirror.on(button, "click", function() {
                    close();
                    me.focus();
                  });
            
                  if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close);
            
                  button.focus();
                }
                return close;
              });
            
              CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) {
                closeNotification(this, null);
                var dialog = dialogDiv(this, template, options && options.bottom);
                var buttons = dialog.getElementsByTagName("button");
                var closed = false, me = this, blurring = 1;
                function close() {
                  if (closed) return;
                  closed = true;
                  dialog.parentNode.removeChild(dialog);
                  me.focus();
                }
                buttons[0].focus();
                for (var i = 0; i < buttons.length; ++i) {
                  var b = buttons[i];
                  (function(callback) {
                    CodeMirror.on(b, "click", function(e) {
                      CodeMirror.e_preventDefault(e);
                      close();
                      if (callback) callback(me);
                    });
                  })(callbacks[i]);
                  CodeMirror.on(b, "blur", function() {
                    --blurring;
                    setTimeout(function() { if (blurring <= 0) close(); }, 200);
                  });
                  CodeMirror.on(b, "focus", function() { ++blurring; });
                }
              });
            
              /*
               * openNotification
               * Opens a notification, that can be closed with an optional timer
               * (default 5000ms timer) and always closes on click.
               *
               * If a notification is opened while another is opened, it will close the
               * currently opened one and open the new one immediately.
               */
              CodeMirror.defineExtension("openNotification", function(template, options) {
                closeNotification(this, close);
                var dialog = dialogDiv(this, template, options && options.bottom);
                var closed = false, doneTimer;
                var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000;
            
                function close() {
                  if (closed) return;
                  closed = true;
                  clearTimeout(doneTimer);
                  dialog.parentNode.removeChild(dialog);
                }
            
                CodeMirror.on(dialog, 'click', function(e) {
                  CodeMirror.e_preventDefault(e);
                  close();
                });
            
                if (duration)
                  doneTimer = setTimeout(close, duration);
            
                return close;
              });
            });
            
        • display
          • fullscreen.css
            .CodeMirror-fullscreen {
              position: fixed;
              top: 0; left: 0; right: 0; bottom: 0;
              height: auto;
              z-index: 9;
            }
            
          • fullscreen.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("fullScreen", false, function(cm, val, old) {
                if (old == CodeMirror.Init) old = false;
                if (!old == !val) return;
                if (val) setFullscreen(cm);
                else setNormal(cm);
              });
            
              function setFullscreen(cm) {
                var wrap = cm.getWrapperElement();
                cm.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset,
                                              width: wrap.style.width, height: wrap.style.height};
                wrap.style.width = "";
                wrap.style.height = "auto";
                wrap.className += " CodeMirror-fullscreen";
                document.documentElement.style.overflow = "hidden";
                cm.refresh();
              }
            
              function setNormal(cm) {
                var wrap = cm.getWrapperElement();
                wrap.className = wrap.className.replace(/\s*CodeMirror-fullscreen\b/, "");
                document.documentElement.style.overflow = "";
                var info = cm.state.fullScreenRestore;
                wrap.style.width = info.width; wrap.style.height = info.height;
                window.scrollTo(info.scrollLeft, info.scrollTop);
                cm.refresh();
              }
            });
            
          • panel.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              CodeMirror.defineExtension("addPanel", function(node, options) {
                options = options || {};
            
                if (!this.state.panels) initPanels(this);
            
                var info = this.state.panels;
                var wrapper = info.wrapper;
                var cmWrapper = this.getWrapperElement();
            
                if (options.after instanceof Panel && !options.after.cleared) {
                  wrapper.insertBefore(node, options.before.node.nextSibling);
                } else if (options.before instanceof Panel && !options.before.cleared) {
                  wrapper.insertBefore(node, options.before.node);
                } else if (options.replace instanceof Panel && !options.replace.cleared) {
                  wrapper.insertBefore(node, options.replace.node);
                  options.replace.clear();
                } else if (options.position == "bottom") {
                  wrapper.appendChild(node);
                } else if (options.position == "before-bottom") {
                  wrapper.insertBefore(node, cmWrapper.nextSibling);
                } else if (options.position == "after-top") {
                  wrapper.insertBefore(node, cmWrapper);
                } else {
                  wrapper.insertBefore(node, wrapper.firstChild);
                }
            
                var height = (options && options.height) || node.offsetHeight;
                this._setSize(null, info.heightLeft -= height);
                info.panels++;
                return new Panel(this, node, options, height);
              });
            
              function Panel(cm, node, options, height) {
                this.cm = cm;
                this.node = node;
                this.options = options;
                this.height = height;
                this.cleared = false;
              }
            
              Panel.prototype.clear = function() {
                if (this.cleared) return;
                this.cleared = true;
                var info = this.cm.state.panels;
                this.cm._setSize(null, info.heightLeft += this.height);
                info.wrapper.removeChild(this.node);
                if (--info.panels == 0) removePanels(this.cm);
              };
            
              Panel.prototype.changed = function(height) {
                var newHeight = height == null ? this.node.offsetHeight : height;
                var info = this.cm.state.panels;
                this.cm._setSize(null, info.height += (newHeight - this.height));
                this.height = newHeight;
              };
            
              function initPanels(cm) {
                var wrap = cm.getWrapperElement();
                var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle;
                var height = parseInt(style.height);
                var info = cm.state.panels = {
                  setHeight: wrap.style.height,
                  heightLeft: height,
                  panels: 0,
                  wrapper: document.createElement("div")
                };
                wrap.parentNode.insertBefore(info.wrapper, wrap);
                var hasFocus = cm.hasFocus();
                info.wrapper.appendChild(wrap);
                if (hasFocus) cm.focus();
            
                cm._setSize = cm.setSize;
                if (height != null) cm.setSize = function(width, newHeight) {
                  if (newHeight == null) return this._setSize(width, newHeight);
                  info.setHeight = newHeight;
                  if (typeof newHeight != "number") {
                    var px = /^(\d+\.?\d*)px$/.exec(newHeight);
                    if (px) {
                      newHeight = Number(px[1]);
                    } else {
                      info.wrapper.style.height = newHeight;
                      newHeight = info.wrapper.offsetHeight;
                      info.wrapper.style.height = "";
                    }
                  }
                  cm._setSize(width, info.heightLeft += (newHeight - height));
                  height = newHeight;
                };
              }
            
              function removePanels(cm) {
                var info = cm.state.panels;
                cm.state.panels = null;
            
                var wrap = cm.getWrapperElement();
                info.wrapper.parentNode.replaceChild(wrap, info.wrapper);
                wrap.style.height = info.setHeight;
                cm.setSize = cm._setSize;
                cm.setSize();
              }
            });
            
          • placeholder.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              CodeMirror.defineOption("placeholder", "", function(cm, val, old) {
                var prev = old && old != CodeMirror.Init;
                if (val && !prev) {
                  cm.on("blur", onBlur);
                  cm.on("change", onChange);
                  onChange(cm);
                } else if (!val && prev) {
                  cm.off("blur", onBlur);
                  cm.off("change", onChange);
                  clearPlaceholder(cm);
                  var wrapper = cm.getWrapperElement();
                  wrapper.className = wrapper.className.replace(" CodeMirror-empty", "");
                }
            
                if (val && !cm.hasFocus()) onBlur(cm);
              });
            
              function clearPlaceholder(cm) {
                if (cm.state.placeholder) {
                  cm.state.placeholder.parentNode.removeChild(cm.state.placeholder);
                  cm.state.placeholder = null;
                }
              }
              function setPlaceholder(cm) {
                clearPlaceholder(cm);
                var elt = cm.state.placeholder = document.createElement("pre");
                elt.style.cssText = "height: 0; overflow: visible";
                elt.className = "CodeMirror-placeholder";
                elt.appendChild(document.createTextNode(cm.getOption("placeholder")));
                cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
              }
            
              function onBlur(cm) {
                if (isEmpty(cm)) setPlaceholder(cm);
              }
              function onChange(cm) {
                var wrapper = cm.getWrapperElement(), empty = isEmpty(cm);
                wrapper.className = wrapper.className.replace(" CodeMirror-empty", "") + (empty ? " CodeMirror-empty" : "");
            
                if (empty) setPlaceholder(cm);
                else clearPlaceholder(cm);
              }
            
              function isEmpty(cm) {
                return (cm.lineCount() === 1) && (cm.getLine(0) === "");
              }
            });
            
          • rulers.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("rulers", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init) {
                  clearRulers(cm);
                  cm.off("refresh", refreshRulers);
                }
                if (val && val.length) {
                  setRulers(cm);
                  cm.on("refresh", refreshRulers);
                }
              });
            
              function clearRulers(cm) {
                for (var i = cm.display.lineSpace.childNodes.length - 1; i >= 0; i--) {
                  var node = cm.display.lineSpace.childNodes[i];
                  if (/(^|\s)CodeMirror-ruler($|\s)/.test(node.className))
                    node.parentNode.removeChild(node);
                }
              }
            
              function setRulers(cm) {
                var val = cm.getOption("rulers");
                var cw = cm.defaultCharWidth();
                var left = cm.charCoords(CodeMirror.Pos(cm.firstLine(), 0), "div").left;
                var minH = cm.display.scroller.offsetHeight + 30;
                for (var i = 0; i < val.length; i++) {
                  var elt = document.createElement("div");
                  elt.className = "CodeMirror-ruler";
                  var col, conf = val[i];
                  if (typeof conf == "number") {
                    col = conf;
                  } else {
                    col = conf.column;
                    if (conf.className) elt.className += " " + conf.className;
                    if (conf.color) elt.style.borderColor = conf.color;
                    if (conf.lineStyle) elt.style.borderLeftStyle = conf.lineStyle;
                    if (conf.width) elt.style.borderLeftWidth = conf.width;
                  }
                  elt.style.left = (left + col * cw) + "px";
                  elt.style.top = "-50px";
                  elt.style.bottom = "-20px";
                  elt.style.minHeight = minH + "px";
                  cm.display.lineSpace.insertBefore(elt, cm.display.cursorDiv);
                }
              }
            
              function refreshRulers(cm) {
                clearRulers(cm);
                setRulers(cm);
              }
            });
            
        • edit
          • closebrackets.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              var defaults = {
                pairs: "()[]{}''\"\"",
                triples: "",
                explode: "[]{}"
              };
            
              var Pos = CodeMirror.Pos;
            
              CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init) {
                  cm.removeKeyMap(keyMap);
                  cm.state.closeBrackets = null;
                }
                if (val) {
                  cm.state.closeBrackets = val;
                  cm.addKeyMap(keyMap);
                }
              });
            
              function getOption(conf, name) {
                if (name == "pairs" && typeof conf == "string") return conf;
                if (typeof conf == "object" && conf[name] != null) return conf[name];
                return defaults[name];
              }
            
              var bind = defaults.pairs + "`";
              var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
              for (var i = 0; i < bind.length; i++)
                keyMap["'" + bind.charAt(i) + "'"] = handler(bind.charAt(i));
            
              function handler(ch) {
                return function(cm) { return handleChar(cm, ch); };
              }
            
              function getConfig(cm) {
                var deflt = cm.state.closeBrackets;
                if (!deflt) return null;
                var mode = cm.getModeAt(cm.getCursor());
                return mode.closeBrackets || deflt;
              }
            
              function handleBackspace(cm) {
                var conf = getConfig(cm);
                if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
            
                var pairs = getOption(conf, "pairs");
                var ranges = cm.listSelections();
                for (var i = 0; i < ranges.length; i++) {
                  if (!ranges[i].empty()) return CodeMirror.Pass;
                  var around = charsAround(cm, ranges[i].head);
                  if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
                }
                for (var i = ranges.length - 1; i >= 0; i--) {
                  var cur = ranges[i].head;
                  cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
                }
              }
            
              function handleEnter(cm) {
                var conf = getConfig(cm);
                var explode = conf && getOption(conf, "explode");
                if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
            
                var ranges = cm.listSelections();
                for (var i = 0; i < ranges.length; i++) {
                  if (!ranges[i].empty()) return CodeMirror.Pass;
                  var around = charsAround(cm, ranges[i].head);
                  if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
                }
                cm.operation(function() {
                  cm.replaceSelection("\n\n", null);
                  cm.execCommand("goCharLeft");
                  ranges = cm.listSelections();
                  for (var i = 0; i < ranges.length; i++) {
                    var line = ranges[i].head.line;
                    cm.indentLine(line, null, true);
                    cm.indentLine(line + 1, null, true);
                  }
                });
              }
            
              function handleChar(cm, ch) {
                var conf = getConfig(cm);
                if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
            
                var pairs = getOption(conf, "pairs");
                var pos = pairs.indexOf(ch);
                if (pos == -1) return CodeMirror.Pass;
                var triples = getOption(conf, "triples");
            
                var identical = pairs.charAt(pos + 1) == ch;
                var ranges = cm.listSelections();
                var opening = pos % 2 == 0;
            
                var type, next;
                for (var i = 0; i < ranges.length; i++) {
                  var range = ranges[i], cur = range.head, curType;
                  var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
                  if (opening && !range.empty()) {
                    curType = "surround";
                  } else if ((identical || !opening) && next == ch) {
                    if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch)
                      curType = "skipThree";
                    else
                      curType = "skip";
                  } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
                             cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch &&
                             (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != ch)) {
                    curType = "addFour";
                  } else if (identical) {
                    if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, ch)) curType = "both";
                    else return CodeMirror.Pass;
                  } else if (opening && (cm.getLine(cur.line).length == cur.ch ||
                                         isClosingBracket(next, pairs) ||
                                         /\s/.test(next))) {
                    curType = "both";
                  } else {
                    return CodeMirror.Pass;
                  }
                  if (!type) type = curType;
                  else if (type != curType) return CodeMirror.Pass;
                }
            
                var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
                var right = pos % 2 ? ch : pairs.charAt(pos + 1);
                cm.operation(function() {
                  if (type == "skip") {
                    cm.execCommand("goCharRight");
                  } else if (type == "skipThree") {
                    for (var i = 0; i < 3; i++)
                      cm.execCommand("goCharRight");
                  } else if (type == "surround") {
                    var sels = cm.getSelections();
                    for (var i = 0; i < sels.length; i++)
                      sels[i] = left + sels[i] + right;
                    cm.replaceSelections(sels, "around");
                  } else if (type == "both") {
                    cm.replaceSelection(left + right, null);
                    cm.triggerElectric(left + right);
                    cm.execCommand("goCharLeft");
                  } else if (type == "addFour") {
                    cm.replaceSelection(left + left + left + left, "before");
                    cm.execCommand("goCharRight");
                  }
                });
              }
            
              function isClosingBracket(ch, pairs) {
                var pos = pairs.lastIndexOf(ch);
                return pos > -1 && pos % 2 == 1;
              }
            
              function charsAround(cm, pos) {
                var str = cm.getRange(Pos(pos.line, pos.ch - 1),
                                      Pos(pos.line, pos.ch + 1));
                return str.length == 2 ? str : null;
              }
            
              // Project the token type that will exists after the given char is
              // typed, and use it to determine whether it would cause the start
              // of a string token.
              function enteringString(cm, pos, ch) {
                var line = cm.getLine(pos.line);
                var token = cm.getTokenAt(pos);
                if (/\bstring2?\b/.test(token.type)) return false;
                var stream = new CodeMirror.StringStream(line.slice(0, pos.ch) + ch + line.slice(pos.ch), 4);
                stream.pos = stream.start = token.start;
                for (;;) {
                  var type1 = cm.getMode().token(stream, token.state);
                  if (stream.pos >= pos.ch + 1) return /\bstring2?\b/.test(type1);
                  stream.start = stream.pos;
                }
              }
            });
            
          • closetag.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Tag-closer extension for CodeMirror.
             *
             * This extension adds an "autoCloseTags" option that can be set to
             * either true to get the default behavior, or an object to further
             * configure its behavior.
             *
             * These are supported options:
             *
             * `whenClosing` (default true)
             *   Whether to autoclose when the '/' of a closing tag is typed.
             * `whenOpening` (default true)
             *   Whether to autoclose the tag when the final '>' of an opening
             *   tag is typed.
             * `dontCloseTags` (default is empty tags for HTML, none for XML)
             *   An array of tag names that should not be autoclosed.
             * `indentTags` (default is block tags for HTML, none for XML)
             *   An array of tag names that should, when opened, cause a
             *   blank line to be added inside the tag, and the blank line and
             *   closing line to be indented.
             *
             * See demos/closetag.html for a usage example.
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../fold/xml-fold"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) {
                if (old != CodeMirror.Init && old)
                  cm.removeKeyMap("autoCloseTags");
                if (!val) return;
                var map = {name: "autoCloseTags"};
                if (typeof val != "object" || val.whenClosing)
                  map["'/'"] = function(cm) { return autoCloseSlash(cm); };
                if (typeof val != "object" || val.whenOpening)
                  map["'>'"] = function(cm) { return autoCloseGT(cm); };
                cm.addKeyMap(map);
              });
            
              var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param",
                                   "source", "track", "wbr"];
              var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4",
                                "h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"];
            
              function autoCloseGT(cm) {
                if (cm.getOption("disableInput")) return CodeMirror.Pass;
                var ranges = cm.listSelections(), replacements = [];
                for (var i = 0; i < ranges.length; i++) {
                  if (!ranges[i].empty()) return CodeMirror.Pass;
                  var pos = ranges[i].head, tok = cm.getTokenAt(pos);
                  var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
                  if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass;
            
                  var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html";
                  var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
                  var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
            
                  var tagName = state.tagName;
                  if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);
                  var lowerTagName = tagName.toLowerCase();
                  // Don't process the '>' at the end of an end-tag or self-closing tag
                  if (!tagName ||
                      tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) ||
                      tok.type == "tag" && state.type == "closeTag" ||
                      tok.string.indexOf("/") == (tok.string.length - 1) || // match something like <someTagName />
                      dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||
                      closingTagExists(cm, tagName, pos, state, true))
                    return CodeMirror.Pass;
            
                  var indent = indentTags && indexOf(indentTags, lowerTagName) > -1;
                  replacements[i] = {indent: indent,
                                     text: ">" + (indent ? "\n\n" : "") + "</" + tagName + ">",
                                     newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)};
                }
            
                for (var i = ranges.length - 1; i >= 0; i--) {
                  var info = replacements[i];
                  cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert");
                  var sel = cm.listSelections().slice(0);
                  sel[i] = {head: info.newPos, anchor: info.newPos};
                  cm.setSelections(sel);
                  if (info.indent) {
                    cm.indentLine(info.newPos.line, null, true);
                    cm.indentLine(info.newPos.line + 1, null, true);
                  }
                }
              }
            
              function autoCloseCurrent(cm, typingSlash) {
                var ranges = cm.listSelections(), replacements = [];
                var head = typingSlash ? "/" : "</";
                for (var i = 0; i < ranges.length; i++) {
                  if (!ranges[i].empty()) return CodeMirror.Pass;
                  var pos = ranges[i].head, tok = cm.getTokenAt(pos);
                  var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
                  if (typingSlash && (tok.type == "string" || tok.string.charAt(0) != "<" ||
                                      tok.start != pos.ch - 1))
                    return CodeMirror.Pass;
                  // Kludge to get around the fact that we are not in XML mode
                  // when completing in JS/CSS snippet in htmlmixed mode. Does not
                  // work for other XML embedded languages (there is no general
                  // way to go from a mixed mode to its current XML state).
                  if (inner.mode.name != "xml") {
                    if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript")
                      replacements[i] = head + "script>";
                    else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css")
                      replacements[i] = head + "style>";
                    else
                      return CodeMirror.Pass;
                  } else {
                    if (!state.context || !state.context.tagName ||
                        closingTagExists(cm, state.context.tagName, pos, state))
                      return CodeMirror.Pass;
                    replacements[i] = head + state.context.tagName + ">";
                  }
                }
                cm.replaceSelections(replacements);
                ranges = cm.listSelections();
                for (var i = 0; i < ranges.length; i++)
                  if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)
                    cm.indentLine(ranges[i].head.line);
              }
            
              function autoCloseSlash(cm) {
                if (cm.getOption("disableInput")) return CodeMirror.Pass;
                return autoCloseCurrent(cm, true);
              }
            
              CodeMirror.commands.closeTag = function(cm) { return autoCloseCurrent(cm); };
            
              function indexOf(collection, elt) {
                if (collection.indexOf) return collection.indexOf(elt);
                for (var i = 0, e = collection.length; i < e; ++i)
                  if (collection[i] == elt) return i;
                return -1;
              }
            
              // If xml-fold is loaded, we use its functionality to try and verify
              // whether a given tag is actually unclosed.
              function closingTagExists(cm, tagName, pos, state, newTag) {
                if (!CodeMirror.scanForClosingTag) return false;
                var end = Math.min(cm.lastLine() + 1, pos.line + 500);
                var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end);
                if (!nextClose || nextClose.tag != tagName) return false;
                var cx = state.context;
                // If the immediate wrapping context contains onCx instances of
                // the same tag, a closing tag only exists if there are at least
                // that many closing tags of that type following.
                for (var onCx = newTag ? 1 : 0; cx && cx.tagName == tagName; cx = cx.prev) ++onCx;
                pos = nextClose.to;
                for (var i = 1; i < onCx; i++) {
                  var next = CodeMirror.scanForClosingTag(cm, pos, null, end);
                  if (!next || next.tag != tagName) return false;
                  pos = next.to;
                }
                return true;
              }
            });
            
          • continuelist.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var listRE = /^(\s*)(>[> ]*|[*+-]\s|(\d+)\.)(\s*)/,
                  emptyListRE = /^(\s*)(>[> ]*|[*+-]|(\d+)\.)(\s*)$/,
                  unorderedListRE = /[*+-]\s/;
            
              CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
                if (cm.getOption("disableInput")) return CodeMirror.Pass;
                var ranges = cm.listSelections(), replacements = [];
                for (var i = 0; i < ranges.length; i++) {
                  var pos = ranges[i].head;
                  var eolState = cm.getStateAfter(pos.line);
                  var inList = eolState.list !== false;
                  var inQuote = eolState.quote !== 0;
            
                  var line = cm.getLine(pos.line), match = listRE.exec(line);
                  if (!ranges[i].empty() || (!inList && !inQuote) || !match) {
                    cm.execCommand("newlineAndIndent");
                    return;
                  }
                  if (emptyListRE.test(line)) {
                    cm.replaceRange("", {
                      line: pos.line, ch: 0
                    }, {
                      line: pos.line, ch: pos.ch + 1
                    });
                    replacements[i] = "\n";
                  } else {
                    var indent = match[1], after = match[4];
                    var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0
                      ? match[2]
                      : (parseInt(match[3], 10) + 1) + ".";
            
                    replacements[i] = "\n" + indent + bullet + after;
                  }
                }
            
                cm.replaceSelections(replacements);
              };
            });
            
          • matchbrackets.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
                (document.documentMode == null || document.documentMode < 8);
            
              var Pos = CodeMirror.Pos;
            
              var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
            
              function findMatchingBracket(cm, where, strict, config) {
                var line = cm.getLineHandle(where.line), pos = where.ch - 1;
                var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
                if (!match) return null;
                var dir = match.charAt(1) == ">" ? 1 : -1;
                if (strict && (dir > 0) != (pos == where.ch)) return null;
                var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
            
                var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
                if (found == null) return null;
                return {from: Pos(where.line, pos), to: found && found.pos,
                        match: found && found.ch == match.charAt(0), forward: dir > 0};
              }
            
              // bracketRegex is used to specify which type of bracket to scan
              // should be a regexp, e.g. /[[\]]/
              //
              // Note: If "where" is on an open bracket, then this bracket is ignored.
              //
              // Returns false when no bracket was found, null when it reached
              // maxScanLines and gave up
              function scanForBracket(cm, where, dir, style, config) {
                var maxScanLen = (config && config.maxScanLineLength) || 10000;
                var maxScanLines = (config && config.maxScanLines) || 1000;
            
                var stack = [];
                var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/;
                var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1)
                                      : Math.max(cm.firstLine() - 1, where.line - maxScanLines);
                for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {
                  var line = cm.getLine(lineNo);
                  if (!line) continue;
                  var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;
                  if (line.length > maxScanLen) continue;
                  if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0);
                  for (; pos != end; pos += dir) {
                    var ch = line.charAt(pos);
                    if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) {
                      var match = matching[ch];
                      if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch);
                      else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch};
                      else stack.pop();
                    }
                  }
                }
                return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null;
              }
            
              function matchBrackets(cm, autoclear, config) {
                // Disable brace matching in long lines, since it'll cause hugely slow updates
                var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
                var marks = [], ranges = cm.listSelections();
                for (var i = 0; i < ranges.length; i++) {
                  var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config);
                  if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {
                    var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
                    marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
                    if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen)
                      marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style}));
                  }
                }
            
                if (marks.length) {
                  // Kludge to work around the IE bug from issue #1193, where text
                  // input stops going to the textare whever this fires.
                  if (ie_lt8 && cm.state.focused) cm.focus();
            
                  var clear = function() {
                    cm.operation(function() {
                      for (var i = 0; i < marks.length; i++) marks[i].clear();
                    });
                  };
                  if (autoclear) setTimeout(clear, 800);
                  else return clear;
                }
              }
            
              var currentlyHighlighted = null;
              function doMatchBrackets(cm) {
                cm.operation(function() {
                  if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
                  currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);
                });
              }
            
              CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init)
                  cm.off("cursorActivity", doMatchBrackets);
                if (val) {
                  cm.state.matchBrackets = typeof val == "object" ? val : {};
                  cm.on("cursorActivity", doMatchBrackets);
                }
              });
            
              CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
              CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){
                return findMatchingBracket(this, pos, strict, config);
              });
              CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){
                return scanForBracket(this, pos, dir, style, config);
              });
            });
            
          • matchtags.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../fold/xml-fold"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("matchTags", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init) {
                  cm.off("cursorActivity", doMatchTags);
                  cm.off("viewportChange", maybeUpdateMatch);
                  clear(cm);
                }
                if (val) {
                  cm.state.matchBothTags = typeof val == "object" && val.bothTags;
                  cm.on("cursorActivity", doMatchTags);
                  cm.on("viewportChange", maybeUpdateMatch);
                  doMatchTags(cm);
                }
              });
            
              function clear(cm) {
                if (cm.state.tagHit) cm.state.tagHit.clear();
                if (cm.state.tagOther) cm.state.tagOther.clear();
                cm.state.tagHit = cm.state.tagOther = null;
              }
            
              function doMatchTags(cm) {
                cm.state.failedTagMatch = false;
                cm.operation(function() {
                  clear(cm);
                  if (cm.somethingSelected()) return;
                  var cur = cm.getCursor(), range = cm.getViewport();
                  range.from = Math.min(range.from, cur.line); range.to = Math.max(cur.line + 1, range.to);
                  var match = CodeMirror.findMatchingTag(cm, cur, range);
                  if (!match) return;
                  if (cm.state.matchBothTags) {
                    var hit = match.at == "open" ? match.open : match.close;
                    if (hit) cm.state.tagHit = cm.markText(hit.from, hit.to, {className: "CodeMirror-matchingtag"});
                  }
                  var other = match.at == "close" ? match.open : match.close;
                  if (other)
                    cm.state.tagOther = cm.markText(other.from, other.to, {className: "CodeMirror-matchingtag"});
                  else
                    cm.state.failedTagMatch = true;
                });
              }
            
              function maybeUpdateMatch(cm) {
                if (cm.state.failedTagMatch) doMatchTags(cm);
              }
            
              CodeMirror.commands.toMatchingTag = function(cm) {
                var found = CodeMirror.findMatchingTag(cm, cm.getCursor());
                if (found) {
                  var other = found.at == "close" ? found.open : found.close;
                  if (other) cm.extendSelection(other.to, other.from);
                }
              };
            });
            
          • trailingspace.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) {
                if (prev == CodeMirror.Init) prev = false;
                if (prev && !val)
                  cm.removeOverlay("trailingspace");
                else if (!prev && val)
                  cm.addOverlay({
                    token: function(stream) {
                      for (var l = stream.string.length, i = l; i && /\s/.test(stream.string.charAt(i - 1)); --i) {}
                      if (i > stream.pos) { stream.pos = i; return null; }
                      stream.pos = l;
                      return "trailingspace";
                    },
                    name: "trailingspace"
                  });
              });
            });
            
        • fold
          • brace-fold.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerHelper("fold", "brace", function(cm, start) {
              var line = start.line, lineText = cm.getLine(line);
              var startCh, tokenType;
            
              function findOpening(openCh) {
                for (var at = start.ch, pass = 0;;) {
                  var found = at <= 0 ? -1 : lineText.lastIndexOf(openCh, at - 1);
                  if (found == -1) {
                    if (pass == 1) break;
                    pass = 1;
                    at = lineText.length;
                    continue;
                  }
                  if (pass == 1 && found < start.ch) break;
                  tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1));
                  if (!/^(comment|string)/.test(tokenType)) return found + 1;
                  at = found - 1;
                }
              }
            
              var startToken = "{", endToken = "}", startCh = findOpening("{");
              if (startCh == null) {
                startToken = "[", endToken = "]";
                startCh = findOpening("[");
              }
            
              if (startCh == null) return;
              var count = 1, lastLine = cm.lastLine(), end, endCh;
              outer: for (var i = line; i <= lastLine; ++i) {
                var text = cm.getLine(i), pos = i == line ? startCh : 0;
                for (;;) {
                  var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
                  if (nextOpen < 0) nextOpen = text.length;
                  if (nextClose < 0) nextClose = text.length;
                  pos = Math.min(nextOpen, nextClose);
                  if (pos == text.length) break;
                  if (cm.getTokenTypeAt(CodeMirror.Pos(i, pos + 1)) == tokenType) {
                    if (pos == nextOpen) ++count;
                    else if (!--count) { end = i; endCh = pos; break outer; }
                  }
                  ++pos;
                }
              }
              if (end == null || line == end && endCh == startCh) return;
              return {from: CodeMirror.Pos(line, startCh),
                      to: CodeMirror.Pos(end, endCh)};
            });
            
            CodeMirror.registerHelper("fold", "import", function(cm, start) {
              function hasImport(line) {
                if (line < cm.firstLine() || line > cm.lastLine()) return null;
                var start = cm.getTokenAt(CodeMirror.Pos(line, 1));
                if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1));
                if (start.type != "keyword" || start.string != "import") return null;
                // Now find closing semicolon, return its position
                for (var i = line, e = Math.min(cm.lastLine(), line + 10); i <= e; ++i) {
                  var text = cm.getLine(i), semi = text.indexOf(";");
                  if (semi != -1) return {startCh: start.end, end: CodeMirror.Pos(i, semi)};
                }
              }
            
              var start = start.line, has = hasImport(start), prev;
              if (!has || hasImport(start - 1) || ((prev = hasImport(start - 2)) && prev.end.line == start - 1))
                return null;
              for (var end = has.end;;) {
                var next = hasImport(end.line + 1);
                if (next == null) break;
                end = next.end;
              }
              return {from: cm.clipPos(CodeMirror.Pos(start, has.startCh + 1)), to: end};
            });
            
            CodeMirror.registerHelper("fold", "include", function(cm, start) {
              function hasInclude(line) {
                if (line < cm.firstLine() || line > cm.lastLine()) return null;
                var start = cm.getTokenAt(CodeMirror.Pos(line, 1));
                if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1));
                if (start.type == "meta" && start.string.slice(0, 8) == "#include") return start.start + 8;
              }
            
              var start = start.line, has = hasInclude(start);
              if (has == null || hasInclude(start - 1) != null) return null;
              for (var end = start;;) {
                var next = hasInclude(end + 1);
                if (next == null) break;
                ++end;
              }
              return {from: CodeMirror.Pos(start, has + 1),
                      to: cm.clipPos(CodeMirror.Pos(end))};
            });
            
            });
            
          • comment-fold.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {
              return mode.blockCommentStart && mode.blockCommentEnd;
            }, function(cm, start) {
              var mode = cm.getModeAt(start), startToken = mode.blockCommentStart, endToken = mode.blockCommentEnd;
              if (!startToken || !endToken) return;
              var line = start.line, lineText = cm.getLine(line);
            
              var startCh;
              for (var at = start.ch, pass = 0;;) {
                var found = at <= 0 ? -1 : lineText.lastIndexOf(startToken, at - 1);
                if (found == -1) {
                  if (pass == 1) return;
                  pass = 1;
                  at = lineText.length;
                  continue;
                }
                if (pass == 1 && found < start.ch) return;
                if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1)))) {
                  startCh = found + startToken.length;
                  break;
                }
                at = found - 1;
              }
            
              var depth = 1, lastLine = cm.lastLine(), end, endCh;
              outer: for (var i = line; i <= lastLine; ++i) {
                var text = cm.getLine(i), pos = i == line ? startCh : 0;
                for (;;) {
                  var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
                  if (nextOpen < 0) nextOpen = text.length;
                  if (nextClose < 0) nextClose = text.length;
                  pos = Math.min(nextOpen, nextClose);
                  if (pos == text.length) break;
                  if (pos == nextOpen) ++depth;
                  else if (!--depth) { end = i; endCh = pos; break outer; }
                  ++pos;
                }
              }
              if (end == null || line == end && endCh == startCh) return;
              return {from: CodeMirror.Pos(line, startCh),
                      to: CodeMirror.Pos(end, endCh)};
            });
            
            });
            
          • foldcode.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              function doFold(cm, pos, options, force) {
                if (options && options.call) {
                  var finder = options;
                  options = null;
                } else {
                  var finder = getOption(cm, options, "rangeFinder");
                }
                if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0);
                var minSize = getOption(cm, options, "minFoldSize");
            
                function getRange(allowFolded) {
                  var range = finder(cm, pos);
                  if (!range || range.to.line - range.from.line < minSize) return null;
                  var marks = cm.findMarksAt(range.from);
                  for (var i = 0; i < marks.length; ++i) {
                    if (marks[i].__isFold && force !== "fold") {
                      if (!allowFolded) return null;
                      range.cleared = true;
                      marks[i].clear();
                    }
                  }
                  return range;
                }
            
                var range = getRange(true);
                if (getOption(cm, options, "scanUp")) while (!range && pos.line > cm.firstLine()) {
                  pos = CodeMirror.Pos(pos.line - 1, 0);
                  range = getRange(false);
                }
                if (!range || range.cleared || force === "unfold") return;
            
                var myWidget = makeWidget(cm, options);
                CodeMirror.on(myWidget, "mousedown", function(e) {
                  myRange.clear();
                  CodeMirror.e_preventDefault(e);
                });
                var myRange = cm.markText(range.from, range.to, {
                  replacedWith: myWidget,
                  clearOnEnter: true,
                  __isFold: true
                });
                myRange.on("clear", function(from, to) {
                  CodeMirror.signal(cm, "unfold", cm, from, to);
                });
                CodeMirror.signal(cm, "fold", cm, range.from, range.to);
              }
            
              function makeWidget(cm, options) {
                var widget = getOption(cm, options, "widget");
                if (typeof widget == "string") {
                  var text = document.createTextNode(widget);
                  widget = document.createElement("span");
                  widget.appendChild(text);
                  widget.className = "CodeMirror-foldmarker";
                }
                return widget;
              }
            
              // Clumsy backwards-compatible interface
              CodeMirror.newFoldFunction = function(rangeFinder, widget) {
                return function(cm, pos) { doFold(cm, pos, {rangeFinder: rangeFinder, widget: widget}); };
              };
            
              // New-style interface
              CodeMirror.defineExtension("foldCode", function(pos, options, force) {
                doFold(this, pos, options, force);
              });
            
              CodeMirror.defineExtension("isFolded", function(pos) {
                var marks = this.findMarksAt(pos);
                for (var i = 0; i < marks.length; ++i)
                  if (marks[i].__isFold) return true;
              });
            
              CodeMirror.commands.toggleFold = function(cm) {
                cm.foldCode(cm.getCursor());
              };
              CodeMirror.commands.fold = function(cm) {
                cm.foldCode(cm.getCursor(), null, "fold");
              };
              CodeMirror.commands.unfold = function(cm) {
                cm.foldCode(cm.getCursor(), null, "unfold");
              };
              CodeMirror.commands.foldAll = function(cm) {
                cm.operation(function() {
                  for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
                    cm.foldCode(CodeMirror.Pos(i, 0), null, "fold");
                });
              };
              CodeMirror.commands.unfoldAll = function(cm) {
                cm.operation(function() {
                  for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
                    cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold");
                });
              };
            
              CodeMirror.registerHelper("fold", "combine", function() {
                var funcs = Array.prototype.slice.call(arguments, 0);
                return function(cm, start) {
                  for (var i = 0; i < funcs.length; ++i) {
                    var found = funcs[i](cm, start);
                    if (found) return found;
                  }
                };
              });
            
              CodeMirror.registerHelper("fold", "auto", function(cm, start) {
                var helpers = cm.getHelpers(start, "fold");
                for (var i = 0; i < helpers.length; i++) {
                  var cur = helpers[i](cm, start);
                  if (cur) return cur;
                }
              });
            
              var defaultOptions = {
                rangeFinder: CodeMirror.fold.auto,
                widget: "\u2194",
                minFoldSize: 0,
                scanUp: false
              };
            
              CodeMirror.defineOption("foldOptions", null);
            
              function getOption(cm, options, name) {
                if (options && options[name] !== undefined)
                  return options[name];
                var editorOptions = cm.options.foldOptions;
                if (editorOptions && editorOptions[name] !== undefined)
                  return editorOptions[name];
                return defaultOptions[name];
              }
            
              CodeMirror.defineExtension("foldOption", function(options, name) {
                return getOption(this, options, name);
              });
            });
            
          • foldgutter.css
            .CodeMirror-foldmarker {
              color: blue;
              text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px;
              font-family: arial;
              line-height: .3;
              cursor: pointer;
            }
            .CodeMirror-foldgutter {
              width: .7em;
            }
            .CodeMirror-foldgutter-open,
            .CodeMirror-foldgutter-folded {
              cursor: pointer;
            }
            .CodeMirror-foldgutter-open:after {
              content: "\25BE";
            }
            .CodeMirror-foldgutter-folded:after {
              content: "\25B8";
            }
            
          • foldgutter.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("./foldcode"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "./foldcode"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("foldGutter", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init) {
                  cm.clearGutter(cm.state.foldGutter.options.gutter);
                  cm.state.foldGutter = null;
                  cm.off("gutterClick", onGutterClick);
                  cm.off("change", onChange);
                  cm.off("viewportChange", onViewportChange);
                  cm.off("fold", onFold);
                  cm.off("unfold", onFold);
                  cm.off("swapDoc", updateInViewport);
                }
                if (val) {
                  cm.state.foldGutter = new State(parseOptions(val));
                  updateInViewport(cm);
                  cm.on("gutterClick", onGutterClick);
                  cm.on("change", onChange);
                  cm.on("viewportChange", onViewportChange);
                  cm.on("fold", onFold);
                  cm.on("unfold", onFold);
                  cm.on("swapDoc", updateInViewport);
                }
              });
            
              var Pos = CodeMirror.Pos;
            
              function State(options) {
                this.options = options;
                this.from = this.to = 0;
              }
            
              function parseOptions(opts) {
                if (opts === true) opts = {};
                if (opts.gutter == null) opts.gutter = "CodeMirror-foldgutter";
                if (opts.indicatorOpen == null) opts.indicatorOpen = "CodeMirror-foldgutter-open";
                if (opts.indicatorFolded == null) opts.indicatorFolded = "CodeMirror-foldgutter-folded";
                return opts;
              }
            
              function isFolded(cm, line) {
                var marks = cm.findMarksAt(Pos(line));
                for (var i = 0; i < marks.length; ++i)
                  if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i];
              }
            
              function marker(spec) {
                if (typeof spec == "string") {
                  var elt = document.createElement("div");
                  elt.className = spec + " CodeMirror-guttermarker-subtle";
                  return elt;
                } else {
                  return spec.cloneNode(true);
                }
              }
            
              function updateFoldInfo(cm, from, to) {
                var opts = cm.state.foldGutter.options, cur = from;
                var minSize = cm.foldOption(opts, "minFoldSize");
                var func = cm.foldOption(opts, "rangeFinder");
                cm.eachLine(from, to, function(line) {
                  var mark = null;
                  if (isFolded(cm, cur)) {
                    mark = marker(opts.indicatorFolded);
                  } else {
                    var pos = Pos(cur, 0);
                    var range = func && func(cm, pos);
                    if (range && range.to.line - range.from.line >= minSize)
                      mark = marker(opts.indicatorOpen);
                  }
                  cm.setGutterMarker(line, opts.gutter, mark);
                  ++cur;
                });
              }
            
              function updateInViewport(cm) {
                var vp = cm.getViewport(), state = cm.state.foldGutter;
                if (!state) return;
                cm.operation(function() {
                  updateFoldInfo(cm, vp.from, vp.to);
                });
                state.from = vp.from; state.to = vp.to;
              }
            
              function onGutterClick(cm, line, gutter) {
                var state = cm.state.foldGutter;
                if (!state) return;
                var opts = state.options;
                if (gutter != opts.gutter) return;
                var folded = isFolded(cm, line);
                if (folded) folded.clear();
                else cm.foldCode(Pos(line, 0), opts.rangeFinder);
              }
            
              function onChange(cm) {
                var state = cm.state.foldGutter;
                if (!state) return;
                var opts = state.options;
                state.from = state.to = 0;
                clearTimeout(state.changeUpdate);
                state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600);
              }
            
              function onViewportChange(cm) {
                var state = cm.state.foldGutter;
                if (!state) return;
                var opts = state.options;
                clearTimeout(state.changeUpdate);
                state.changeUpdate = setTimeout(function() {
                  var vp = cm.getViewport();
                  if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
                    updateInViewport(cm);
                  } else {
                    cm.operation(function() {
                      if (vp.from < state.from) {
                        updateFoldInfo(cm, vp.from, state.from);
                        state.from = vp.from;
                      }
                      if (vp.to > state.to) {
                        updateFoldInfo(cm, state.to, vp.to);
                        state.to = vp.to;
                      }
                    });
                  }
                }, opts.updateViewportTimeSpan || 400);
              }
            
              function onFold(cm, from) {
                var state = cm.state.foldGutter;
                if (!state) return;
                var line = from.line;
                if (line >= state.from && line < state.to)
                  updateFoldInfo(cm, line, line + 1);
              }
            });
            
          • indent-fold.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerHelper("fold", "indent", function(cm, start) {
              var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line);
              if (!/\S/.test(firstLine)) return;
              var getIndent = function(line) {
                return CodeMirror.countColumn(line, null, tabSize);
              };
              var myIndent = getIndent(firstLine);
              var lastLineInFold = null;
              // Go through lines until we find a line that definitely doesn't belong in
              // the block we're folding, or to the end.
              for (var i = start.line + 1, end = cm.lastLine(); i <= end; ++i) {
                var curLine = cm.getLine(i);
                var curIndent = getIndent(curLine);
                if (curIndent > myIndent) {
                  // Lines with a greater indent are considered part of the block.
                  lastLineInFold = i;
                } else if (!/\S/.test(curLine)) {
                  // Empty lines might be breaks within the block we're trying to fold.
                } else {
                  // A non-empty line at an indent equal to or less than ours marks the
                  // start of another block.
                  break;
                }
              }
              if (lastLineInFold) return {
                from: CodeMirror.Pos(start.line, firstLine.length),
                to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length)
              };
            });
            
            });
            
          • markdown-fold.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerHelper("fold", "markdown", function(cm, start) {
              var maxDepth = 100;
            
              function isHeader(lineNo) {
                var tokentype = cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0));
                return tokentype && /\bheader\b/.test(tokentype);
              }
            
              function headerLevel(lineNo, line, nextLine) {
                var match = line && line.match(/^#+/);
                if (match && isHeader(lineNo)) return match[0].length;
                match = nextLine && nextLine.match(/^[=\-]+\s*$/);
                if (match && isHeader(lineNo + 1)) return nextLine[0] == "=" ? 1 : 2;
                return maxDepth;
              }
            
              var firstLine = cm.getLine(start.line), nextLine = cm.getLine(start.line + 1);
              var level = headerLevel(start.line, firstLine, nextLine);
              if (level === maxDepth) return undefined;
            
              var lastLineNo = cm.lastLine();
              var end = start.line, nextNextLine = cm.getLine(end + 2);
              while (end < lastLineNo) {
                if (headerLevel(end + 1, nextLine, nextNextLine) <= level) break;
                ++end;
                nextLine = nextNextLine;
                nextNextLine = cm.getLine(end + 2);
              }
            
              return {
                from: CodeMirror.Pos(start.line, firstLine.length),
                to: CodeMirror.Pos(end, cm.getLine(end).length)
              };
            });
            
            });
            
          • xml-fold.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var Pos = CodeMirror.Pos;
              function cmp(a, b) { return a.line - b.line || a.ch - b.ch; }
            
              var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
              var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
              var xmlTagStart = new RegExp("<(/?)([" + nameStartChar + "][" + nameChar + "]*)", "g");
            
              function Iter(cm, line, ch, range) {
                this.line = line; this.ch = ch;
                this.cm = cm; this.text = cm.getLine(line);
                this.min = range ? range.from : cm.firstLine();
                this.max = range ? range.to - 1 : cm.lastLine();
              }
            
              function tagAt(iter, ch) {
                var type = iter.cm.getTokenTypeAt(Pos(iter.line, ch));
                return type && /\btag\b/.test(type);
              }
            
              function nextLine(iter) {
                if (iter.line >= iter.max) return;
                iter.ch = 0;
                iter.text = iter.cm.getLine(++iter.line);
                return true;
              }
              function prevLine(iter) {
                if (iter.line <= iter.min) return;
                iter.text = iter.cm.getLine(--iter.line);
                iter.ch = iter.text.length;
                return true;
              }
            
              function toTagEnd(iter) {
                for (;;) {
                  var gt = iter.text.indexOf(">", iter.ch);
                  if (gt == -1) { if (nextLine(iter)) continue; else return; }
                  if (!tagAt(iter, gt + 1)) { iter.ch = gt + 1; continue; }
                  var lastSlash = iter.text.lastIndexOf("/", gt);
                  var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
                  iter.ch = gt + 1;
                  return selfClose ? "selfClose" : "regular";
                }
              }
              function toTagStart(iter) {
                for (;;) {
                  var lt = iter.ch ? iter.text.lastIndexOf("<", iter.ch - 1) : -1;
                  if (lt == -1) { if (prevLine(iter)) continue; else return; }
                  if (!tagAt(iter, lt + 1)) { iter.ch = lt; continue; }
                  xmlTagStart.lastIndex = lt;
                  iter.ch = lt;
                  var match = xmlTagStart.exec(iter.text);
                  if (match && match.index == lt) return match;
                }
              }
            
              function toNextTag(iter) {
                for (;;) {
                  xmlTagStart.lastIndex = iter.ch;
                  var found = xmlTagStart.exec(iter.text);
                  if (!found) { if (nextLine(iter)) continue; else return; }
                  if (!tagAt(iter, found.index + 1)) { iter.ch = found.index + 1; continue; }
                  iter.ch = found.index + found[0].length;
                  return found;
                }
              }
              function toPrevTag(iter) {
                for (;;) {
                  var gt = iter.ch ? iter.text.lastIndexOf(">", iter.ch - 1) : -1;
                  if (gt == -1) { if (prevLine(iter)) continue; else return; }
                  if (!tagAt(iter, gt + 1)) { iter.ch = gt; continue; }
                  var lastSlash = iter.text.lastIndexOf("/", gt);
                  var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
                  iter.ch = gt + 1;
                  return selfClose ? "selfClose" : "regular";
                }
              }
            
              function findMatchingClose(iter, tag) {
                var stack = [];
                for (;;) {
                  var next = toNextTag(iter), end, startLine = iter.line, startCh = iter.ch - (next ? next[0].length : 0);
                  if (!next || !(end = toTagEnd(iter))) return;
                  if (end == "selfClose") continue;
                  if (next[1]) { // closing tag
                    for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == next[2]) {
                      stack.length = i;
                      break;
                    }
                    if (i < 0 && (!tag || tag == next[2])) return {
                      tag: next[2],
                      from: Pos(startLine, startCh),
                      to: Pos(iter.line, iter.ch)
                    };
                  } else { // opening tag
                    stack.push(next[2]);
                  }
                }
              }
              function findMatchingOpen(iter, tag) {
                var stack = [];
                for (;;) {
                  var prev = toPrevTag(iter);
                  if (!prev) return;
                  if (prev == "selfClose") { toTagStart(iter); continue; }
                  var endLine = iter.line, endCh = iter.ch;
                  var start = toTagStart(iter);
                  if (!start) return;
                  if (start[1]) { // closing tag
                    stack.push(start[2]);
                  } else { // opening tag
                    for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == start[2]) {
                      stack.length = i;
                      break;
                    }
                    if (i < 0 && (!tag || tag == start[2])) return {
                      tag: start[2],
                      from: Pos(iter.line, iter.ch),
                      to: Pos(endLine, endCh)
                    };
                  }
                }
              }
            
              CodeMirror.registerHelper("fold", "xml", function(cm, start) {
                var iter = new Iter(cm, start.line, 0);
                for (;;) {
                  var openTag = toNextTag(iter), end;
                  if (!openTag || iter.line != start.line || !(end = toTagEnd(iter))) return;
                  if (!openTag[1] && end != "selfClose") {
                    var start = Pos(iter.line, iter.ch);
                    var close = findMatchingClose(iter, openTag[2]);
                    return close && {from: start, to: close.from};
                  }
                }
              });
              CodeMirror.findMatchingTag = function(cm, pos, range) {
                var iter = new Iter(cm, pos.line, pos.ch, range);
                if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return;
                var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch);
                var start = end && toTagStart(iter);
                if (!end || !start || cmp(iter, pos) > 0) return;
                var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]};
                if (end == "selfClose") return {open: here, close: null, at: "open"};
            
                if (start[1]) { // closing tag
                  return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"};
                } else { // opening tag
                  iter = new Iter(cm, to.line, to.ch, range);
                  return {open: here, close: findMatchingClose(iter, start[2]), at: "open"};
                }
              };
            
              CodeMirror.findEnclosingTag = function(cm, pos, range) {
                var iter = new Iter(cm, pos.line, pos.ch, range);
                for (;;) {
                  var open = findMatchingOpen(iter);
                  if (!open) break;
                  var forward = new Iter(cm, pos.line, pos.ch, range);
                  var close = findMatchingClose(forward, open.tag);
                  if (close) return {open: open, close: close};
                }
              };
            
              // Used by addon/edit/closetag.js
              CodeMirror.scanForClosingTag = function(cm, pos, name, end) {
                var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null);
                return findMatchingClose(iter, name);
              };
            });
            
        • hint
          • anyword-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var WORD = /[\w$]+/, RANGE = 500;
            
              CodeMirror.registerHelper("hint", "anyword", function(editor, options) {
                var word = options && options.word || WORD;
                var range = options && options.range || RANGE;
                var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
                var end = cur.ch, start = end;
                while (start && word.test(curLine.charAt(start - 1))) --start;
                var curWord = start != end && curLine.slice(start, end);
            
                var list = [], seen = {};
                var re = new RegExp(word.source, "g");
                for (var dir = -1; dir <= 1; dir += 2) {
                  var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
                  for (; line != endLine; line += dir) {
                    var text = editor.getLine(line), m;
                    while (m = re.exec(text)) {
                      if (line == cur.line && m[0] === curWord) continue;
                      if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) {
                        seen[m[0]] = true;
                        list.push(m[0]);
                      }
                    }
                  }
                }
                return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
              });
            });
            
          • css-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../../mode/css/css"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../../mode/css/css"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var pseudoClasses = {link: 1, visited: 1, active: 1, hover: 1, focus: 1,
                                   "first-letter": 1, "first-line": 1, "first-child": 1,
                                   before: 1, after: 1, lang: 1};
            
              CodeMirror.registerHelper("hint", "css", function(cm) {
                var cur = cm.getCursor(), token = cm.getTokenAt(cur);
                var inner = CodeMirror.innerMode(cm.getMode(), token.state);
                if (inner.mode.name != "css") return;
            
                if (token.type == "keyword" && "!important".indexOf(token.string) == 0)
                  return {list: ["!important"], from: CodeMirror.Pos(cur.line, token.start),
                          to: CodeMirror.Pos(cur.line, token.end)};
            
                var start = token.start, end = cur.ch, word = token.string.slice(0, end - start);
                if (/[^\w$_-]/.test(word)) {
                  word = ""; start = end = cur.ch;
                }
            
                var spec = CodeMirror.resolveMode("text/css");
            
                var result = [];
                function add(keywords) {
                  for (var name in keywords)
                    if (!word || name.lastIndexOf(word, 0) == 0)
                      result.push(name);
                }
            
                var st = inner.state.state;
                if (st == "pseudo" || token.type == "variable-3") {
                  add(pseudoClasses);
                } else if (st == "block" || st == "maybeprop") {
                  add(spec.propertyKeywords);
                } else if (st == "prop" || st == "parens" || st == "at" || st == "params") {
                  add(spec.valueKeywords);
                  add(spec.colorKeywords);
                } else if (st == "media" || st == "media_parens") {
                  add(spec.mediaTypes);
                  add(spec.mediaFeatures);
                }
            
                if (result.length) return {
                  list: result,
                  from: CodeMirror.Pos(cur.line, start),
                  to: CodeMirror.Pos(cur.line, end)
                };
              });
            });
            
          • html-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("./xml-hint"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "./xml-hint"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var langs = "ab aa af ak sq am ar an hy as av ae ay az bm ba eu be bn bh bi bs br bg my ca ch ce ny zh cv kw co cr hr cs da dv nl dz en eo et ee fo fj fi fr ff gl ka de el gn gu ht ha he hz hi ho hu ia id ie ga ig ik io is it iu ja jv kl kn kr ks kk km ki rw ky kv kg ko ku kj la lb lg li ln lo lt lu lv gv mk mg ms ml mt mi mr mh mn na nv nb nd ne ng nn no ii nr oc oj cu om or os pa pi fa pl ps pt qu rm rn ro ru sa sc sd se sm sg sr gd sn si sk sl so st es su sw ss sv ta te tg th ti bo tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa cy wo fy xh yi yo za zu".split(" ");
              var targets = ["_blank", "_self", "_top", "_parent"];
              var charsets = ["ascii", "utf-8", "utf-16", "latin1", "latin1"];
              var methods = ["get", "post", "put", "delete"];
              var encs = ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"];
              var media = ["all", "screen", "print", "embossed", "braille", "handheld", "print", "projection", "screen", "tty", "tv", "speech",
                           "3d-glasses", "resolution [>][<][=] [X]", "device-aspect-ratio: X/Y", "orientation:portrait",
                           "orientation:landscape", "device-height: [X]", "device-width: [X]"];
              var s = { attrs: {} }; // Simple tag, reused for a whole lot of tags
            
              var data = {
                a: {
                  attrs: {
                    href: null, ping: null, type: null,
                    media: media,
                    target: targets,
                    hreflang: langs
                  }
                },
                abbr: s,
                acronym: s,
                address: s,
                applet: s,
                area: {
                  attrs: {
                    alt: null, coords: null, href: null, target: null, ping: null,
                    media: media, hreflang: langs, type: null,
                    shape: ["default", "rect", "circle", "poly"]
                  }
                },
                article: s,
                aside: s,
                audio: {
                  attrs: {
                    src: null, mediagroup: null,
                    crossorigin: ["anonymous", "use-credentials"],
                    preload: ["none", "metadata", "auto"],
                    autoplay: ["", "autoplay"],
                    loop: ["", "loop"],
                    controls: ["", "controls"]
                  }
                },
                b: s,
                base: { attrs: { href: null, target: targets } },
                basefont: s,
                bdi: s,
                bdo: s,
                big: s,
                blockquote: { attrs: { cite: null } },
                body: s,
                br: s,
                button: {
                  attrs: {
                    form: null, formaction: null, name: null, value: null,
                    autofocus: ["", "autofocus"],
                    disabled: ["", "autofocus"],
                    formenctype: encs,
                    formmethod: methods,
                    formnovalidate: ["", "novalidate"],
                    formtarget: targets,
                    type: ["submit", "reset", "button"]
                  }
                },
                canvas: { attrs: { width: null, height: null } },
                caption: s,
                center: s,
                cite: s,
                code: s,
                col: { attrs: { span: null } },
                colgroup: { attrs: { span: null } },
                command: {
                  attrs: {
                    type: ["command", "checkbox", "radio"],
                    label: null, icon: null, radiogroup: null, command: null, title: null,
                    disabled: ["", "disabled"],
                    checked: ["", "checked"]
                  }
                },
                data: { attrs: { value: null } },
                datagrid: { attrs: { disabled: ["", "disabled"], multiple: ["", "multiple"] } },
                datalist: { attrs: { data: null } },
                dd: s,
                del: { attrs: { cite: null, datetime: null } },
                details: { attrs: { open: ["", "open"] } },
                dfn: s,
                dir: s,
                div: s,
                dl: s,
                dt: s,
                em: s,
                embed: { attrs: { src: null, type: null, width: null, height: null } },
                eventsource: { attrs: { src: null } },
                fieldset: { attrs: { disabled: ["", "disabled"], form: null, name: null } },
                figcaption: s,
                figure: s,
                font: s,
                footer: s,
                form: {
                  attrs: {
                    action: null, name: null,
                    "accept-charset": charsets,
                    autocomplete: ["on", "off"],
                    enctype: encs,
                    method: methods,
                    novalidate: ["", "novalidate"],
                    target: targets
                  }
                },
                frame: s,
                frameset: s,
                h1: s, h2: s, h3: s, h4: s, h5: s, h6: s,
                head: {
                  attrs: {},
                  children: ["title", "base", "link", "style", "meta", "script", "noscript", "command"]
                },
                header: s,
                hgroup: s,
                hr: s,
                html: {
                  attrs: { manifest: null },
                  children: ["head", "body"]
                },
                i: s,
                iframe: {
                  attrs: {
                    src: null, srcdoc: null, name: null, width: null, height: null,
                    sandbox: ["allow-top-navigation", "allow-same-origin", "allow-forms", "allow-scripts"],
                    seamless: ["", "seamless"]
                  }
                },
                img: {
                  attrs: {
                    alt: null, src: null, ismap: null, usemap: null, width: null, height: null,
                    crossorigin: ["anonymous", "use-credentials"]
                  }
                },
                input: {
                  attrs: {
                    alt: null, dirname: null, form: null, formaction: null,
                    height: null, list: null, max: null, maxlength: null, min: null,
                    name: null, pattern: null, placeholder: null, size: null, src: null,
                    step: null, value: null, width: null,
                    accept: ["audio/*", "video/*", "image/*"],
                    autocomplete: ["on", "off"],
                    autofocus: ["", "autofocus"],
                    checked: ["", "checked"],
                    disabled: ["", "disabled"],
                    formenctype: encs,
                    formmethod: methods,
                    formnovalidate: ["", "novalidate"],
                    formtarget: targets,
                    multiple: ["", "multiple"],
                    readonly: ["", "readonly"],
                    required: ["", "required"],
                    type: ["hidden", "text", "search", "tel", "url", "email", "password", "datetime", "date", "month",
                           "week", "time", "datetime-local", "number", "range", "color", "checkbox", "radio",
                           "file", "submit", "image", "reset", "button"]
                  }
                },
                ins: { attrs: { cite: null, datetime: null } },
                kbd: s,
                keygen: {
                  attrs: {
                    challenge: null, form: null, name: null,
                    autofocus: ["", "autofocus"],
                    disabled: ["", "disabled"],
                    keytype: ["RSA"]
                  }
                },
                label: { attrs: { "for": null, form: null } },
                legend: s,
                li: { attrs: { value: null } },
                link: {
                  attrs: {
                    href: null, type: null,
                    hreflang: langs,
                    media: media,
                    sizes: ["all", "16x16", "16x16 32x32", "16x16 32x32 64x64"]
                  }
                },
                map: { attrs: { name: null } },
                mark: s,
                menu: { attrs: { label: null, type: ["list", "context", "toolbar"] } },
                meta: {
                  attrs: {
                    content: null,
                    charset: charsets,
                    name: ["viewport", "application-name", "author", "description", "generator", "keywords"],
                    "http-equiv": ["content-language", "content-type", "default-style", "refresh"]
                  }
                },
                meter: { attrs: { value: null, min: null, low: null, high: null, max: null, optimum: null } },
                nav: s,
                noframes: s,
                noscript: s,
                object: {
                  attrs: {
                    data: null, type: null, name: null, usemap: null, form: null, width: null, height: null,
                    typemustmatch: ["", "typemustmatch"]
                  }
                },
                ol: { attrs: { reversed: ["", "reversed"], start: null, type: ["1", "a", "A", "i", "I"] } },
                optgroup: { attrs: { disabled: ["", "disabled"], label: null } },
                option: { attrs: { disabled: ["", "disabled"], label: null, selected: ["", "selected"], value: null } },
                output: { attrs: { "for": null, form: null, name: null } },
                p: s,
                param: { attrs: { name: null, value: null } },
                pre: s,
                progress: { attrs: { value: null, max: null } },
                q: { attrs: { cite: null } },
                rp: s,
                rt: s,
                ruby: s,
                s: s,
                samp: s,
                script: {
                  attrs: {
                    type: ["text/javascript"],
                    src: null,
                    async: ["", "async"],
                    defer: ["", "defer"],
                    charset: charsets
                  }
                },
                section: s,
                select: {
                  attrs: {
                    form: null, name: null, size: null,
                    autofocus: ["", "autofocus"],
                    disabled: ["", "disabled"],
                    multiple: ["", "multiple"]
                  }
                },
                small: s,
                source: { attrs: { src: null, type: null, media: null } },
                span: s,
                strike: s,
                strong: s,
                style: {
                  attrs: {
                    type: ["text/css"],
                    media: media,
                    scoped: null
                  }
                },
                sub: s,
                summary: s,
                sup: s,
                table: s,
                tbody: s,
                td: { attrs: { colspan: null, rowspan: null, headers: null } },
                textarea: {
                  attrs: {
                    dirname: null, form: null, maxlength: null, name: null, placeholder: null,
                    rows: null, cols: null,
                    autofocus: ["", "autofocus"],
                    disabled: ["", "disabled"],
                    readonly: ["", "readonly"],
                    required: ["", "required"],
                    wrap: ["soft", "hard"]
                  }
                },
                tfoot: s,
                th: { attrs: { colspan: null, rowspan: null, headers: null, scope: ["row", "col", "rowgroup", "colgroup"] } },
                thead: s,
                time: { attrs: { datetime: null } },
                title: s,
                tr: s,
                track: {
                  attrs: {
                    src: null, label: null, "default": null,
                    kind: ["subtitles", "captions", "descriptions", "chapters", "metadata"],
                    srclang: langs
                  }
                },
                tt: s,
                u: s,
                ul: s,
                "var": s,
                video: {
                  attrs: {
                    src: null, poster: null, width: null, height: null,
                    crossorigin: ["anonymous", "use-credentials"],
                    preload: ["auto", "metadata", "none"],
                    autoplay: ["", "autoplay"],
                    mediagroup: ["movie"],
                    muted: ["", "muted"],
                    controls: ["", "controls"]
                  }
                },
                wbr: s
              };
            
              var globalAttrs = {
                accesskey: ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
                "class": null,
                contenteditable: ["true", "false"],
                contextmenu: null,
                dir: ["ltr", "rtl", "auto"],
                draggable: ["true", "false", "auto"],
                dropzone: ["copy", "move", "link", "string:", "file:"],
                hidden: ["hidden"],
                id: null,
                inert: ["inert"],
                itemid: null,
                itemprop: null,
                itemref: null,
                itemscope: ["itemscope"],
                itemtype: null,
                lang: ["en", "es"],
                spellcheck: ["true", "false"],
                style: null,
                tabindex: ["1", "2", "3", "4", "5", "6", "7", "8", "9"],
                title: null,
                translate: ["yes", "no"],
                onclick: null,
                rel: ["stylesheet", "alternate", "author", "bookmark", "help", "license", "next", "nofollow", "noreferrer", "prefetch", "prev", "search", "tag"]
              };
              function populate(obj) {
                for (var attr in globalAttrs) if (globalAttrs.hasOwnProperty(attr))
                  obj.attrs[attr] = globalAttrs[attr];
              }
            
              populate(s);
              for (var tag in data) if (data.hasOwnProperty(tag) && data[tag] != s)
                populate(data[tag]);
            
              CodeMirror.htmlSchema = data;
              function htmlHint(cm, options) {
                var local = {schemaInfo: data};
                if (options) for (var opt in options) local[opt] = options[opt];
                return CodeMirror.hint.xml(cm, local);
              }
              CodeMirror.registerHelper("hint", "html", htmlHint);
            });
            
          • javascript-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              var Pos = CodeMirror.Pos;
            
              function forEach(arr, f) {
                for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
              }
            
              function arrayContains(arr, item) {
                if (!Array.prototype.indexOf) {
                  var i = arr.length;
                  while (i--) {
                    if (arr[i] === item) {
                      return true;
                    }
                  }
                  return false;
                }
                return arr.indexOf(item) != -1;
              }
            
              function scriptHint(editor, keywords, getToken, options) {
                // Find the token at the cursor
                var cur = editor.getCursor(), token = getToken(editor, cur);
                if (/\b(?:string|comment)\b/.test(token.type)) return;
                token.state = CodeMirror.innerMode(editor.getMode(), token.state).state;
            
                // If it's not a 'word-style' token, ignore the token.
                if (!/^[\w$_]*$/.test(token.string)) {
                  token = {start: cur.ch, end: cur.ch, string: "", state: token.state,
                           type: token.string == "." ? "property" : null};
                } else if (token.end > cur.ch) {
                  token.end = cur.ch;
                  token.string = token.string.slice(0, cur.ch - token.start);
                }
            
                var tprop = token;
                // If it is a property, find out what it is a property of.
                while (tprop.type == "property") {
                  tprop = getToken(editor, Pos(cur.line, tprop.start));
                  if (tprop.string != ".") return;
                  tprop = getToken(editor, Pos(cur.line, tprop.start));
                  if (!context) var context = [];
                  context.push(tprop);
                }
                return {list: getCompletions(token, context, keywords, options),
                        from: Pos(cur.line, token.start),
                        to: Pos(cur.line, token.end)};
              }
            
              function javascriptHint(editor, options) {
                return scriptHint(editor, javascriptKeywords,
                                  function (e, cur) {return e.getTokenAt(cur);},
                                  options);
              };
              CodeMirror.registerHelper("hint", "javascript", javascriptHint);
            
              function getCoffeeScriptToken(editor, cur) {
              // This getToken, it is for coffeescript, imitates the behavior of
              // getTokenAt method in javascript.js, that is, returning "property"
              // type and treat "." as indepenent token.
                var token = editor.getTokenAt(cur);
                if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
                  token.end = token.start;
                  token.string = '.';
                  token.type = "property";
                }
                else if (/^\.[\w$_]*$/.test(token.string)) {
                  token.type = "property";
                  token.start++;
                  token.string = token.string.replace(/\./, '');
                }
                return token;
              }
            
              function coffeescriptHint(editor, options) {
                return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options);
              }
              CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint);
            
              var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
                                 "toUpperCase toLowerCase split concat match replace search").split(" ");
              var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
                                "lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
              var funcProps = "prototype apply call bind".split(" ");
              var javascriptKeywords = ("break case catch continue debugger default delete do else false finally for function " +
                              "if in instanceof new null return switch throw true try typeof var void while with").split(" ");
              var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
                              "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
            
              function getCompletions(token, context, keywords, options) {
                var found = [], start = token.string, global = options && options.globalScope || window;
                function maybeAdd(str) {
                  if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);
                }
                function gatherCompletions(obj) {
                  if (typeof obj == "string") forEach(stringProps, maybeAdd);
                  else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
                  else if (obj instanceof Function) forEach(funcProps, maybeAdd);
                  for (var name in obj) maybeAdd(name);
                }
            
                if (context && context.length) {
                  // If this is a property, see if it belongs to some object we can
                  // find in the current environment.
                  var obj = context.pop(), base;
                  if (obj.type && obj.type.indexOf("variable") === 0) {
                    if (options && options.additionalContext)
                      base = options.additionalContext[obj.string];
                    if (!options || options.useGlobalScope !== false)
                      base = base || global[obj.string];
                  } else if (obj.type == "string") {
                    base = "";
                  } else if (obj.type == "atom") {
                    base = 1;
                  } else if (obj.type == "function") {
                    if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
                        (typeof global.jQuery == 'function'))
                      base = global.jQuery();
                    else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function'))
                      base = global._();
                  }
                  while (base != null && context.length)
                    base = base[context.pop().string];
                  if (base != null) gatherCompletions(base);
                } else {
                  // If not, just look in the global object and any local scope
                  // (reading into JS mode internals to get at the local and global variables)
                  for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
                  for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
                  if (!options || options.useGlobalScope !== false)
                    gatherCompletions(global);
                  forEach(keywords, maybeAdd);
                }
                return found;
              }
            });
            
          • show-hint.css
            .CodeMirror-hints {
              position: absolute;
              z-index: 10;
              overflow: hidden;
              list-style: none;
            
              margin: 0;
              padding: 2px;
            
              -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
              -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
              box-shadow: 2px 3px 5px rgba(0,0,0,.2);
              border-radius: 3px;
              border: 1px solid silver;
            
              background: white;
              font-size: 90%;
              font-family: monospace;
            
              max-height: 20em;
              overflow-y: auto;
            }
            
            .CodeMirror-hint {
              margin: 0;
              padding: 0 4px;
              border-radius: 2px;
              max-width: 19em;
              overflow: hidden;
              white-space: pre;
              color: black;
              cursor: pointer;
            }
            
            li.CodeMirror-hint-active {
              background: #08f;
              color: white;
            }
            
          • show-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var HINT_ELEMENT_CLASS        = "CodeMirror-hint";
              var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
            
              // This is the old interface, kept around for now to stay
              // backwards-compatible.
              CodeMirror.showHint = function(cm, getHints, options) {
                if (!getHints) return cm.showHint(options);
                if (options && options.async) getHints.async = true;
                var newOpts = {hint: getHints};
                if (options) for (var prop in options) newOpts[prop] = options[prop];
                return cm.showHint(newOpts);
              };
            
              CodeMirror.defineExtension("showHint", function(options) {
                // We want a single cursor position.
                if (this.listSelections().length > 1 || this.somethingSelected()) return;
            
                if (this.state.completionActive) this.state.completionActive.close();
                var completion = this.state.completionActive = new Completion(this, options);
                if (!completion.options.hint) return;
            
                CodeMirror.signal(this, "startCompletion", this);
                completion.update(true);
              });
            
              function Completion(cm, options) {
                this.cm = cm;
                this.options = this.buildOptions(options);
                this.widget = null;
                this.debounce = 0;
                this.tick = 0;
                this.startPos = this.cm.getCursor();
                this.startLen = this.cm.getLine(this.startPos.line).length;
            
                var self = this;
                cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
              }
            
              var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
                return setTimeout(fn, 1000/60);
              };
              var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
            
              Completion.prototype = {
                close: function() {
                  if (!this.active()) return;
                  this.cm.state.completionActive = null;
                  this.tick = null;
                  this.cm.off("cursorActivity", this.activityFunc);
            
                  if (this.widget && this.data) CodeMirror.signal(this.data, "close");
                  if (this.widget) this.widget.close();
                  CodeMirror.signal(this.cm, "endCompletion", this.cm);
                },
            
                active: function() {
                  return this.cm.state.completionActive == this;
                },
            
                pick: function(data, i) {
                  var completion = data.list[i];
                  if (completion.hint) completion.hint(this.cm, data, completion);
                  else this.cm.replaceRange(getText(completion), completion.from || data.from,
                                            completion.to || data.to, "complete");
                  CodeMirror.signal(data, "pick", completion);
                  this.close();
                },
            
                cursorActivity: function() {
                  if (this.debounce) {
                    cancelAnimationFrame(this.debounce);
                    this.debounce = 0;
                  }
            
                  var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
                  if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
                      pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
                      (pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
                    this.close();
                  } else {
                    var self = this;
                    this.debounce = requestAnimationFrame(function() {self.update();});
                    if (this.widget) this.widget.disable();
                  }
                },
            
                update: function(first) {
                  if (this.tick == null) return;
                  if (this.data) CodeMirror.signal(this.data, "update");
                  if (!this.options.hint.async) {
                    this.finishUpdate(this.options.hint(this.cm, this.options), first);
                  } else {
                    var myTick = ++this.tick, self = this;
                    this.options.hint(this.cm, function(data) {
                      if (self.tick == myTick) self.finishUpdate(data, first);
                    }, this.options);
                  }
                },
            
                finishUpdate: function(data, first) {
                  this.data = data;
            
                  var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
                  if (this.widget) this.widget.close();
                  if (data && data.list.length) {
                    if (picked && data.list.length == 1) {
                      this.pick(data, 0);
                    } else {
                      this.widget = new Widget(this, data);
                      CodeMirror.signal(data, "shown");
                    }
                  }
                },
            
                buildOptions: function(options) {
                  var editor = this.cm.options.hintOptions;
                  var out = {};
                  for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
                  if (editor) for (var prop in editor)
                    if (editor[prop] !== undefined) out[prop] = editor[prop];
                  if (options) for (var prop in options)
                    if (options[prop] !== undefined) out[prop] = options[prop];
                  return out;
                }
              };
            
              function getText(completion) {
                if (typeof completion == "string") return completion;
                else return completion.text;
              }
            
              function buildKeyMap(completion, handle) {
                var baseMap = {
                  Up: function() {handle.moveFocus(-1);},
                  Down: function() {handle.moveFocus(1);},
                  PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
                  PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
                  Home: function() {handle.setFocus(0);},
                  End: function() {handle.setFocus(handle.length - 1);},
                  Enter: handle.pick,
                  Tab: handle.pick,
                  Esc: handle.close
                };
                var custom = completion.options.customKeys;
                var ourMap = custom ? {} : baseMap;
                function addBinding(key, val) {
                  var bound;
                  if (typeof val != "string")
                    bound = function(cm) { return val(cm, handle); };
                  // This mechanism is deprecated
                  else if (baseMap.hasOwnProperty(val))
                    bound = baseMap[val];
                  else
                    bound = val;
                  ourMap[key] = bound;
                }
                if (custom)
                  for (var key in custom) if (custom.hasOwnProperty(key))
                    addBinding(key, custom[key]);
                var extra = completion.options.extraKeys;
                if (extra)
                  for (var key in extra) if (extra.hasOwnProperty(key))
                    addBinding(key, extra[key]);
                return ourMap;
              }
            
              function getHintElement(hintsElement, el) {
                while (el && el != hintsElement) {
                  if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
                  el = el.parentNode;
                }
              }
            
              function Widget(completion, data) {
                this.completion = completion;
                this.data = data;
                this.picked = false;
                var widget = this, cm = completion.cm;
            
                var hints = this.hints = document.createElement("ul");
                hints.className = "CodeMirror-hints";
                this.selectedHint = data.selectedHint || 0;
            
                var completions = data.list;
                for (var i = 0; i < completions.length; ++i) {
                  var elt = hints.appendChild(document.createElement("li")), cur = completions[i];
                  var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
                  if (cur.className != null) className = cur.className + " " + className;
                  elt.className = className;
                  if (cur.render) cur.render(elt, data, cur);
                  else elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));
                  elt.hintId = i;
                }
            
                var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
                var left = pos.left, top = pos.bottom, below = true;
                hints.style.left = left + "px";
                hints.style.top = top + "px";
                // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
                var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
                var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
                (completion.options.container || document.body).appendChild(hints);
                var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
                if (overlapY > 0) {
                  var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
                  if (curTop - height > 0) { // Fits above cursor
                    hints.style.top = (top = pos.top - height) + "px";
                    below = false;
                  } else if (height > winH) {
                    hints.style.height = (winH - 5) + "px";
                    hints.style.top = (top = pos.bottom - box.top) + "px";
                    var cursor = cm.getCursor();
                    if (data.from.ch != cursor.ch) {
                      pos = cm.cursorCoords(cursor);
                      hints.style.left = (left = pos.left) + "px";
                      box = hints.getBoundingClientRect();
                    }
                  }
                }
                var overlapX = box.right - winW;
                if (overlapX > 0) {
                  if (box.right - box.left > winW) {
                    hints.style.width = (winW - 5) + "px";
                    overlapX -= (box.right - box.left) - winW;
                  }
                  hints.style.left = (left = pos.left - overlapX) + "px";
                }
            
                cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
                  moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
                  setFocus: function(n) { widget.changeActive(n); },
                  menuSize: function() { return widget.screenAmount(); },
                  length: completions.length,
                  close: function() { completion.close(); },
                  pick: function() { widget.pick(); },
                  data: data
                }));
            
                if (completion.options.closeOnUnfocus) {
                  var closingOnBlur;
                  cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
                  cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
                }
            
                var startScroll = cm.getScrollInfo();
                cm.on("scroll", this.onScroll = function() {
                  var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
                  var newTop = top + startScroll.top - curScroll.top;
                  var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);
                  if (!below) point += hints.offsetHeight;
                  if (point <= editor.top || point >= editor.bottom) return completion.close();
                  hints.style.top = newTop + "px";
                  hints.style.left = (left + startScroll.left - curScroll.left) + "px";
                });
            
                CodeMirror.on(hints, "dblclick", function(e) {
                  var t = getHintElement(hints, e.target || e.srcElement);
                  if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
                });
            
                CodeMirror.on(hints, "click", function(e) {
                  var t = getHintElement(hints, e.target || e.srcElement);
                  if (t && t.hintId != null) {
                    widget.changeActive(t.hintId);
                    if (completion.options.completeOnSingleClick) widget.pick();
                  }
                });
            
                CodeMirror.on(hints, "mousedown", function() {
                  setTimeout(function(){cm.focus();}, 20);
                });
            
                CodeMirror.signal(data, "select", completions[0], hints.firstChild);
                return true;
              }
            
              Widget.prototype = {
                close: function() {
                  if (this.completion.widget != this) return;
                  this.completion.widget = null;
                  this.hints.parentNode.removeChild(this.hints);
                  this.completion.cm.removeKeyMap(this.keyMap);
            
                  var cm = this.completion.cm;
                  if (this.completion.options.closeOnUnfocus) {
                    cm.off("blur", this.onBlur);
                    cm.off("focus", this.onFocus);
                  }
                  cm.off("scroll", this.onScroll);
                },
            
                disable: function() {
                  this.completion.cm.removeKeyMap(this.keyMap);
                  var widget = this;
                  this.keyMap = {Enter: function() { widget.picked = true; }};
                  this.completion.cm.addKeyMap(this.keyMap);
                },
            
                pick: function() {
                  this.completion.pick(this.data, this.selectedHint);
                },
            
                changeActive: function(i, avoidWrap) {
                  if (i >= this.data.list.length)
                    i = avoidWrap ? this.data.list.length - 1 : 0;
                  else if (i < 0)
                    i = avoidWrap ? 0  : this.data.list.length - 1;
                  if (this.selectedHint == i) return;
                  var node = this.hints.childNodes[this.selectedHint];
                  node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
                  node = this.hints.childNodes[this.selectedHint = i];
                  node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
                  if (node.offsetTop < this.hints.scrollTop)
                    this.hints.scrollTop = node.offsetTop - 3;
                  else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
                    this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
                  CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
                },
            
                screenAmount: function() {
                  return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
                }
              };
            
              CodeMirror.registerHelper("hint", "auto", function(cm, options) {
                var helpers = cm.getHelpers(cm.getCursor(), "hint"), words;
                if (helpers.length) {
                  for (var i = 0; i < helpers.length; i++) {
                    var cur = helpers[i](cm, options);
                    if (cur && cur.list.length) return cur;
                  }
                } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
                  if (words) return CodeMirror.hint.fromList(cm, {words: words});
                } else if (CodeMirror.hint.anyword) {
                  return CodeMirror.hint.anyword(cm, options);
                }
              });
            
              CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
                var cur = cm.getCursor(), token = cm.getTokenAt(cur);
                var found = [];
                for (var i = 0; i < options.words.length; i++) {
                  var word = options.words[i];
                  if (word.slice(0, token.string.length) == token.string)
                    found.push(word);
                }
            
                if (found.length) return {
                  list: found,
                  from: CodeMirror.Pos(cur.line, token.start),
                        to: CodeMirror.Pos(cur.line, token.end)
                };
              });
            
              CodeMirror.commands.autocomplete = CodeMirror.showHint;
            
              var defaultOptions = {
                hint: CodeMirror.hint.auto,
                completeSingle: true,
                alignWithWord: true,
                closeCharacters: /[\s()\[\]{};:>,]/,
                closeOnUnfocus: true,
                completeOnSingleClick: false,
                container: null,
                customKeys: null,
                extraKeys: null
              };
            
              CodeMirror.defineOption("hintOptions", null);
            });
            
          • sql-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../../mode/sql/sql"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../../mode/sql/sql"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var tables;
              var defaultTable;
              var keywords;
              var CONS = {
                QUERY_DIV: ";",
                ALIAS_KEYWORD: "AS"
              };
              var Pos = CodeMirror.Pos;
            
              function getKeywords(editor) {
                var mode = editor.doc.modeOption;
                if (mode === "sql") mode = "text/x-sql";
                return CodeMirror.resolveMode(mode).keywords;
              }
            
              function getText(item) {
                return typeof item == "string" ? item : item.text;
              }
            
              function getItem(list, item) {
                if (!list.slice) return list[item];
                for (var i = list.length - 1; i >= 0; i--) if (getText(list[i]) == item)
                  return list[i];
              }
            
              function shallowClone(object) {
                var result = {};
                for (var key in object) if (object.hasOwnProperty(key))
                  result[key] = object[key];
                return result;
              }
            
              function match(string, word) {
                var len = string.length;
                var sub = getText(word).substr(0, len);
                return string.toUpperCase() === sub.toUpperCase();
              }
            
              function addMatches(result, search, wordlist, formatter) {
                for (var word in wordlist) {
                  if (!wordlist.hasOwnProperty(word)) continue;
                  if (wordlist.slice) word = wordlist[word];
            
                  if (match(search, word)) result.push(formatter(word));
                }
              }
            
              function cleanName(name) {
                // Get rid name from backticks(`) and preceding dot(.)
                if (name.charAt(0) == ".") {
                  name = name.substr(1);
                }
                return name.replace(/`/g, "");
              }
            
              function insertBackticks(name) {
                var nameParts = getText(name).split(".");
                for (var i = 0; i < nameParts.length; i++)
                  nameParts[i] = "`" + nameParts[i] + "`";
                var escaped = nameParts.join(".");
                if (typeof name == "string") return escaped;
                name = shallowClone(name);
                name.text = escaped;
                return name;
              }
            
              function nameCompletion(cur, token, result, editor) {
                // Try to complete table, colunm names and return start position of completion
                var useBacktick = false;
                var nameParts = [];
                var start = token.start;
                var cont = true;
                while (cont) {
                  cont = (token.string.charAt(0) == ".");
                  useBacktick = useBacktick || (token.string.charAt(0) == "`");
            
                  start = token.start;
                  nameParts.unshift(cleanName(token.string));
            
                  token = editor.getTokenAt(Pos(cur.line, token.start));
                  if (token.string == ".") {
                    cont = true;
                    token = editor.getTokenAt(Pos(cur.line, token.start));
                  }
                }
            
                // Try to complete table names
                var string = nameParts.join(".");
                addMatches(result, string, tables, function(w) {
                  return useBacktick ? insertBackticks(w) : w;
                });
            
                // Try to complete columns from defaultTable
                addMatches(result, string, defaultTable, function(w) {
                  return useBacktick ? insertBackticks(w) : w;
                });
            
                // Try to complete columns
                string = nameParts.pop();
                var table = nameParts.join(".");
            
                var alias = false;
                var aliasTable = table;
                // Check if table is available. If not, find table by Alias
                if (!getItem(tables, table)) {
                  var oldTable = table;
                  table = findTableByAlias(table, editor);
                  if (table !== oldTable) alias = true;
                }
            
                var columns = getItem(tables, table);
                if (columns && columns.columns)
                  columns = columns.columns;
            
                if (columns) {
                  addMatches(result, string, columns, function(w) {
                    if (typeof w == "string") {
                      var tableInsert = table;
                      if (alias == true) tableInsert = aliasTable;
                      w = tableInsert + "." + w;
                    } else {
                      w = shallowClone(w);
                      w.text = table + "." + w.text;
                    }
                    return useBacktick ? insertBackticks(w) : w;
                  });
                }
            
                return start;
              }
            
              function eachWord(lineText, f) {
                if (!lineText) return;
                var excepted = /[,;]/g;
                var words = lineText.split(" ");
                for (var i = 0; i < words.length; i++) {
                  f(words[i]?words[i].replace(excepted, '') : '');
                }
              }
            
              function convertCurToNumber(cur) {
                // max characters of a line is 999,999.
                return cur.line + cur.ch / Math.pow(10, 6);
              }
            
              function convertNumberToCur(num) {
                return Pos(Math.floor(num), +num.toString().split('.').pop());
              }
            
              function findTableByAlias(alias, editor) {
                var doc = editor.doc;
                var fullQuery = doc.getValue();
                var aliasUpperCase = alias.toUpperCase();
                var previousWord = "";
                var table = "";
                var separator = [];
                var validRange = {
                  start: Pos(0, 0),
                  end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)
                };
            
                //add separator
                var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);
                while(indexOfSeparator != -1) {
                  separator.push(doc.posFromIndex(indexOfSeparator));
                  indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);
                }
                separator.unshift(Pos(0, 0));
                separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
            
                //find valid range
                var prevItem = 0;
                var current = convertCurToNumber(editor.getCursor());
                for (var i=0; i< separator.length; i++) {
                  var _v = convertCurToNumber(separator[i]);
                  if (current > prevItem && current <= _v) {
                    validRange = { start: convertNumberToCur(prevItem), end: convertNumberToCur(_v) };
                    break;
                  }
                  prevItem = _v;
                }
            
                var query = doc.getRange(validRange.start, validRange.end, false);
            
                for (var i = 0; i < query.length; i++) {
                  var lineText = query[i];
                  eachWord(lineText, function(word) {
                    var wordUpperCase = word.toUpperCase();
                    if (wordUpperCase === aliasUpperCase && getItem(tables, previousWord))
                      table = previousWord;
                    if (wordUpperCase !== CONS.ALIAS_KEYWORD)
                      previousWord = word;
                  });
                  if (table) break;
                }
                return table;
              }
            
              CodeMirror.registerHelper("hint", "sql", function(editor, options) {
                tables = (options && options.tables) || {};
                var defaultTableName = options && options.defaultTable;
                var disableKeywords = options && options.disableKeywords;
                defaultTable = defaultTableName && getItem(tables, defaultTableName);
                keywords = keywords || getKeywords(editor);
            
                if (defaultTableName && !defaultTable)
                  defaultTable = findTableByAlias(defaultTableName, editor);
            
                defaultTable = defaultTable || [];
            
                if (defaultTable.columns)
                  defaultTable = defaultTable.columns;
            
                var cur = editor.getCursor();
                var result = [];
                var token = editor.getTokenAt(cur), start, end, search;
                if (token.end > cur.ch) {
                  token.end = cur.ch;
                  token.string = token.string.slice(0, cur.ch - token.start);
                }
            
                if (token.string.match(/^[.`\w@]\w*$/)) {
                  search = token.string;
                  start = token.start;
                  end = token.end;
                } else {
                  start = end = cur.ch;
                  search = "";
                }
                if (search.charAt(0) == "." || search.charAt(0) == "`") {
                  start = nameCompletion(cur, token, result, editor);
                } else {
                  addMatches(result, search, tables, function(w) {return w;});
                  addMatches(result, search, defaultTable, function(w) {return w;});
                  if (!disableKeywords)
                    addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
                }
            
                return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
              });
            });
            
          • xml-hint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var Pos = CodeMirror.Pos;
            
              function getHints(cm, options) {
                var tags = options && options.schemaInfo;
                var quote = (options && options.quoteChar) || '"';
                if (!tags) return;
                var cur = cm.getCursor(), token = cm.getTokenAt(cur);
                if (token.end > cur.ch) {
                  token.end = cur.ch;
                  token.string = token.string.slice(0, cur.ch - token.start);
                }
                var inner = CodeMirror.innerMode(cm.getMode(), token.state);
                if (inner.mode.name != "xml") return;
                var result = [], replaceToken = false, prefix;
                var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
                var tagName = tag && /^\w/.test(token.string), tagStart;
            
                if (tagName) {
                  var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);
                  var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;
                  if (tagType) tagStart = token.start - (tagType == "close" ? 2 : 1);
                } else if (tag && token.string == "<") {
                  tagType = "open";
                } else if (tag && token.string == "</") {
                  tagType = "close";
                }
            
                if (!tag && !inner.state.tagName || tagType) {
                  if (tagName)
                    prefix = token.string;
                  replaceToken = tagType;
                  var cx = inner.state.context, curTag = cx && tags[cx.tagName];
                  var childList = cx ? curTag && curTag.children : tags["!top"];
                  if (childList && tagType != "close") {
                    for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].lastIndexOf(prefix, 0) == 0)
                      result.push("<" + childList[i]);
                  } else if (tagType != "close") {
                    for (var name in tags)
                      if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || name.lastIndexOf(prefix, 0) == 0))
                        result.push("<" + name);
                  }
                  if (cx && (!prefix || tagType == "close" && cx.tagName.lastIndexOf(prefix, 0) == 0))
                    result.push("</" + cx.tagName + ">");
                } else {
                  // Attribute completion
                  var curTag = tags[inner.state.tagName], attrs = curTag && curTag.attrs;
                  var globalAttrs = tags["!attrs"];
                  if (!attrs && !globalAttrs) return;
                  if (!attrs) {
                    attrs = globalAttrs;
                  } else if (globalAttrs) { // Combine tag-local and global attributes
                    var set = {};
                    for (var nm in globalAttrs) if (globalAttrs.hasOwnProperty(nm)) set[nm] = globalAttrs[nm];
                    for (var nm in attrs) if (attrs.hasOwnProperty(nm)) set[nm] = attrs[nm];
                    attrs = set;
                  }
                  if (token.type == "string" || token.string == "=") { // A value
                    var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),
                                             Pos(cur.line, token.type == "string" ? token.start : token.end));
                    var atName = before.match(/([^\s\u00a0=<>\"\']+)=$/), atValues;
                    if (!atName || !attrs.hasOwnProperty(atName[1]) || !(atValues = attrs[atName[1]])) return;
                    if (typeof atValues == 'function') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget
                    if (token.type == "string") {
                      prefix = token.string;
                      var n = 0;
                      if (/['"]/.test(token.string.charAt(0))) {
                        quote = token.string.charAt(0);
                        prefix = token.string.slice(1);
                        n++;
                      }
                      var len = token.string.length;
                      if (/['"]/.test(token.string.charAt(len - 1))) {
                        quote = token.string.charAt(len - 1);
                        prefix = token.string.substr(n, len - 2);
                      }
                      replaceToken = true;
                    }
                    for (var i = 0; i < atValues.length; ++i) if (!prefix || atValues[i].lastIndexOf(prefix, 0) == 0)
                      result.push(quote + atValues[i] + quote);
                  } else { // An attribute name
                    if (token.type == "attribute") {
                      prefix = token.string;
                      replaceToken = true;
                    }
                    for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || attr.lastIndexOf(prefix, 0) == 0))
                      result.push(attr);
                  }
                }
                return {
                  list: result,
                  from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
                  to: replaceToken ? Pos(cur.line, token.end) : cur
                };
              }
            
              CodeMirror.registerHelper("hint", "xml", getHints);
            });
            
        • lint
          • coffeescript-lint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Depends on coffeelint.js from http://www.coffeelint.org/js/coffeelint.js
            
            // declare global: coffeelint
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerHelper("lint", "coffeescript", function(text) {
              var found = [];
              var parseError = function(err) {
                var loc = err.lineNumber;
                found.push({from: CodeMirror.Pos(loc-1, 0),
                            to: CodeMirror.Pos(loc, 0),
                            severity: err.level,
                            message: err.message});
              };
              try {
                var res = coffeelint.lint(text);
                for(var i = 0; i < res.length; i++) {
                  parseError(res[i]);
                }
              } catch(e) {
                found.push({from: CodeMirror.Pos(e.location.first_line, 0),
                            to: CodeMirror.Pos(e.location.last_line, e.location.last_column),
                            severity: 'error',
                            message: e.message});
              }
              return found;
            });
            
            });
            
          • css-lint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Depends on csslint.js from https://github.com/stubbornella/csslint
            
            // declare global: CSSLint
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerHelper("lint", "css", function(text) {
              var found = [];
              if (!window.CSSLint) return found;
              var results = CSSLint.verify(text), messages = results.messages, message = null;
              for ( var i = 0; i < messages.length; i++) {
                message = messages[i];
                var startLine = message.line -1, endLine = message.line -1, startCol = message.col -1, endCol = message.col;
                found.push({
                  from: CodeMirror.Pos(startLine, startCol),
                  to: CodeMirror.Pos(endLine, endCol),
                  message: message.message,
                  severity : message.type
                });
              }
              return found;
            });
            
            });
            
          • javascript-lint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              // declare global: JSHINT
            
              var bogus = [ "Dangerous comment" ];
            
              var warnings = [ [ "Expected '{'",
                                 "Statement body should be inside '{ }' braces." ] ];
            
              var errors = [ "Missing semicolon", "Extra comma", "Missing property name",
                             "Unmatched ", " and instead saw", " is not defined",
                             "Unclosed string", "Stopping, unable to continue" ];
            
              function validator(text, options) {
                if (!window.JSHINT) return [];
                JSHINT(text, options, options.globals);
                var errors = JSHINT.data().errors, result = [];
                if (errors) parseErrors(errors, result);
                return result;
              }
            
              CodeMirror.registerHelper("lint", "javascript", validator);
            
              function cleanup(error) {
                // All problems are warnings by default
                fixWith(error, warnings, "warning", true);
                fixWith(error, errors, "error");
            
                return isBogus(error) ? null : error;
              }
            
              function fixWith(error, fixes, severity, force) {
                var description, fix, find, replace, found;
            
                description = error.description;
            
                for ( var i = 0; i < fixes.length; i++) {
                  fix = fixes[i];
                  find = (typeof fix === "string" ? fix : fix[0]);
                  replace = (typeof fix === "string" ? null : fix[1]);
                  found = description.indexOf(find) !== -1;
            
                  if (force || found) {
                    error.severity = severity;
                  }
                  if (found && replace) {
                    error.description = replace;
                  }
                }
              }
            
              function isBogus(error) {
                var description = error.description;
                for ( var i = 0; i < bogus.length; i++) {
                  if (description.indexOf(bogus[i]) !== -1) {
                    return true;
                  }
                }
                return false;
              }
            
              function parseErrors(errors, output) {
                for ( var i = 0; i < errors.length; i++) {
                  var error = errors[i];
                  if (error) {
                    var linetabpositions, index;
            
                    linetabpositions = [];
            
                    // This next block is to fix a problem in jshint. Jshint
                    // replaces
                    // all tabs with spaces then performs some checks. The error
                    // positions (character/space) are then reported incorrectly,
                    // not taking the replacement step into account. Here we look
                    // at the evidence line and try to adjust the character position
                    // to the correct value.
                    if (error.evidence) {
                      // Tab positions are computed once per line and cached
                      var tabpositions = linetabpositions[error.line];
                      if (!tabpositions) {
                        var evidence = error.evidence;
                        tabpositions = [];
                        // ugggh phantomjs does not like this
                        // forEachChar(evidence, function(item, index) {
                        Array.prototype.forEach.call(evidence, function(item,
                                                                        index) {
                          if (item === '\t') {
                            // First col is 1 (not 0) to match error
                            // positions
                            tabpositions.push(index + 1);
                          }
                        });
                        linetabpositions[error.line] = tabpositions;
                      }
                      if (tabpositions.length > 0) {
                        var pos = error.character;
                        tabpositions.forEach(function(tabposition) {
                          if (pos > tabposition) pos -= 1;
                        });
                        error.character = pos;
                      }
                    }
            
                    var start = error.character - 1, end = start + 1;
                    if (error.evidence) {
                      index = error.evidence.substring(start).search(/.\b/);
                      if (index > -1) {
                        end += index;
                      }
                    }
            
                    // Convert to format expected by validation service
                    error.description = error.reason;// + "(jshint)";
                    error.start = error.character;
                    error.end = end;
                    error = cleanup(error);
            
                    if (error)
                      output.push({message: error.description,
                                   severity: error.severity,
                                   from: CodeMirror.Pos(error.line - 1, start),
                                   to: CodeMirror.Pos(error.line - 1, end)});
                  }
                }
              }
            });
            
          • json-lint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Depends on jsonlint.js from https://github.com/zaach/jsonlint
            
            // declare global: jsonlint
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.registerHelper("lint", "json", function(text) {
              var found = [];
              jsonlint.parseError = function(str, hash) {
                var loc = hash.loc;
                found.push({from: CodeMirror.Pos(loc.first_line - 1, loc.first_column),
                            to: CodeMirror.Pos(loc.last_line - 1, loc.last_column),
                            message: str});
              };
              try { jsonlint.parse(text); }
              catch(e) {}
              return found;
            });
            
            });
            
          • lint.css
            /* The lint marker gutter */
            .CodeMirror-lint-markers {
              width: 16px;
            }
            
            .CodeMirror-lint-tooltip {
              background-color: infobackground;
              border: 1px solid black;
              border-radius: 4px 4px 4px 4px;
              color: infotext;
              font-family: monospace;
              font-size: 10pt;
              overflow: hidden;
              padding: 2px 5px;
              position: fixed;
              white-space: pre;
              white-space: pre-wrap;
              z-index: 100;
              max-width: 600px;
              opacity: 0;
              transition: opacity .4s;
              -moz-transition: opacity .4s;
              -webkit-transition: opacity .4s;
              -o-transition: opacity .4s;
              -ms-transition: opacity .4s;
            }
            
            .CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning {
              background-position: left bottom;
              background-repeat: repeat-x;
            }
            
            .CodeMirror-lint-mark-error {
              background-image:
              url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==")
              ;
            }
            
            .CodeMirror-lint-mark-warning {
              background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=");
            }
            
            .CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning {
              background-position: center center;
              background-repeat: no-repeat;
              cursor: pointer;
              display: inline-block;
              height: 16px;
              width: 16px;
              vertical-align: middle;
              position: relative;
            }
            
            .CodeMirror-lint-message-error, .CodeMirror-lint-message-warning {
              padding-left: 18px;
              background-position: top left;
              background-repeat: no-repeat;
            }
            
            .CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {
              background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=");
            }
            
            .CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning {
              background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=");
            }
            
            .CodeMirror-lint-marker-multiple {
              background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC");
              background-repeat: no-repeat;
              background-position: right bottom;
              width: 100%; height: 100%;
            }
            
          • lint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              var GUTTER_ID = "CodeMirror-lint-markers";
            
              function showTooltip(e, content) {
                var tt = document.createElement("div");
                tt.className = "CodeMirror-lint-tooltip";
                tt.appendChild(content.cloneNode(true));
                document.body.appendChild(tt);
            
                function position(e) {
                  if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
                  tt.style.top = Math.max(0, e.clientY - tt.offsetHeight - 5) + "px";
                  tt.style.left = (e.clientX + 5) + "px";
                }
                CodeMirror.on(document, "mousemove", position);
                position(e);
                if (tt.style.opacity != null) tt.style.opacity = 1;
                return tt;
              }
              function rm(elt) {
                if (elt.parentNode) elt.parentNode.removeChild(elt);
              }
              function hideTooltip(tt) {
                if (!tt.parentNode) return;
                if (tt.style.opacity == null) rm(tt);
                tt.style.opacity = 0;
                setTimeout(function() { rm(tt); }, 600);
              }
            
              function showTooltipFor(e, content, node) {
                var tooltip = showTooltip(e, content);
                function hide() {
                  CodeMirror.off(node, "mouseout", hide);
                  if (tooltip) { hideTooltip(tooltip); tooltip = null; }
                }
                var poll = setInterval(function() {
                  if (tooltip) for (var n = node;; n = n.parentNode) {
                    if (n && n.nodeType == 11) n = n.host;
                    if (n == document.body) return;
                    if (!n) { hide(); break; }
                  }
                  if (!tooltip) return clearInterval(poll);
                }, 400);
                CodeMirror.on(node, "mouseout", hide);
              }
            
              function LintState(cm, options, hasGutter) {
                this.marked = [];
                this.options = options;
                this.timeout = null;
                this.hasGutter = hasGutter;
                this.onMouseOver = function(e) { onMouseOver(cm, e); };
              }
            
              function parseOptions(_cm, options) {
                if (options instanceof Function) return {getAnnotations: options};
                if (!options || options === true) options = {};
                return options;
              }
            
              function clearMarks(cm) {
                var state = cm.state.lint;
                if (state.hasGutter) cm.clearGutter(GUTTER_ID);
                for (var i = 0; i < state.marked.length; ++i)
                  state.marked[i].clear();
                state.marked.length = 0;
              }
            
              function makeMarker(labels, severity, multiple, tooltips) {
                var marker = document.createElement("div"), inner = marker;
                marker.className = "CodeMirror-lint-marker-" + severity;
                if (multiple) {
                  inner = marker.appendChild(document.createElement("div"));
                  inner.className = "CodeMirror-lint-marker-multiple";
                }
            
                if (tooltips != false) CodeMirror.on(inner, "mouseover", function(e) {
                  showTooltipFor(e, labels, inner);
                });
            
                return marker;
              }
            
              function getMaxSeverity(a, b) {
                if (a == "error") return a;
                else return b;
              }
            
              function groupByLine(annotations) {
                var lines = [];
                for (var i = 0; i < annotations.length; ++i) {
                  var ann = annotations[i], line = ann.from.line;
                  (lines[line] || (lines[line] = [])).push(ann);
                }
                return lines;
              }
            
              function annotationTooltip(ann) {
                var severity = ann.severity;
                if (!severity) severity = "error";
                var tip = document.createElement("div");
                tip.className = "CodeMirror-lint-message-" + severity;
                tip.appendChild(document.createTextNode(ann.message));
                return tip;
              }
            
              function startLinting(cm) {
                var state = cm.state.lint, options = state.options;
                var passOptions = options.options || options; // Support deprecated passing of `options` property in options
                var getAnnotations = options.getAnnotations || cm.getHelper(CodeMirror.Pos(0, 0), "lint");
                if (!getAnnotations) return;
                if (options.async || getAnnotations.async)
                  getAnnotations(cm.getValue(), updateLinting, passOptions, cm);
                else
                  updateLinting(cm, getAnnotations(cm.getValue(), passOptions, cm));
              }
            
              function updateLinting(cm, annotationsNotSorted) {
                clearMarks(cm);
                var state = cm.state.lint, options = state.options;
            
                var annotations = groupByLine(annotationsNotSorted);
            
                for (var line = 0; line < annotations.length; ++line) {
                  var anns = annotations[line];
                  if (!anns) continue;
            
                  var maxSeverity = null;
                  var tipLabel = state.hasGutter && document.createDocumentFragment();
            
                  for (var i = 0; i < anns.length; ++i) {
                    var ann = anns[i];
                    var severity = ann.severity;
                    if (!severity) severity = "error";
                    maxSeverity = getMaxSeverity(maxSeverity, severity);
            
                    if (options.formatAnnotation) ann = options.formatAnnotation(ann);
                    if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann));
            
                    if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, {
                      className: "CodeMirror-lint-mark-" + severity,
                      __annotation: ann
                    }));
                  }
            
                  if (state.hasGutter)
                    cm.setGutterMarker(line, GUTTER_ID, makeMarker(tipLabel, maxSeverity, anns.length > 1,
                                                                   state.options.tooltips));
                }
                if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm);
              }
            
              function onChange(cm) {
                var state = cm.state.lint;
                if (!state) return;
                clearTimeout(state.timeout);
                state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
              }
            
              function popupSpanTooltip(ann, e) {
                var target = e.target || e.srcElement;
                showTooltipFor(e, annotationTooltip(ann), target);
              }
            
              function onMouseOver(cm, e) {
                var target = e.target || e.srcElement;
                if (!/\bCodeMirror-lint-mark-/.test(target.className)) return;
                var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2;
                var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client"));
                for (var i = 0; i < spans.length; ++i) {
                  var ann = spans[i].__annotation;
                  if (ann) return popupSpanTooltip(ann, e);
                }
              }
            
              CodeMirror.defineOption("lint", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init) {
                  clearMarks(cm);
                  cm.off("change", onChange);
                  CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.lint.onMouseOver);
                  clearTimeout(cm.state.lint.timeout);
                  delete cm.state.lint;
                }
            
                if (val) {
                  var gutters = cm.getOption("gutters"), hasLintGutter = false;
                  for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true;
                  var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter);
                  cm.on("change", onChange);
                  if (state.options.tooltips != false)
                    CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
            
                  startLinting(cm);
                }
              });
            });
            
          • yaml-lint.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            // Depends on js-yaml.js from https://github.com/nodeca/js-yaml
            
            // declare global: jsyaml
            
            CodeMirror.registerHelper("lint", "yaml", function(text) {
              var found = [];
              try { jsyaml.load(text); }
              catch(e) {
                  var loc = e.mark;
                  found.push({ from: CodeMirror.Pos(loc.line, loc.column), to: CodeMirror.Pos(loc.line, loc.column), message: e.message });
              }
              return found;
            });
            
            });
            
        • merge
          • merge.css
            .CodeMirror-merge {
              position: relative;
              border: 1px solid #ddd;
              white-space: pre;
            }
            
            .CodeMirror-merge, .CodeMirror-merge .CodeMirror {
              height: 350px;
            }
            
            .CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 47%; }
            .CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 6%; }
            .CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; }
            .CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; }
            
            .CodeMirror-merge-pane {
              display: inline-block;
              white-space: normal;
              vertical-align: top;
            }
            .CodeMirror-merge-pane-rightmost {
              position: absolute;
              right: 0px;
              z-index: 1;
            }
            
            .CodeMirror-merge-gap {
              z-index: 2;
              display: inline-block;
              height: 100%;
              -moz-box-sizing: border-box;
              box-sizing: border-box;
              overflow: hidden;
              border-left: 1px solid #ddd;
              border-right: 1px solid #ddd;
              position: relative;
              background: #f8f8f8;
            }
            
            .CodeMirror-merge-scrolllock-wrap {
              position: absolute;
              bottom: 0; left: 50%;
            }
            .CodeMirror-merge-scrolllock {
              position: relative;
              left: -50%;
              cursor: pointer;
              color: #555;
              line-height: 1;
            }
            
            .CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
              position: absolute;
              left: 0; top: 0;
              right: 0; bottom: 0;
              line-height: 1;
            }
            
            .CodeMirror-merge-copy {
              position: absolute;
              cursor: pointer;
              color: #44c;
            }
            
            .CodeMirror-merge-copy-reverse {
              position: absolute;
              cursor: pointer;
              color: #44c;
            }
            
            .CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }
            .CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }
            
            .CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted {
              background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);
              background-position: bottom left;
              background-repeat: repeat-x;
            }
            
            .CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted {
              background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);
              background-position: bottom left;
              background-repeat: repeat-x;
            }
            
            .CodeMirror-merge-r-chunk { background: #ffffe0; }
            .CodeMirror-merge-r-chunk-start { border-top: 1px solid #ee8; }
            .CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #ee8; }
            .CodeMirror-merge-r-connect { fill: #ffffe0; stroke: #ee8; stroke-width: 1px; }
            
            .CodeMirror-merge-l-chunk { background: #eef; }
            .CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; }
            .CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; }
            .CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }
            
            .CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
            .CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
            .CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
            
            .CodeMirror-merge-collapsed-widget:before {
              content: "(...)";
            }
            .CodeMirror-merge-collapsed-widget {
              cursor: pointer;
              color: #88b;
              background: #eef;
              border: 1px solid #ddf;
              font-size: 90%;
              padding: 0 3px;
              border-radius: 4px;
            }
            .CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }
            
          • merge.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("diff_match_patch"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "diff_match_patch"], mod);
              else // Plain browser env
                mod(CodeMirror, diff_match_patch);
            })(function(CodeMirror, diff_match_patch) {
              "use strict";
              var Pos = CodeMirror.Pos;
              var svgNS = "http://www.w3.org/2000/svg";
            
              function DiffView(mv, type) {
                this.mv = mv;
                this.type = type;
                this.classes = type == "left"
                  ? {chunk: "CodeMirror-merge-l-chunk",
                     start: "CodeMirror-merge-l-chunk-start",
                     end: "CodeMirror-merge-l-chunk-end",
                     insert: "CodeMirror-merge-l-inserted",
                     del: "CodeMirror-merge-l-deleted",
                     connect: "CodeMirror-merge-l-connect"}
                  : {chunk: "CodeMirror-merge-r-chunk",
                     start: "CodeMirror-merge-r-chunk-start",
                     end: "CodeMirror-merge-r-chunk-end",
                     insert: "CodeMirror-merge-r-inserted",
                     del: "CodeMirror-merge-r-deleted",
                     connect: "CodeMirror-merge-r-connect"};
              }
            
              DiffView.prototype = {
                constructor: DiffView,
                init: function(pane, orig, options) {
                  this.edit = this.mv.edit;
                  (this.edit.state.diffViews || (this.edit.state.diffViews = [])).push(this);
                  this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));
                  this.orig.state.diffViews = [this];
            
                  this.diff = getDiff(asString(orig), asString(options.value));
                  this.chunks = getChunks(this.diff);
                  this.diffOutOfDate = this.dealigned = false;
            
                  this.showDifferences = options.showDifferences !== false;
                  this.forceUpdate = registerUpdate(this);
                  setScrollLock(this, true, false);
                  registerScroll(this);
                },
                setShowDifferences: function(val) {
                  val = val !== false;
                  if (val != this.showDifferences) {
                    this.showDifferences = val;
                    this.forceUpdate("full");
                  }
                }
              };
            
              function ensureDiff(dv) {
                if (dv.diffOutOfDate) {
                  dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());
                  dv.chunks = getChunks(dv.diff);
                  dv.diffOutOfDate = false;
                  CodeMirror.signal(dv.edit, "updateDiff", dv.diff);
                }
              }
            
              var updating = false;
              function registerUpdate(dv) {
                var edit = {from: 0, to: 0, marked: []};
                var orig = {from: 0, to: 0, marked: []};
                var debounceChange, updatingFast = false;
                function update(mode) {
                  updating = true;
                  updatingFast = false;
                  if (mode == "full") {
                    if (dv.svg) clear(dv.svg);
                    if (dv.copyButtons) clear(dv.copyButtons);
                    clearMarks(dv.edit, edit.marked, dv.classes);
                    clearMarks(dv.orig, orig.marked, dv.classes);
                    edit.from = edit.to = orig.from = orig.to = 0;
                  }
                  ensureDiff(dv);
                  if (dv.showDifferences) {
                    updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);
                    updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
                  }
                  makeConnections(dv);
            
                  if (dv.mv.options.connect == "align")
                    alignChunks(dv);
                  updating = false;
                }
                function setDealign(fast) {
                  if (updating) return;
                  dv.dealigned = true;
                  set(fast);
                }
                function set(fast) {
                  if (updating || updatingFast) return;
                  clearTimeout(debounceChange);
                  if (fast === true) updatingFast = true;
                  debounceChange = setTimeout(update, fast === true ? 20 : 250);
                }
                function change(_cm, change) {
                  if (!dv.diffOutOfDate) {
                    dv.diffOutOfDate = true;
                    edit.from = edit.to = orig.from = orig.to = 0;
                  }
                  // Update faster when a line was added/removed
                  setDealign(change.text.length - 1 != change.to.line - change.from.line);
                }
                dv.edit.on("change", change);
                dv.orig.on("change", change);
                dv.edit.on("markerAdded", setDealign);
                dv.edit.on("markerCleared", setDealign);
                dv.orig.on("markerAdded", setDealign);
                dv.orig.on("markerCleared", setDealign);
                dv.edit.on("viewportChange", function() { set(false); });
                dv.orig.on("viewportChange", function() { set(false); });
                update();
                return update;
              }
            
              function registerScroll(dv) {
                dv.edit.on("scroll", function() {
                  syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
                });
                dv.orig.on("scroll", function() {
                  syncScroll(dv, DIFF_DELETE) && makeConnections(dv);
                });
              }
            
              function syncScroll(dv, type) {
                // Change handler will do a refresh after a timeout when diff is out of date
                if (dv.diffOutOfDate) return false;
                if (!dv.lockScroll) return true;
                var editor, other, now = +new Date;
                if (type == DIFF_INSERT) { editor = dv.edit; other = dv.orig; }
                else { editor = dv.orig; other = dv.edit; }
                // Don't take action if the position of this editor was recently set
                // (to prevent feedback loops)
                if (editor.state.scrollSetBy == dv && (editor.state.scrollSetAt || 0) + 50 > now) return false;
            
                var sInfo = editor.getScrollInfo();
                if (dv.mv.options.connect == "align") {
                  targetPos = sInfo.top;
                } else {
                  var halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;
                  var mid = editor.lineAtHeight(midY, "local");
                  var around = chunkBoundariesAround(dv.chunks, mid, type == DIFF_INSERT);
                  var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);
                  var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);
                  var ratio = (midY - off.top) / (off.bot - off.top);
                  var targetPos = (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top);
            
                  var botDist, mix;
                  // Some careful tweaking to make sure no space is left out of view
                  // when scrolling to top or bottom.
                  if (targetPos > sInfo.top && (mix = sInfo.top / halfScreen) < 1) {
                    targetPos = targetPos * mix + sInfo.top * (1 - mix);
                  } else if ((botDist = sInfo.height - sInfo.clientHeight - sInfo.top) < halfScreen) {
                    var otherInfo = other.getScrollInfo();
                    var botDistOther = otherInfo.height - otherInfo.clientHeight - targetPos;
                    if (botDistOther > botDist && (mix = botDist / halfScreen) < 1)
                      targetPos = targetPos * mix + (otherInfo.height - otherInfo.clientHeight - botDist) * (1 - mix);
                  }
                }
            
                other.scrollTo(sInfo.left, targetPos);
                other.state.scrollSetAt = now;
                other.state.scrollSetBy = dv;
                return true;
              }
            
              function getOffsets(editor, around) {
                var bot = around.after;
                if (bot == null) bot = editor.lastLine() + 1;
                return {top: editor.heightAtLine(around.before || 0, "local"),
                        bot: editor.heightAtLine(bot, "local")};
              }
            
              function setScrollLock(dv, val, action) {
                dv.lockScroll = val;
                if (val && action != false) syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
                dv.lockButton.innerHTML = val ? "\u21db\u21da" : "\u21db&nbsp;&nbsp;\u21da";
              }
            
              // Updating the marks for editor content
            
              function clearMarks(editor, arr, classes) {
                for (var i = 0; i < arr.length; ++i) {
                  var mark = arr[i];
                  if (mark instanceof CodeMirror.TextMarker) {
                    mark.clear();
                  } else if (mark.parent) {
                    editor.removeLineClass(mark, "background", classes.chunk);
                    editor.removeLineClass(mark, "background", classes.start);
                    editor.removeLineClass(mark, "background", classes.end);
                  }
                }
                arr.length = 0;
              }
            
              // FIXME maybe add a margin around viewport to prevent too many updates
              function updateMarks(editor, diff, state, type, classes) {
                var vp = editor.getViewport();
                editor.operation(function() {
                  if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
                    clearMarks(editor, state.marked, classes);
                    markChanges(editor, diff, type, state.marked, vp.from, vp.to, classes);
                    state.from = vp.from; state.to = vp.to;
                  } else {
                    if (vp.from < state.from) {
                      markChanges(editor, diff, type, state.marked, vp.from, state.from, classes);
                      state.from = vp.from;
                    }
                    if (vp.to > state.to) {
                      markChanges(editor, diff, type, state.marked, state.to, vp.to, classes);
                      state.to = vp.to;
                    }
                  }
                });
              }
            
              function markChanges(editor, diff, type, marks, from, to, classes) {
                var pos = Pos(0, 0);
                var top = Pos(from, 0), bot = editor.clipPos(Pos(to - 1));
                var cls = type == DIFF_DELETE ? classes.del : classes.insert;
                function markChunk(start, end) {
                  var bfrom = Math.max(from, start), bto = Math.min(to, end);
                  for (var i = bfrom; i < bto; ++i) {
                    var line = editor.addLineClass(i, "background", classes.chunk);
                    if (i == start) editor.addLineClass(line, "background", classes.start);
                    if (i == end - 1) editor.addLineClass(line, "background", classes.end);
                    marks.push(line);
                  }
                  // When the chunk is empty, make sure a horizontal line shows up
                  if (start == end && bfrom == end && bto == end) {
                    if (bfrom)
                      marks.push(editor.addLineClass(bfrom - 1, "background", classes.end));
                    else
                      marks.push(editor.addLineClass(bfrom, "background", classes.start));
                  }
                }
            
                var chunkStart = 0;
                for (var i = 0; i < diff.length; ++i) {
                  var part = diff[i], tp = part[0], str = part[1];
                  if (tp == DIFF_EQUAL) {
                    var cleanFrom = pos.line + (startOfLineClean(diff, i) ? 0 : 1);
                    moveOver(pos, str);
                    var cleanTo = pos.line + (endOfLineClean(diff, i) ? 1 : 0);
                    if (cleanTo > cleanFrom) {
                      if (i) markChunk(chunkStart, cleanFrom);
                      chunkStart = cleanTo;
                    }
                  } else {
                    if (tp == type) {
                      var end = moveOver(pos, str, true);
                      var a = posMax(top, pos), b = posMin(bot, end);
                      if (!posEq(a, b))
                        marks.push(editor.markText(a, b, {className: cls}));
                      pos = end;
                    }
                  }
                }
                if (chunkStart <= pos.line) markChunk(chunkStart, pos.line + 1);
              }
            
              // Updating the gap between editor and original
            
              function makeConnections(dv) {
                if (!dv.showDifferences) return;
            
                if (dv.svg) {
                  clear(dv.svg);
                  var w = dv.gap.offsetWidth;
                  attrs(dv.svg, "width", w, "height", dv.gap.offsetHeight);
                }
                if (dv.copyButtons) clear(dv.copyButtons);
            
                var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();
                var sTopEdit = dv.edit.getScrollInfo().top, sTopOrig = dv.orig.getScrollInfo().top;
                for (var i = 0; i < dv.chunks.length; i++) {
                  var ch = dv.chunks[i];
                  if (ch.editFrom <= vpEdit.to && ch.editTo >= vpEdit.from &&
                      ch.origFrom <= vpOrig.to && ch.origTo >= vpOrig.from)
                    drawConnectorsForChunk(dv, ch, sTopOrig, sTopEdit, w);
                }
              }
            
              function getMatchingOrigLine(editLine, chunks) {
                var editStart = 0, origStart = 0;
                for (var i = 0; i < chunks.length; i++) {
                  var chunk = chunks[i];
                  if (chunk.editTo > editLine && chunk.editFrom <= editLine) return null;
                  if (chunk.editFrom > editLine) break;
                  editStart = chunk.editTo;
                  origStart = chunk.origTo;
                }
                return origStart + (editLine - editStart);
              }
            
              function findAlignedLines(dv, other) {
                var linesToAlign = [];
                for (var i = 0; i < dv.chunks.length; i++) {
                  var chunk = dv.chunks[i];
                  linesToAlign.push([chunk.origTo, chunk.editTo, other ? getMatchingOrigLine(chunk.editTo, other.chunks) : null]);
                }
                if (other) {
                  for (var i = 0; i < other.chunks.length; i++) {
                    var chunk = other.chunks[i];
                    for (var j = 0; j < linesToAlign.length; j++) {
                      var align = linesToAlign[j];
                      if (align[1] == chunk.editTo) {
                        j = -1;
                        break;
                      } else if (align[1] > chunk.editTo) {
                        break;
                      }
                    }
                    if (j > -1)
                      linesToAlign.splice(j - 1, 0, [getMatchingOrigLine(chunk.editTo, dv.chunks), chunk.editTo, chunk.origTo]);
                  }
                }
                return linesToAlign;
              }
            
              function alignChunks(dv, force) {
                if (!dv.dealigned && !force) return;
                if (!dv.orig.curOp) return dv.orig.operation(function() {
                  alignChunks(dv, force);
                });
            
                dv.dealigned = false;
                var other = dv.mv.left == dv ? dv.mv.right : dv.mv.left;
                if (other) {
                  ensureDiff(other);
                  other.dealigned = false;
                }
                var linesToAlign = findAlignedLines(dv, other);
            
                // Clear old aligners
                var aligners = dv.mv.aligners;
                for (var i = 0; i < aligners.length; i++)
                  aligners[i].clear();
                aligners.length = 0;
            
                var cm = [dv.orig, dv.edit], scroll = [];
                if (other) cm.push(other.orig);
                for (var i = 0; i < cm.length; i++)
                  scroll.push(cm[i].getScrollInfo().top);
            
                for (var ln = 0; ln < linesToAlign.length; ln++)
                  alignLines(cm, linesToAlign[ln], aligners);
            
                for (var i = 0; i < cm.length; i++)
                  cm[i].scrollTo(null, scroll[i]);
              }
            
              function alignLines(cm, lines, aligners) {
                var maxOffset = 0, offset = [];
                for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
                  var off = cm[i].heightAtLine(lines[i], "local");
                  offset[i] = off;
                  maxOffset = Math.max(maxOffset, off);
                }
                for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
                  var diff = maxOffset - offset[i];
                  if (diff > 1)
                    aligners.push(padAbove(cm[i], lines[i], diff));
                }
              }
            
              function padAbove(cm, line, size) {
                var above = true;
                if (line > cm.lastLine()) {
                  line--;
                  above = false;
                }
                var elt = document.createElement("div");
                elt.className = "CodeMirror-merge-spacer";
                elt.style.height = size + "px"; elt.style.minWidth = "1px";
                return cm.addLineWidget(line, elt, {height: size, above: above});
              }
            
              function drawConnectorsForChunk(dv, chunk, sTopOrig, sTopEdit, w) {
                var flip = dv.type == "left";
                var top = dv.orig.heightAtLine(chunk.origFrom, "local") - sTopOrig;
                if (dv.svg) {
                  var topLpx = top;
                  var topRpx = dv.edit.heightAtLine(chunk.editFrom, "local") - sTopEdit;
                  if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }
                  var botLpx = dv.orig.heightAtLine(chunk.origTo, "local") - sTopOrig;
                  var botRpx = dv.edit.heightAtLine(chunk.editTo, "local") - sTopEdit;
                  if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }
                  var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;
                  var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;
                  attrs(dv.svg.appendChild(document.createElementNS(svgNS, "path")),
                        "d", "M -1 " + topRpx + curveTop + " L " + (w + 2) + " " + botLpx + curveBot + " z",
                        "class", dv.classes.connect);
                }
                if (dv.copyButtons) {
                  var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\u21dd" : "\u21dc",
                                                            "CodeMirror-merge-copy"));
                  var editOriginals = dv.mv.options.allowEditingOriginals;
                  copy.title = editOriginals ? "Push to left" : "Revert chunk";
                  copy.chunk = chunk;
                  copy.style.top = top + "px";
            
                  if (editOriginals) {
                    var topReverse = dv.orig.heightAtLine(chunk.editFrom, "local") - sTopEdit;
                    var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\u21dd" : "\u21dc",
                                                                     "CodeMirror-merge-copy-reverse"));
                    copyReverse.title = "Push to right";
                    copyReverse.chunk = {editFrom: chunk.origFrom, editTo: chunk.origTo,
                                         origFrom: chunk.editFrom, origTo: chunk.editTo};
                    copyReverse.style.top = topReverse + "px";
                    dv.type == "right" ? copyReverse.style.left = "2px" : copyReverse.style.right = "2px";
                  }
                }
              }
            
              function copyChunk(dv, to, from, chunk) {
                if (dv.diffOutOfDate) return;
                to.replaceRange(from.getRange(Pos(chunk.origFrom, 0), Pos(chunk.origTo, 0)),
                                     Pos(chunk.editFrom, 0), Pos(chunk.editTo, 0));
              }
            
              // Merge view, containing 0, 1, or 2 diff views.
            
              var MergeView = CodeMirror.MergeView = function(node, options) {
                if (!(this instanceof MergeView)) return new MergeView(node, options);
            
                this.options = options;
                var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight;
            
                var hasLeft = origLeft != null, hasRight = origRight != null;
                var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0);
                var wrap = [], left = this.left = null, right = this.right = null;
                var self = this;
            
                if (hasLeft) {
                  left = this.left = new DiffView(this, "left");
                  var leftPane = elt("div", null, "CodeMirror-merge-pane");
                  wrap.push(leftPane);
                  wrap.push(buildGap(left));
                }
            
                var editPane = elt("div", null, "CodeMirror-merge-pane");
                wrap.push(editPane);
            
                if (hasRight) {
                  right = this.right = new DiffView(this, "right");
                  wrap.push(buildGap(right));
                  var rightPane = elt("div", null, "CodeMirror-merge-pane");
                  wrap.push(rightPane);
                }
            
                (hasRight ? rightPane : editPane).className += " CodeMirror-merge-pane-rightmost";
            
                wrap.push(elt("div", null, null, "height: 0; clear: both;"));
            
                var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-merge CodeMirror-merge-" + panes + "pane"));
                this.edit = CodeMirror(editPane, copyObj(options));
            
                if (left) left.init(leftPane, origLeft, options);
                if (right) right.init(rightPane, origRight, options);
            
                if (options.collapseIdentical) {
                  updating = true;
                  this.editor().operation(function() {
                    collapseIdenticalStretches(self, options.collapseIdentical);
                  });
                  updating = false;
                }
                if (options.connect == "align") {
                  this.aligners = [];
                  alignChunks(this.left || this.right, true);
                }
            
                var onResize = function() {
                  if (left) makeConnections(left);
                  if (right) makeConnections(right);
                };
                CodeMirror.on(window, "resize", onResize);
                var resizeInterval = setInterval(function() {
                  for (var p = wrapElt.parentNode; p && p != document.body; p = p.parentNode) {}
                  if (!p) { clearInterval(resizeInterval); CodeMirror.off(window, "resize", onResize); }
                }, 5000);
              };
            
              function buildGap(dv) {
                var lock = dv.lockButton = elt("div", null, "CodeMirror-merge-scrolllock");
                lock.title = "Toggle locked scrolling";
                var lockWrap = elt("div", [lock], "CodeMirror-merge-scrolllock-wrap");
                CodeMirror.on(lock, "click", function() { setScrollLock(dv, !dv.lockScroll); });
                var gapElts = [lockWrap];
                if (dv.mv.options.revertButtons !== false) {
                  dv.copyButtons = elt("div", null, "CodeMirror-merge-copybuttons-" + dv.type);
                  CodeMirror.on(dv.copyButtons, "click", function(e) {
                    var node = e.target || e.srcElement;
                    if (!node.chunk) return;
                    if (node.className == "CodeMirror-merge-copy-reverse") {
                      copyChunk(dv, dv.orig, dv.edit, node.chunk);
                      return;
                    }
                    copyChunk(dv, dv.edit, dv.orig, node.chunk);
                  });
                  gapElts.unshift(dv.copyButtons);
                }
                if (dv.mv.options.connect != "align") {
                  var svg = document.createElementNS && document.createElementNS(svgNS, "svg");
                  if (svg && !svg.createSVGRect) svg = null;
                  dv.svg = svg;
                  if (svg) gapElts.push(svg);
                }
            
                return dv.gap = elt("div", gapElts, "CodeMirror-merge-gap");
              }
            
              MergeView.prototype = {
                constuctor: MergeView,
                editor: function() { return this.edit; },
                rightOriginal: function() { return this.right && this.right.orig; },
                leftOriginal: function() { return this.left && this.left.orig; },
                setShowDifferences: function(val) {
                  if (this.right) this.right.setShowDifferences(val);
                  if (this.left) this.left.setShowDifferences(val);
                },
                rightChunks: function() {
                  if (this.right) { ensureDiff(this.right); return this.right.chunks; }
                },
                leftChunks: function() {
                  if (this.left) { ensureDiff(this.left); return this.left.chunks; }
                }
              };
            
              function asString(obj) {
                if (typeof obj == "string") return obj;
                else return obj.getValue();
              }
            
              // Operations on diffs
            
              var dmp = new diff_match_patch();
              function getDiff(a, b) {
                var diff = dmp.diff_main(a, b);
                dmp.diff_cleanupSemantic(diff);
                // The library sometimes leaves in empty parts, which confuse the algorithm
                for (var i = 0; i < diff.length; ++i) {
                  var part = diff[i];
                  if (!part[1]) {
                    diff.splice(i--, 1);
                  } else if (i && diff[i - 1][0] == part[0]) {
                    diff.splice(i--, 1);
                    diff[i][1] += part[1];
                  }
                }
                return diff;
              }
            
              function getChunks(diff) {
                var chunks = [];
                var startEdit = 0, startOrig = 0;
                var edit = Pos(0, 0), orig = Pos(0, 0);
                for (var i = 0; i < diff.length; ++i) {
                  var part = diff[i], tp = part[0];
                  if (tp == DIFF_EQUAL) {
                    var startOff = startOfLineClean(diff, i) ? 0 : 1;
                    var cleanFromEdit = edit.line + startOff, cleanFromOrig = orig.line + startOff;
                    moveOver(edit, part[1], null, orig);
                    var endOff = endOfLineClean(diff, i) ? 1 : 0;
                    var cleanToEdit = edit.line + endOff, cleanToOrig = orig.line + endOff;
                    if (cleanToEdit > cleanFromEdit) {
                      if (i) chunks.push({origFrom: startOrig, origTo: cleanFromOrig,
                                          editFrom: startEdit, editTo: cleanFromEdit});
                      startEdit = cleanToEdit; startOrig = cleanToOrig;
                    }
                  } else {
                    moveOver(tp == DIFF_INSERT ? edit : orig, part[1]);
                  }
                }
                if (startEdit <= edit.line || startOrig <= orig.line)
                  chunks.push({origFrom: startOrig, origTo: orig.line + 1,
                               editFrom: startEdit, editTo: edit.line + 1});
                return chunks;
              }
            
              function endOfLineClean(diff, i) {
                if (i == diff.length - 1) return true;
                var next = diff[i + 1][1];
                if (next.length == 1 || next.charCodeAt(0) != 10) return false;
                if (i == diff.length - 2) return true;
                next = diff[i + 2][1];
                return next.length > 1 && next.charCodeAt(0) == 10;
              }
            
              function startOfLineClean(diff, i) {
                if (i == 0) return true;
                var last = diff[i - 1][1];
                if (last.charCodeAt(last.length - 1) != 10) return false;
                if (i == 1) return true;
                last = diff[i - 2][1];
                return last.charCodeAt(last.length - 1) == 10;
              }
            
              function chunkBoundariesAround(chunks, n, nInEdit) {
                var beforeE, afterE, beforeO, afterO;
                for (var i = 0; i < chunks.length; i++) {
                  var chunk = chunks[i];
                  var fromLocal = nInEdit ? chunk.editFrom : chunk.origFrom;
                  var toLocal = nInEdit ? chunk.editTo : chunk.origTo;
                  if (afterE == null) {
                    if (fromLocal > n) { afterE = chunk.editFrom; afterO = chunk.origFrom; }
                    else if (toLocal > n) { afterE = chunk.editTo; afterO = chunk.origTo; }
                  }
                  if (toLocal <= n) { beforeE = chunk.editTo; beforeO = chunk.origTo; }
                  else if (fromLocal <= n) { beforeE = chunk.editFrom; beforeO = chunk.origFrom; }
                }
                return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}};
              }
            
              function collapseSingle(cm, from, to) {
                cm.addLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
                var widget = document.createElement("span");
                widget.className = "CodeMirror-merge-collapsed-widget";
                widget.title = "Identical text collapsed. Click to expand.";
                var mark = cm.markText(Pos(from, 0), Pos(to - 1), {
                  inclusiveLeft: true,
                  inclusiveRight: true,
                  replacedWith: widget,
                  clearOnEnter: true
                });
                function clear() {
                  mark.clear();
                  cm.removeLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
                }
                widget.addEventListener("click", clear);
                return {mark: mark, clear: clear};
              }
            
              function collapseStretch(size, editors) {
                var marks = [];
                function clear() {
                  for (var i = 0; i < marks.length; i++) marks[i].clear();
                }
                for (var i = 0; i < editors.length; i++) {
                  var editor = editors[i];
                  var mark = collapseSingle(editor.cm, editor.line, editor.line + size);
                  marks.push(mark);
                  mark.mark.on("clear", clear);
                }
                return marks[0].mark;
              }
            
              function unclearNearChunks(dv, margin, off, clear) {
                for (var i = 0; i < dv.chunks.length; i++) {
                  var chunk = dv.chunks[i];
                  for (var l = chunk.editFrom - margin; l < chunk.editTo + margin; l++) {
                    var pos = l + off;
                    if (pos >= 0 && pos < clear.length) clear[pos] = false;
                  }
                }
              }
            
              function collapseIdenticalStretches(mv, margin) {
                if (typeof margin != "number") margin = 2;
                var clear = [], edit = mv.editor(), off = edit.firstLine();
                for (var l = off, e = edit.lastLine(); l <= e; l++) clear.push(true);
                if (mv.left) unclearNearChunks(mv.left, margin, off, clear);
                if (mv.right) unclearNearChunks(mv.right, margin, off, clear);
            
                for (var i = 0; i < clear.length; i++) {
                  if (clear[i]) {
                    var line = i + off;
                    for (var size = 1; i < clear.length - 1 && clear[i + 1]; i++, size++) {}
                    if (size > margin) {
                      var editors = [{line: line, cm: edit}];
                      if (mv.left) editors.push({line: getMatchingOrigLine(line, mv.left.chunks), cm: mv.left.orig});
                      if (mv.right) editors.push({line: getMatchingOrigLine(line, mv.right.chunks), cm: mv.right.orig});
                      var mark = collapseStretch(size, editors);
                      if (mv.options.onCollapse) mv.options.onCollapse(mv, line, size, mark);
                    }
                  }
                }
              }
            
              // General utilities
            
              function elt(tag, content, className, style) {
                var e = document.createElement(tag);
                if (className) e.className = className;
                if (style) e.style.cssText = style;
                if (typeof content == "string") e.appendChild(document.createTextNode(content));
                else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
                return e;
              }
            
              function clear(node) {
                for (var count = node.childNodes.length; count > 0; --count)
                  node.removeChild(node.firstChild);
              }
            
              function attrs(elt) {
                for (var i = 1; i < arguments.length; i += 2)
                  elt.setAttribute(arguments[i], arguments[i+1]);
              }
            
              function copyObj(obj, target) {
                if (!target) target = {};
                for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
                return target;
              }
            
              function moveOver(pos, str, copy, other) {
                var out = copy ? Pos(pos.line, pos.ch) : pos, at = 0;
                for (;;) {
                  var nl = str.indexOf("\n", at);
                  if (nl == -1) break;
                  ++out.line;
                  if (other) ++other.line;
                  at = nl + 1;
                }
                out.ch = (at ? 0 : out.ch) + (str.length - at);
                if (other) other.ch = (at ? 0 : other.ch) + (str.length - at);
                return out;
              }
            
              function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; }
              function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; }
              function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }
            
              function findPrevDiff(chunks, start, isOrig) {
                for (var i = chunks.length - 1; i >= 0; i--) {
                  var chunk = chunks[i];
                  var to = (isOrig ? chunk.origTo : chunk.editTo) - 1;
                  if (to < start) return to;
                }
              }
            
              function findNextDiff(chunks, start, isOrig) {
                for (var i = 0; i < chunks.length; i++) {
                  var chunk = chunks[i];
                  var from = (isOrig ? chunk.origFrom : chunk.editFrom);
                  if (from > start) return from;
                }
              }
            
              function goNearbyDiff(cm, dir) {
                var found = null, views = cm.state.diffViews, line = cm.getCursor().line;
                if (views) for (var i = 0; i < views.length; i++) {
                  var dv = views[i], isOrig = cm == dv.orig;
                  ensureDiff(dv);
                  var pos = dir < 0 ? findPrevDiff(dv.chunks, line, isOrig) : findNextDiff(dv.chunks, line, isOrig);
                  if (pos != null && (found == null || (dir < 0 ? pos > found : pos < found)))
                    found = pos;
                }
                if (found != null)
                  cm.setCursor(found, 0);
                else
                  return CodeMirror.Pass;
              }
            
              CodeMirror.commands.goNextDiff = function(cm) {
                return goNearbyDiff(cm, 1);
              };
              CodeMirror.commands.goPrevDiff = function(cm) {
                return goNearbyDiff(cm, -1);
              };
            });
            
        • mode
          • loadmode.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), "cjs");
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], function(CM) { mod(CM, "amd"); });
              else // Plain browser env
                mod(CodeMirror, "plain");
            })(function(CodeMirror, env) {
              if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";
            
              var loading = {};
              function splitCallback(cont, n) {
                var countDown = n;
                return function() { if (--countDown == 0) cont(); };
              }
              function ensureDeps(mode, cont) {
                var deps = CodeMirror.modes[mode].dependencies;
                if (!deps) return cont();
                var missing = [];
                for (var i = 0; i < deps.length; ++i) {
                  if (!CodeMirror.modes.hasOwnProperty(deps[i]))
                    missing.push(deps[i]);
                }
                if (!missing.length) return cont();
                var split = splitCallback(cont, missing.length);
                for (var i = 0; i < missing.length; ++i)
                  CodeMirror.requireMode(missing[i], split);
              }
            
              CodeMirror.requireMode = function(mode, cont) {
                if (typeof mode != "string") mode = mode.name;
                if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
                if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
            
                var file = CodeMirror.modeURL.replace(/%N/g, mode);
                if (env == "plain") {
                  var script = document.createElement("script");
                  script.src = file;
                  var others = document.getElementsByTagName("script")[0];
                  var list = loading[mode] = [cont];
                  CodeMirror.on(script, "load", function() {
                    ensureDeps(mode, function() {
                      for (var i = 0; i < list.length; ++i) list[i]();
                    });
                  });
                  others.parentNode.insertBefore(script, others);
                } else if (env == "cjs") {
                  require(file);
                  cont();
                } else if (env == "amd") {
                  requirejs([file], cont);
                }
              };
            
              CodeMirror.autoLoadMode = function(instance, mode) {
                if (!CodeMirror.modes.hasOwnProperty(mode))
                  CodeMirror.requireMode(mode, function() {
                    instance.setOption("mode", instance.getOption("mode"));
                  });
              };
            });
            
          • multiplex.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.multiplexingMode = function(outer /*, others */) {
              // Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects
              var others = Array.prototype.slice.call(arguments, 1);
            
              function indexOf(string, pattern, from, returnEnd) {
                if (typeof pattern == "string") {
                  var found = string.indexOf(pattern, from);
                  return returnEnd && found > -1 ? found + pattern.length : found;
                }
                var m = pattern.exec(from ? string.slice(from) : string);
                return m ? m.index + from + (returnEnd ? m[0].length : 0) : -1;
              }
            
              return {
                startState: function() {
                  return {
                    outer: CodeMirror.startState(outer),
                    innerActive: null,
                    inner: null
                  };
                },
            
                copyState: function(state) {
                  return {
                    outer: CodeMirror.copyState(outer, state.outer),
                    innerActive: state.innerActive,
                    inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner)
                  };
                },
            
                token: function(stream, state) {
                  if (!state.innerActive) {
                    var cutOff = Infinity, oldContent = stream.string;
                    for (var i = 0; i < others.length; ++i) {
                      var other = others[i];
                      var found = indexOf(oldContent, other.open, stream.pos);
                      if (found == stream.pos) {
                        if (!other.parseDelimiters) stream.match(other.open);
                        state.innerActive = other;
                        state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
                        return other.delimStyle;
                      } else if (found != -1 && found < cutOff) {
                        cutOff = found;
                      }
                    }
                    if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff);
                    var outerToken = outer.token(stream, state.outer);
                    if (cutOff != Infinity) stream.string = oldContent;
                    return outerToken;
                  } else {
                    var curInner = state.innerActive, oldContent = stream.string;
                    if (!curInner.close && stream.sol()) {
                      state.innerActive = state.inner = null;
                      return this.token(stream, state);
                    }
                    var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos, curInner.parseDelimiters) : -1;
                    if (found == stream.pos && !curInner.parseDelimiters) {
                      stream.match(curInner.close);
                      state.innerActive = state.inner = null;
                      return curInner.delimStyle;
                    }
                    if (found > -1) stream.string = oldContent.slice(0, found);
                    var innerToken = curInner.mode.token(stream, state.inner);
                    if (found > -1) stream.string = oldContent;
            
                    if (found == stream.pos && curInner.parseDelimiters)
                      state.innerActive = state.inner = null;
            
                    if (curInner.innerStyle) {
                      if (innerToken) innerToken = innerToken + ' ' + curInner.innerStyle;
                      else innerToken = curInner.innerStyle;
                    }
            
                    return innerToken;
                  }
                },
            
                indent: function(state, textAfter) {
                  var mode = state.innerActive ? state.innerActive.mode : outer;
                  if (!mode.indent) return CodeMirror.Pass;
                  return mode.indent(state.innerActive ? state.inner : state.outer, textAfter);
                },
            
                blankLine: function(state) {
                  var mode = state.innerActive ? state.innerActive.mode : outer;
                  if (mode.blankLine) {
                    mode.blankLine(state.innerActive ? state.inner : state.outer);
                  }
                  if (!state.innerActive) {
                    for (var i = 0; i < others.length; ++i) {
                      var other = others[i];
                      if (other.open === "\n") {
                        state.innerActive = other;
                        state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "") : 0);
                      }
                    }
                  } else if (state.innerActive.close === "\n") {
                    state.innerActive = state.inner = null;
                  }
                },
            
                electricChars: outer.electricChars,
            
                innerMode: function(state) {
                  return state.inner ? {state: state.inner, mode: state.innerActive.mode} : {state: state.outer, mode: outer};
                }
              };
            };
            
            });
            
          • multiplex_test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              CodeMirror.defineMode("markdown_with_stex", function(){
                var inner = CodeMirror.getMode({}, "stex");
                var outer = CodeMirror.getMode({}, "markdown");
            
                var innerOptions = {
                  open: '$',
                  close: '$',
                  mode: inner,
                  delimStyle: 'delim',
                  innerStyle: 'inner'
                };
            
                return CodeMirror.multiplexingMode(outer, innerOptions);
              });
            
              var mode = CodeMirror.getMode({}, "markdown_with_stex");
            
              function MT(name) {
                test.mode(
                  name,
                  mode,
                  Array.prototype.slice.call(arguments, 1),
                  'multiplexing');
              }
            
              MT(
                "stexInsideMarkdown",
                "[strong **Equation:**] [delim $][inner&tag \\pi][delim $]");
            })();
            
          • overlay.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Utility function that allows modes to be combined. The mode given
            // as the base argument takes care of most of the normal mode
            // functionality, but a second (typically simple) mode is used, which
            // can override the style of text. Both modes get to parse all of the
            // text, but when both assign a non-null style to a piece of code, the
            // overlay wins, unless the combine argument was true and not overridden,
            // or state.overlay.combineTokens was true, in which case the styles are
            // combined.
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.overlayMode = function(base, overlay, combine) {
              return {
                startState: function() {
                  return {
                    base: CodeMirror.startState(base),
                    overlay: CodeMirror.startState(overlay),
                    basePos: 0, baseCur: null,
                    overlayPos: 0, overlayCur: null,
                    streamSeen: null
                  };
                },
                copyState: function(state) {
                  return {
                    base: CodeMirror.copyState(base, state.base),
                    overlay: CodeMirror.copyState(overlay, state.overlay),
                    basePos: state.basePos, baseCur: null,
                    overlayPos: state.overlayPos, overlayCur: null
                  };
                },
            
                token: function(stream, state) {
                  if (stream != state.streamSeen ||
                      Math.min(state.basePos, state.overlayPos) < stream.start) {
                    state.streamSeen = stream;
                    state.basePos = state.overlayPos = stream.start;
                  }
            
                  if (stream.start == state.basePos) {
                    state.baseCur = base.token(stream, state.base);
                    state.basePos = stream.pos;
                  }
                  if (stream.start == state.overlayPos) {
                    stream.pos = stream.start;
                    state.overlayCur = overlay.token(stream, state.overlay);
                    state.overlayPos = stream.pos;
                  }
                  stream.pos = Math.min(state.basePos, state.overlayPos);
            
                  // state.overlay.combineTokens always takes precedence over combine,
                  // unless set to null
                  if (state.overlayCur == null) return state.baseCur;
                  else if (state.baseCur != null &&
                           state.overlay.combineTokens ||
                           combine && state.overlay.combineTokens == null)
                    return state.baseCur + " " + state.overlayCur;
                  else return state.overlayCur;
                },
            
                indent: base.indent && function(state, textAfter) {
                  return base.indent(state.base, textAfter);
                },
                electricChars: base.electricChars,
            
                innerMode: function(state) { return {state: state.base, mode: base}; },
            
                blankLine: function(state) {
                  if (base.blankLine) base.blankLine(state.base);
                  if (overlay.blankLine) overlay.blankLine(state.overlay);
                }
              };
            };
            
            });
            
          • simple.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineSimpleMode = function(name, states) {
                CodeMirror.defineMode(name, function(config) {
                  return CodeMirror.simpleMode(config, states);
                });
              };
            
              CodeMirror.simpleMode = function(config, states) {
                ensureState(states, "start");
                var states_ = {}, meta = states.meta || {}, hasIndentation = false;
                for (var state in states) if (state != meta && states.hasOwnProperty(state)) {
                  var list = states_[state] = [], orig = states[state];
                  for (var i = 0; i < orig.length; i++) {
                    var data = orig[i];
                    list.push(new Rule(data, states));
                    if (data.indent || data.dedent) hasIndentation = true;
                  }
                }
                var mode = {
                  startState: function() {
                    return {state: "start", pending: null,
                            local: null, localState: null,
                            indent: hasIndentation ? [] : null};
                  },
                  copyState: function(state) {
                    var s = {state: state.state, pending: state.pending,
                             local: state.local, localState: null,
                             indent: state.indent && state.indent.slice(0)};
                    if (state.localState)
                      s.localState = CodeMirror.copyState(state.local.mode, state.localState);
                    if (state.stack)
                      s.stack = state.stack.slice(0);
                    for (var pers = state.persistentStates; pers; pers = pers.next)
                      s.persistentStates = {mode: pers.mode,
                                            spec: pers.spec,
                                            state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state),
                                            next: s.persistentStates};
                    return s;
                  },
                  token: tokenFunction(states_, config),
                  innerMode: function(state) { return state.local && {mode: state.local.mode, state: state.localState}; },
                  indent: indentFunction(states_, meta)
                };
                if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop))
                  mode[prop] = meta[prop];
                return mode;
              };
            
              function ensureState(states, name) {
                if (!states.hasOwnProperty(name))
                  throw new Error("Undefined state " + name + "in simple mode");
              }
            
              function toRegex(val, caret) {
                if (!val) return /(?:)/;
                var flags = "";
                if (val instanceof RegExp) {
                  if (val.ignoreCase) flags = "i";
                  val = val.source;
                } else {
                  val = String(val);
                }
                return new RegExp((caret === false ? "" : "^") + "(?:" + val + ")", flags);
              }
            
              function asToken(val) {
                if (!val) return null;
                if (typeof val == "string") return val.replace(/\./g, " ");
                var result = [];
                for (var i = 0; i < val.length; i++)
                  result.push(val[i] && val[i].replace(/\./g, " "));
                return result;
              }
            
              function Rule(data, states) {
                if (data.next || data.push) ensureState(states, data.next || data.push);
                this.regex = toRegex(data.regex);
                this.token = asToken(data.token);
                this.data = data;
              }
            
              function tokenFunction(states, config) {
                return function(stream, state) {
                  if (state.pending) {
                    var pend = state.pending.shift();
                    if (state.pending.length == 0) state.pending = null;
                    stream.pos += pend.text.length;
                    return pend.token;
                  }
            
                  if (state.local) {
                    if (state.local.end && stream.match(state.local.end)) {
                      var tok = state.local.endToken || null;
                      state.local = state.localState = null;
                      return tok;
                    } else {
                      var tok = state.local.mode.token(stream, state.localState), m;
                      if (state.local.endScan && (m = state.local.endScan.exec(stream.current())))
                        stream.pos = stream.start + m.index;
                      return tok;
                    }
                  }
            
                  var curState = states[state.state];
                  for (var i = 0; i < curState.length; i++) {
                    var rule = curState[i];
                    var matches = (!rule.data.sol || stream.sol()) && stream.match(rule.regex);
                    if (matches) {
                      if (rule.data.next) {
                        state.state = rule.data.next;
                      } else if (rule.data.push) {
                        (state.stack || (state.stack = [])).push(state.state);
                        state.state = rule.data.push;
                      } else if (rule.data.pop && state.stack && state.stack.length) {
                        state.state = state.stack.pop();
                      }
            
                      if (rule.data.mode)
                        enterLocalMode(config, state, rule.data.mode, rule.token);
                      if (rule.data.indent)
                        state.indent.push(stream.indentation() + config.indentUnit);
                      if (rule.data.dedent)
                        state.indent.pop();
                      if (matches.length > 2) {
                        state.pending = [];
                        for (var j = 2; j < matches.length; j++)
                          if (matches[j])
                            state.pending.push({text: matches[j], token: rule.token[j - 1]});
                        stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));
                        return rule.token[0];
                      } else if (rule.token && rule.token.join) {
                        return rule.token[0];
                      } else {
                        return rule.token;
                      }
                    }
                  }
                  stream.next();
                  return null;
                };
              }
            
              function cmp(a, b) {
                if (a === b) return true;
                if (!a || typeof a != "object" || !b || typeof b != "object") return false;
                var props = 0;
                for (var prop in a) if (a.hasOwnProperty(prop)) {
                  if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false;
                  props++;
                }
                for (var prop in b) if (b.hasOwnProperty(prop)) props--;
                return props == 0;
              }
            
              function enterLocalMode(config, state, spec, token) {
                var pers;
                if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next)
                  if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p;
                var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec);
                var lState = pers ? pers.state : CodeMirror.startState(mode);
                if (spec.persistent && !pers)
                  state.persistentStates = {mode: mode, spec: spec.spec, state: lState, next: state.persistentStates};
            
                state.localState = lState;
                state.local = {mode: mode,
                               end: spec.end && toRegex(spec.end),
                               endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false),
                               endToken: token && token.join ? token[token.length - 1] : token};
              }
            
              function indexOf(val, arr) {
                for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true;
              }
            
              function indentFunction(states, meta) {
                return function(state, textAfter, line) {
                  if (state.local && state.local.mode.indent)
                    return state.local.mode.indent(state.localState, textAfter, line);
                  if (state.indent == null || state.local || meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1)
                    return CodeMirror.Pass;
            
                  var pos = state.indent.length - 1, rules = states[state.state];
                  scan: for (;;) {
                    for (var i = 0; i < rules.length; i++) {
                      var rule = rules[i];
                      if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {
                        var m = rule.regex.exec(textAfter);
                        if (m && m[0]) {
                          pos--;
                          if (rule.next || rule.push) rules = states[rule.next || rule.push];
                          textAfter = textAfter.slice(m[0].length);
                          continue scan;
                        }
                      }
                    }
                    break;
                  }
                  return pos < 0 ? 0 : state.indent[pos];
                };
              }
            });
            
        • runmode
          • colorize.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("./runmode"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "./runmode"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var isBlock = /^(p|li|div|h\\d|pre|blockquote|td)$/;
            
              function textContent(node, out) {
                if (node.nodeType == 3) return out.push(node.nodeValue);
                for (var ch = node.firstChild; ch; ch = ch.nextSibling) {
                  textContent(ch, out);
                  if (isBlock.test(node.nodeType)) out.push("\n");
                }
              }
            
              CodeMirror.colorize = function(collection, defaultMode) {
                if (!collection) collection = document.body.getElementsByTagName("pre");
            
                for (var i = 0; i < collection.length; ++i) {
                  var node = collection[i];
                  var mode = node.getAttribute("data-lang") || defaultMode;
                  if (!mode) continue;
            
                  var text = [];
                  textContent(node, text);
                  node.innerHTML = "";
                  CodeMirror.runMode(text.join(""), mode, node);
            
                  node.className += " cm-s-default";
                }
              };
            });
            
          • runmode-standalone.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            window.CodeMirror = {};
            
            (function() {
            "use strict";
            
            function splitLines(string){ return string.split(/\r?\n|\r/); };
            
            function StringStream(string) {
              this.pos = this.start = 0;
              this.string = string;
              this.lineStart = 0;
            }
            StringStream.prototype = {
              eol: function() {return this.pos >= this.string.length;},
              sol: function() {return this.pos == 0;},
              peek: function() {return this.string.charAt(this.pos) || null;},
              next: function() {
                if (this.pos < this.string.length)
                  return this.string.charAt(this.pos++);
              },
              eat: function(match) {
                var ch = this.string.charAt(this.pos);
                if (typeof match == "string") var ok = ch == match;
                else var ok = ch && (match.test ? match.test(ch) : match(ch));
                if (ok) {++this.pos; return ch;}
              },
              eatWhile: function(match) {
                var start = this.pos;
                while (this.eat(match)){}
                return this.pos > start;
              },
              eatSpace: function() {
                var start = this.pos;
                while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
                return this.pos > start;
              },
              skipToEnd: function() {this.pos = this.string.length;},
              skipTo: function(ch) {
                var found = this.string.indexOf(ch, this.pos);
                if (found > -1) {this.pos = found; return true;}
              },
              backUp: function(n) {this.pos -= n;},
              column: function() {return this.start - this.lineStart;},
              indentation: function() {return 0;},
              match: function(pattern, consume, caseInsensitive) {
                if (typeof pattern == "string") {
                  var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
                  var substr = this.string.substr(this.pos, pattern.length);
                  if (cased(substr) == cased(pattern)) {
                    if (consume !== false) this.pos += pattern.length;
                    return true;
                  }
                } else {
                  var match = this.string.slice(this.pos).match(pattern);
                  if (match && match.index > 0) return null;
                  if (match && consume !== false) this.pos += match[0].length;
                  return match;
                }
              },
              current: function(){return this.string.slice(this.start, this.pos);},
              hideFirstChars: function(n, inner) {
                this.lineStart += n;
                try { return inner(); }
                finally { this.lineStart -= n; }
              }
            };
            CodeMirror.StringStream = StringStream;
            
            CodeMirror.startState = function (mode, a1, a2) {
              return mode.startState ? mode.startState(a1, a2) : true;
            };
            
            var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
            CodeMirror.defineMode = function (name, mode) {
              if (arguments.length > 2)
                mode.dependencies = Array.prototype.slice.call(arguments, 2);
              modes[name] = mode;
            };
            CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; };
            CodeMirror.resolveMode = function(spec) {
              if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
                spec = mimeModes[spec];
              } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
                spec = mimeModes[spec.name];
              }
              if (typeof spec == "string") return {name: spec};
              else return spec || {name: "null"};
            };
            CodeMirror.getMode = function (options, spec) {
              spec = CodeMirror.resolveMode(spec);
              var mfactory = modes[spec.name];
              if (!mfactory) throw new Error("Unknown mode: " + spec);
              return mfactory(options, spec);
            };
            CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min;
            CodeMirror.defineMode("null", function() {
              return {token: function(stream) {stream.skipToEnd();}};
            });
            CodeMirror.defineMIME("text/plain", "null");
            
            CodeMirror.runMode = function (string, modespec, callback, options) {
              var mode = CodeMirror.getMode({ indentUnit: 2 }, modespec);
            
              if (callback.nodeType == 1) {
                var tabSize = (options && options.tabSize) || 4;
                var node = callback, col = 0;
                node.innerHTML = "";
                callback = function (text, style) {
                  if (text == "\n") {
                    node.appendChild(document.createElement("br"));
                    col = 0;
                    return;
                  }
                  var content = "";
                  // replace tabs
                  for (var pos = 0; ;) {
                    var idx = text.indexOf("\t", pos);
                    if (idx == -1) {
                      content += text.slice(pos);
                      col += text.length - pos;
                      break;
                    } else {
                      col += idx - pos;
                      content += text.slice(pos, idx);
                      var size = tabSize - col % tabSize;
                      col += size;
                      for (var i = 0; i < size; ++i) content += " ";
                      pos = idx + 1;
                    }
                  }
            
                  if (style) {
                    var sp = node.appendChild(document.createElement("span"));
                    sp.className = "cm-" + style.replace(/ +/g, " cm-");
                    sp.appendChild(document.createTextNode(content));
                  } else {
                    node.appendChild(document.createTextNode(content));
                  }
                };
              }
            
              var lines = splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
              for (var i = 0, e = lines.length; i < e; ++i) {
                if (i) callback("\n");
                var stream = new CodeMirror.StringStream(lines[i]);
                if (!stream.string && mode.blankLine) mode.blankLine(state);
                while (!stream.eol()) {
                  var style = mode.token(stream, state);
                  callback(stream.current(), style, i, stream.start, state);
                  stream.start = stream.pos;
                }
              }
            };
            })();
            
          • runmode.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.runMode = function(string, modespec, callback, options) {
              var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
              var ie = /MSIE \d/.test(navigator.userAgent);
              var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
            
              if (callback.nodeType == 1) {
                var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
                var node = callback, col = 0;
                node.innerHTML = "";
                callback = function(text, style) {
                  if (text == "\n") {
                    // Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
                    // Emitting a carriage return makes everything ok.
                    node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
                    col = 0;
                    return;
                  }
                  var content = "";
                  // replace tabs
                  for (var pos = 0;;) {
                    var idx = text.indexOf("\t", pos);
                    if (idx == -1) {
                      content += text.slice(pos);
                      col += text.length - pos;
                      break;
                    } else {
                      col += idx - pos;
                      content += text.slice(pos, idx);
                      var size = tabSize - col % tabSize;
                      col += size;
                      for (var i = 0; i < size; ++i) content += " ";
                      pos = idx + 1;
                    }
                  }
            
                  if (style) {
                    var sp = node.appendChild(document.createElement("span"));
                    sp.className = "cm-" + style.replace(/ +/g, " cm-");
                    sp.appendChild(document.createTextNode(content));
                  } else {
                    node.appendChild(document.createTextNode(content));
                  }
                };
              }
            
              var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
              for (var i = 0, e = lines.length; i < e; ++i) {
                if (i) callback("\n");
                var stream = new CodeMirror.StringStream(lines[i]);
                if (!stream.string && mode.blankLine) mode.blankLine(state);
                while (!stream.eol()) {
                  var style = mode.token(stream, state);
                  callback(stream.current(), style, i, stream.start, state);
                  stream.start = stream.pos;
                }
              }
            };
            
            });
            
          • runmode.node.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /* Just enough of CodeMirror to run runMode under node.js */
            
            // declare global: StringStream
            
            function splitLines(string){ return string.split(/\r?\n|\r/); };
            
            function StringStream(string) {
              this.pos = this.start = 0;
              this.string = string;
              this.lineStart = 0;
            }
            StringStream.prototype = {
              eol: function() {return this.pos >= this.string.length;},
              sol: function() {return this.pos == 0;},
              peek: function() {return this.string.charAt(this.pos) || null;},
              next: function() {
                if (this.pos < this.string.length)
                  return this.string.charAt(this.pos++);
              },
              eat: function(match) {
                var ch = this.string.charAt(this.pos);
                if (typeof match == "string") var ok = ch == match;
                else var ok = ch && (match.test ? match.test(ch) : match(ch));
                if (ok) {++this.pos; return ch;}
              },
              eatWhile: function(match) {
                var start = this.pos;
                while (this.eat(match)){}
                return this.pos > start;
              },
              eatSpace: function() {
                var start = this.pos;
                while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
                return this.pos > start;
              },
              skipToEnd: function() {this.pos = this.string.length;},
              skipTo: function(ch) {
                var found = this.string.indexOf(ch, this.pos);
                if (found > -1) {this.pos = found; return true;}
              },
              backUp: function(n) {this.pos -= n;},
              column: function() {return this.start - this.lineStart;},
              indentation: function() {return 0;},
              match: function(pattern, consume, caseInsensitive) {
                if (typeof pattern == "string") {
                  var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
                  var substr = this.string.substr(this.pos, pattern.length);
                  if (cased(substr) == cased(pattern)) {
                    if (consume !== false) this.pos += pattern.length;
                    return true;
                  }
                } else {
                  var match = this.string.slice(this.pos).match(pattern);
                  if (match && match.index > 0) return null;
                  if (match && consume !== false) this.pos += match[0].length;
                  return match;
                }
              },
              current: function(){return this.string.slice(this.start, this.pos);},
              hideFirstChars: function(n, inner) {
                this.lineStart += n;
                try { return inner(); }
                finally { this.lineStart -= n; }
              }
            };
            exports.StringStream = StringStream;
            
            exports.startState = function(mode, a1, a2) {
              return mode.startState ? mode.startState(a1, a2) : true;
            };
            
            var modes = exports.modes = {}, mimeModes = exports.mimeModes = {};
            exports.defineMode = function(name, mode) {
              if (arguments.length > 2)
                mode.dependencies = Array.prototype.slice.call(arguments, 2);
              modes[name] = mode;
            };
            exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; };
            
            exports.defineMode("null", function() {
              return {token: function(stream) {stream.skipToEnd();}};
            });
            exports.defineMIME("text/plain", "null");
            
            exports.resolveMode = function(spec) {
              if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
                spec = mimeModes[spec];
              } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
                spec = mimeModes[spec.name];
              }
              if (typeof spec == "string") return {name: spec};
              else return spec || {name: "null"};
            };
            exports.getMode = function(options, spec) {
              spec = exports.resolveMode(spec);
              var mfactory = modes[spec.name];
              if (!mfactory) throw new Error("Unknown mode: " + spec);
              return mfactory(options, spec);
            };
            exports.registerHelper = exports.registerGlobalHelper = Math.min;
            
            exports.runMode = function(string, modespec, callback, options) {
              var mode = exports.getMode({indentUnit: 2}, modespec);
              var lines = splitLines(string), state = (options && options.state) || exports.startState(mode);
              for (var i = 0, e = lines.length; i < e; ++i) {
                if (i) callback("\n");
                var stream = new exports.StringStream(lines[i]);
                if (!stream.string && mode.blankLine) mode.blankLine(state);
                while (!stream.eol()) {
                  var style = mode.token(stream, state);
                  callback(stream.current(), style, i, stream.start, state);
                  stream.start = stream.pos;
                }
              }
            };
            
            require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")];
            
        • scroll
          • annotatescrollbar.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineExtension("annotateScrollbar", function(options) {
                if (typeof options == "string") options = {className: options};
                return new Annotation(this, options);
              });
            
              CodeMirror.defineOption("scrollButtonHeight", 0);
            
              function Annotation(cm, options) {
                this.cm = cm;
                this.options = options;
                this.buttonHeight = options.scrollButtonHeight || cm.getOption("scrollButtonHeight");
                this.annotations = [];
                this.doRedraw = this.doUpdate = null;
                this.div = cm.getWrapperElement().appendChild(document.createElement("div"));
                this.div.style.cssText = "position: absolute; right: 0; top: 0; z-index: 7; pointer-events: none";
                this.computeScale();
            
                function scheduleRedraw(delay) {
                  clearTimeout(self.doRedraw);
                  self.doRedraw = setTimeout(function() { self.redraw(); }, delay);
                }
            
                var self = this;
                cm.on("refresh", this.resizeHandler = function() {
                  clearTimeout(self.doUpdate);
                  self.doUpdate = setTimeout(function() {
                    if (self.computeScale()) scheduleRedraw(20);
                  }, 100);
                });
                cm.on("markerAdded", this.resizeHandler);
                cm.on("markerCleared", this.resizeHandler);
                if (options.listenForChanges !== false)
                  cm.on("change", this.changeHandler = function() {
                    scheduleRedraw(250);
                  });
              }
            
              Annotation.prototype.computeScale = function() {
                var cm = this.cm;
                var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight - this.buttonHeight * 2) /
                  cm.heightAtLine(cm.lastLine() + 1, "local");
                if (hScale != this.hScale) {
                  this.hScale = hScale;
                  return true;
                }
              };
            
              Annotation.prototype.update = function(annotations) {
                this.annotations = annotations;
                this.redraw();
              };
            
              Annotation.prototype.redraw = function(compute) {
                if (compute !== false) this.computeScale();
                var cm = this.cm, hScale = this.hScale;
            
                var frag = document.createDocumentFragment(), anns = this.annotations;
            
                var wrapping = cm.getOption("lineWrapping");
                var singleLineH = wrapping && cm.defaultTextHeight() * 1.5;
                var curLine = null, curLineObj = null;
                function getY(pos, top) {
                  if (curLine != pos.line) {
                    curLine = pos.line;
                    curLineObj = cm.getLineHandle(curLine);
                  }
                  if (wrapping && curLineObj.height > singleLineH)
                    return cm.charCoords(pos, "local")[top ? "top" : "bottom"];
                  var topY = cm.heightAtLine(curLineObj, "local");
                  return topY + (top ? 0 : curLineObj.height);
                }
            
                if (cm.display.barWidth) for (var i = 0, nextTop; i < anns.length; i++) {
                  var ann = anns[i];
                  var top = nextTop || getY(ann.from, true) * hScale;
                  var bottom = getY(ann.to, false) * hScale;
                  while (i < anns.length - 1) {
                    nextTop = getY(anns[i + 1].from, true) * hScale;
                    if (nextTop > bottom + .9) break;
                    ann = anns[++i];
                    bottom = getY(ann.to, false) * hScale;
                  }
                  if (bottom == top) continue;
                  var height = Math.max(bottom - top, 3);
            
                  var elt = frag.appendChild(document.createElement("div"));
                  elt.style.cssText = "position: absolute; right: 0px; width: " + Math.max(cm.display.barWidth - 1, 2) + "px; top: "
                    + (top + this.buttonHeight) + "px; height: " + height + "px";
                  elt.className = this.options.className;
                }
                this.div.textContent = "";
                this.div.appendChild(frag);
              };
            
              Annotation.prototype.clear = function() {
                this.cm.off("refresh", this.resizeHandler);
                this.cm.off("markerAdded", this.resizeHandler);
                this.cm.off("markerCleared", this.resizeHandler);
                if (this.changeHandler) this.cm.off("change", this.changeHandler);
                this.div.parentNode.removeChild(this.div);
              };
            });
            
          • scrollpastend.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("scrollPastEnd", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init) {
                  cm.off("change", onChange);
                  cm.off("refresh", updateBottomMargin);
                  cm.display.lineSpace.parentNode.style.paddingBottom = "";
                  cm.state.scrollPastEndPadding = null;
                }
                if (val) {
                  cm.on("change", onChange);
                  cm.on("refresh", updateBottomMargin);
                  updateBottomMargin(cm);
                }
              });
            
              function onChange(cm, change) {
                if (CodeMirror.changeEnd(change).line == cm.lastLine())
                  updateBottomMargin(cm);
              }
            
              function updateBottomMargin(cm) {
                var padding = "";
                if (cm.lineCount() > 1) {
                  var totalH = cm.display.scroller.clientHeight - 30,
                      lastLineH = cm.getLineHandle(cm.lastLine()).height;
                  padding = (totalH - lastLineH) + "px";
                }
                if (cm.state.scrollPastEndPadding != padding) {
                  cm.state.scrollPastEndPadding = padding;
                  cm.display.lineSpace.parentNode.style.paddingBottom = padding;
                  cm.setSize();
                }
              }
            });
            
          • simplescrollbars.css
            .CodeMirror-simplescroll-horizontal div, .CodeMirror-simplescroll-vertical div {
              position: absolute;
              background: #ccc;
              -moz-box-sizing: border-box;
              box-sizing: border-box;
              border: 1px solid #bbb;
              border-radius: 2px;
            }
            
            .CodeMirror-simplescroll-horizontal, .CodeMirror-simplescroll-vertical {
              position: absolute;
              z-index: 6;
              background: #eee;
            }
            
            .CodeMirror-simplescroll-horizontal {
              bottom: 0; left: 0;
              height: 8px;
            }
            .CodeMirror-simplescroll-horizontal div {
              bottom: 0;
              height: 100%;
            }
            
            .CodeMirror-simplescroll-vertical {
              right: 0; top: 0;
              width: 8px;
            }
            .CodeMirror-simplescroll-vertical div {
              right: 0;
              width: 100%;
            }
            
            
            .CodeMirror-overlayscroll .CodeMirror-scrollbar-filler, .CodeMirror-overlayscroll .CodeMirror-gutter-filler {
              display: none;
            }
            
            .CodeMirror-overlayscroll-horizontal div, .CodeMirror-overlayscroll-vertical div {
              position: absolute;
              background: #bcd;
              border-radius: 3px;
            }
            
            .CodeMirror-overlayscroll-horizontal, .CodeMirror-overlayscroll-vertical {
              position: absolute;
              z-index: 6;
            }
            
            .CodeMirror-overlayscroll-horizontal {
              bottom: 0; left: 0;
              height: 6px;
            }
            .CodeMirror-overlayscroll-horizontal div {
              bottom: 0;
              height: 100%;
            }
            
            .CodeMirror-overlayscroll-vertical {
              right: 0; top: 0;
              width: 6px;
            }
            .CodeMirror-overlayscroll-vertical div {
              right: 0;
              width: 100%;
            }
            
          • simplescrollbars.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              function Bar(cls, orientation, scroll) {
                this.orientation = orientation;
                this.scroll = scroll;
                this.screen = this.total = this.size = 1;
                this.pos = 0;
            
                this.node = document.createElement("div");
                this.node.className = cls + "-" + orientation;
                this.inner = this.node.appendChild(document.createElement("div"));
            
                var self = this;
                CodeMirror.on(this.inner, "mousedown", function(e) {
                  if (e.which != 1) return;
                  CodeMirror.e_preventDefault(e);
                  var axis = self.orientation == "horizontal" ? "pageX" : "pageY";
                  var start = e[axis], startpos = self.pos;
                  function done() {
                    CodeMirror.off(document, "mousemove", move);
                    CodeMirror.off(document, "mouseup", done);
                  }
                  function move(e) {
                    if (e.which != 1) return done();
                    self.moveTo(startpos + (e[axis] - start) * (self.total / self.size));
                  }
                  CodeMirror.on(document, "mousemove", move);
                  CodeMirror.on(document, "mouseup", done);
                });
            
                CodeMirror.on(this.node, "click", function(e) {
                  CodeMirror.e_preventDefault(e);
                  var innerBox = self.inner.getBoundingClientRect(), where;
                  if (self.orientation == "horizontal")
                    where = e.clientX < innerBox.left ? -1 : e.clientX > innerBox.right ? 1 : 0;
                  else
                    where = e.clientY < innerBox.top ? -1 : e.clientY > innerBox.bottom ? 1 : 0;
                  self.moveTo(self.pos + where * self.screen);
                });
            
                function onWheel(e) {
                  var moved = CodeMirror.wheelEventPixels(e)[self.orientation == "horizontal" ? "x" : "y"];
                  var oldPos = self.pos;
                  self.moveTo(self.pos + moved);
                  if (self.pos != oldPos) CodeMirror.e_preventDefault(e);
                }
                CodeMirror.on(this.node, "mousewheel", onWheel);
                CodeMirror.on(this.node, "DOMMouseScroll", onWheel);
              }
            
              Bar.prototype.moveTo = function(pos, update) {
                if (pos < 0) pos = 0;
                if (pos > this.total - this.screen) pos = this.total - this.screen;
                if (pos == this.pos) return;
                this.pos = pos;
                this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
                  (pos * (this.size / this.total)) + "px";
                if (update !== false) this.scroll(pos, this.orientation);
              };
            
              var minButtonSize = 10;
            
              Bar.prototype.update = function(scrollSize, clientSize, barSize) {
                this.screen = clientSize;
                this.total = scrollSize;
                this.size = barSize;
            
                var buttonSize = this.screen * (this.size / this.total);
                if (buttonSize < minButtonSize) {
                  this.size -= minButtonSize - buttonSize;
                  buttonSize = minButtonSize;
                }
                this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
                  buttonSize + "px";
                this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
                  this.pos * (this.size / this.total) + "px";
              };
            
              function SimpleScrollbars(cls, place, scroll) {
                this.addClass = cls;
                this.horiz = new Bar(cls, "horizontal", scroll);
                place(this.horiz.node);
                this.vert = new Bar(cls, "vertical", scroll);
                place(this.vert.node);
                this.width = null;
              }
            
              SimpleScrollbars.prototype.update = function(measure) {
                if (this.width == null) {
                  var style = window.getComputedStyle ? window.getComputedStyle(this.horiz.node) : this.horiz.node.currentStyle;
                  if (style) this.width = parseInt(style.height);
                }
                var width = this.width || 0;
            
                var needsH = measure.scrollWidth > measure.clientWidth + 1;
                var needsV = measure.scrollHeight > measure.clientHeight + 1;
                this.vert.node.style.display = needsV ? "block" : "none";
                this.horiz.node.style.display = needsH ? "block" : "none";
            
                if (needsV) {
                  this.vert.update(measure.scrollHeight, measure.clientHeight,
                                   measure.viewHeight - (needsH ? width : 0));
                  this.vert.node.style.display = "block";
                  this.vert.node.style.bottom = needsH ? width + "px" : "0";
                }
                if (needsH) {
                  this.horiz.update(measure.scrollWidth, measure.clientWidth,
                                    measure.viewWidth - (needsV ? width : 0) - measure.barLeft);
                  this.horiz.node.style.right = needsV ? width + "px" : "0";
                  this.horiz.node.style.left = measure.barLeft + "px";
                }
            
                return {right: needsV ? width : 0, bottom: needsH ? width : 0};
              };
            
              SimpleScrollbars.prototype.setScrollTop = function(pos) {
                this.vert.moveTo(pos, false);
              };
            
              SimpleScrollbars.prototype.setScrollLeft = function(pos) {
                this.horiz.moveTo(pos, false);
              };
            
              SimpleScrollbars.prototype.clear = function() {
                var parent = this.horiz.node.parentNode;
                parent.removeChild(this.horiz.node);
                parent.removeChild(this.vert.node);
              };
            
              CodeMirror.scrollbarModel.simple = function(place, scroll) {
                return new SimpleScrollbars("CodeMirror-simplescroll", place, scroll);
              };
              CodeMirror.scrollbarModel.overlay = function(place, scroll) {
                return new SimpleScrollbars("CodeMirror-overlayscroll", place, scroll);
              };
            });
            
        • search
          • match-highlighter.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Highlighting text that matches the selection
            //
            // Defines an option highlightSelectionMatches, which, when enabled,
            // will style strings that match the selection throughout the
            // document.
            //
            // The option can be set to true to simply enable it, or to a
            // {minChars, style, wordsOnly, showToken, delay} object to explicitly
            // configure it. minChars is the minimum amount of characters that should be
            // selected for the behavior to occur, and style is the token style to
            // apply to the matches. This will be prefixed by "cm-" to create an
            // actual CSS class name. If wordsOnly is enabled, the matches will be
            // highlighted only if the selected text is a word. showToken, when enabled,
            // will cause the current token to be highlighted when nothing is selected.
            // delay is used to specify how much time to wait, in milliseconds, before
            // highlighting the matches.
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var DEFAULT_MIN_CHARS = 2;
              var DEFAULT_TOKEN_STYLE = "matchhighlight";
              var DEFAULT_DELAY = 100;
              var DEFAULT_WORDS_ONLY = false;
            
              function State(options) {
                if (typeof options == "object") {
                  this.minChars = options.minChars;
                  this.style = options.style;
                  this.showToken = options.showToken;
                  this.delay = options.delay;
                  this.wordsOnly = options.wordsOnly;
                }
                if (this.style == null) this.style = DEFAULT_TOKEN_STYLE;
                if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS;
                if (this.delay == null) this.delay = DEFAULT_DELAY;
                if (this.wordsOnly == null) this.wordsOnly = DEFAULT_WORDS_ONLY;
                this.overlay = this.timeout = null;
              }
            
              CodeMirror.defineOption("highlightSelectionMatches", false, function(cm, val, old) {
                if (old && old != CodeMirror.Init) {
                  var over = cm.state.matchHighlighter.overlay;
                  if (over) cm.removeOverlay(over);
                  clearTimeout(cm.state.matchHighlighter.timeout);
                  cm.state.matchHighlighter = null;
                  cm.off("cursorActivity", cursorActivity);
                }
                if (val) {
                  cm.state.matchHighlighter = new State(val);
                  highlightMatches(cm);
                  cm.on("cursorActivity", cursorActivity);
                }
              });
            
              function cursorActivity(cm) {
                var state = cm.state.matchHighlighter;
                clearTimeout(state.timeout);
                state.timeout = setTimeout(function() {highlightMatches(cm);}, state.delay);
              }
            
              function highlightMatches(cm) {
                cm.operation(function() {
                  var state = cm.state.matchHighlighter;
                  if (state.overlay) {
                    cm.removeOverlay(state.overlay);
                    state.overlay = null;
                  }
                  if (!cm.somethingSelected() && state.showToken) {
                    var re = state.showToken === true ? /[\w$]/ : state.showToken;
                    var cur = cm.getCursor(), line = cm.getLine(cur.line), start = cur.ch, end = start;
                    while (start && re.test(line.charAt(start - 1))) --start;
                    while (end < line.length && re.test(line.charAt(end))) ++end;
                    if (start < end)
                      cm.addOverlay(state.overlay = makeOverlay(line.slice(start, end), re, state.style));
                    return;
                  }
                  var from = cm.getCursor("from"), to = cm.getCursor("to");
                  if (from.line != to.line) return;
                  if (state.wordsOnly && !isWord(cm, from, to)) return;
                  var selection = cm.getRange(from, to).replace(/^\s+|\s+$/g, "");
                  if (selection.length >= state.minChars)
                    cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style));
                });
              }
            
              function isWord(cm, from, to) {
                var str = cm.getRange(from, to);
                if (str.match(/^\w+$/) !== null) {
                    if (from.ch > 0) {
                        var pos = {line: from.line, ch: from.ch - 1};
                        var chr = cm.getRange(pos, from);
                        if (chr.match(/\W/) === null) return false;
                    }
                    if (to.ch < cm.getLine(from.line).length) {
                        var pos = {line: to.line, ch: to.ch + 1};
                        var chr = cm.getRange(to, pos);
                        if (chr.match(/\W/) === null) return false;
                    }
                    return true;
                } else return false;
              }
            
              function boundariesAround(stream, re) {
                return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) &&
                  (stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos)));
              }
            
              function makeOverlay(query, hasBoundary, style) {
                return {token: function(stream) {
                  if (stream.match(query) &&
                      (!hasBoundary || boundariesAround(stream, hasBoundary)))
                    return style;
                  stream.next();
                  stream.skipTo(query.charAt(0)) || stream.skipToEnd();
                }};
              }
            });
            
          • matchesonscrollbar.css
            .CodeMirror-search-match {
              background: gold;
              border-top: 1px solid orange;
              border-bottom: 1px solid orange;
              -moz-box-sizing: border-box;
              box-sizing: border-box;
              opacity: .5;
            }
            
          • matchesonscrollbar.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("./searchcursor"), require("../scroll/annotatescrollbar"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "./searchcursor", "../scroll/annotatescrollbar"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, options) {
                if (typeof options == "string") options = {className: options};
                if (!options) options = {};
                return new SearchAnnotation(this, query, caseFold, options);
              });
            
              function SearchAnnotation(cm, query, caseFold, options) {
                this.cm = cm;
                this.options = options;
                var annotateOptions = {listenForChanges: false};
                for (var prop in options) annotateOptions[prop] = options[prop];
                if (!annotateOptions.className) annotateOptions.className = "CodeMirror-search-match";
                this.annotation = cm.annotateScrollbar(annotateOptions);
                this.query = query;
                this.caseFold = caseFold;
                this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1};
                this.matches = [];
                this.update = null;
            
                this.findMatches();
                this.annotation.update(this.matches);
            
                var self = this;
                cm.on("change", this.changeHandler = function(_cm, change) { self.onChange(change); });
              }
            
              var MAX_MATCHES = 1000;
            
              SearchAnnotation.prototype.findMatches = function() {
                if (!this.gap) return;
                for (var i = 0; i < this.matches.length; i++) {
                  var match = this.matches[i];
                  if (match.from.line >= this.gap.to) break;
                  if (match.to.line >= this.gap.from) this.matches.splice(i--, 1);
                }
                var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), this.caseFold);
                var maxMatches = this.options && this.options.maxMatches || MAX_MATCHES;
                while (cursor.findNext()) {
                  var match = {from: cursor.from(), to: cursor.to()};
                  if (match.from.line >= this.gap.to) break;
                  this.matches.splice(i++, 0, match);
                  if (this.matches.length > maxMatches) break;
                }
                this.gap = null;
              };
            
              function offsetLine(line, changeStart, sizeChange) {
                if (line <= changeStart) return line;
                return Math.max(changeStart, line + sizeChange);
              }
            
              SearchAnnotation.prototype.onChange = function(change) {
                var startLine = change.from.line;
                var endLine = CodeMirror.changeEnd(change).line;
                var sizeChange = endLine - change.to.line;
                if (this.gap) {
                  this.gap.from = Math.min(offsetLine(this.gap.from, startLine, sizeChange), change.from.line);
                  this.gap.to = Math.max(offsetLine(this.gap.to, startLine, sizeChange), change.from.line);
                } else {
                  this.gap = {from: change.from.line, to: endLine + 1};
                }
            
                if (sizeChange) for (var i = 0; i < this.matches.length; i++) {
                  var match = this.matches[i];
                  var newFrom = offsetLine(match.from.line, startLine, sizeChange);
                  if (newFrom != match.from.line) match.from = CodeMirror.Pos(newFrom, match.from.ch);
                  var newTo = offsetLine(match.to.line, startLine, sizeChange);
                  if (newTo != match.to.line) match.to = CodeMirror.Pos(newTo, match.to.ch);
                }
                clearTimeout(this.update);
                var self = this;
                this.update = setTimeout(function() { self.updateAfterChange(); }, 250);
              };
            
              SearchAnnotation.prototype.updateAfterChange = function() {
                this.findMatches();
                this.annotation.update(this.matches);
              };
            
              SearchAnnotation.prototype.clear = function() {
                this.cm.off("change", this.changeHandler);
                this.annotation.clear();
              };
            });
            
          • search.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Define search commands. Depends on dialog.js or another
            // implementation of the openDialog method.
            
            // Replace works a little oddly -- it will do the replace on the next
            // Ctrl-G (or whatever is bound to findNext) press. You prevent a
            // replace by making sure the match is no longer selected when hitting
            // Ctrl-G.
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              function searchOverlay(query, caseInsensitive) {
                if (typeof query == "string")
                  query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
                else if (!query.global)
                  query = new RegExp(query.source, query.ignoreCase ? "gi" : "g");
            
                return {token: function(stream) {
                  query.lastIndex = stream.pos;
                  var match = query.exec(stream.string);
                  if (match && match.index == stream.pos) {
                    stream.pos += match[0].length;
                    return "searching";
                  } else if (match) {
                    stream.pos = match.index;
                  } else {
                    stream.skipToEnd();
                  }
                }};
              }
            
              function SearchState() {
                this.posFrom = this.posTo = this.lastQuery = this.query = null;
                this.overlay = null;
              }
              function getSearchState(cm) {
                return cm.state.search || (cm.state.search = new SearchState());
              }
              function queryCaseInsensitive(query) {
                return typeof query == "string" && query == query.toLowerCase();
              }
              function getSearchCursor(cm, query, pos) {
                // Heuristic: if the query string is all lowercase, do a case insensitive search.
                return cm.getSearchCursor(query, pos, queryCaseInsensitive(query));
              }
              function dialog(cm, text, shortText, deflt, f) {
                if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true});
                else f(prompt(shortText, deflt));
              }
              function confirmDialog(cm, text, shortText, fs) {
                if (cm.openConfirm) cm.openConfirm(text, fs);
                else if (confirm(shortText)) fs[0]();
              }
              function parseQuery(query) {
                var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
                if (isRE) {
                  try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
                  catch(e) {} // Not a regular expression after all, do a string search
                }
                if (typeof query == "string" ? query == "" : query.test(""))
                  query = /x^/;
                return query;
              }
              var queryDialog =
                'Search: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
              function doSearch(cm, rev) {
                var state = getSearchState(cm);
                if (state.query) return findNext(cm, rev);
                var q = cm.getSelection() || state.lastQuery;
                dialog(cm, queryDialog, "Search for:", q, function(query) {
                  cm.operation(function() {
                    if (!query || state.query) return;
                    state.query = parseQuery(query);
                    cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
                    state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
                    cm.addOverlay(state.overlay);
                    if (cm.showMatchesOnScrollbar) {
                      if (state.annotate) { state.annotate.clear(); state.annotate = null; }
                      state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
                    }
                    state.posFrom = state.posTo = cm.getCursor();
                    findNext(cm, rev);
                  });
                });
              }
              function findNext(cm, rev) {cm.operation(function() {
                var state = getSearchState(cm);
                var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
                if (!cursor.find(rev)) {
                  cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0));
                  if (!cursor.find(rev)) return;
                }
                cm.setSelection(cursor.from(), cursor.to());
                cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
                state.posFrom = cursor.from(); state.posTo = cursor.to();
              });}
              function clearSearch(cm) {cm.operation(function() {
                var state = getSearchState(cm);
                state.lastQuery = state.query;
                if (!state.query) return;
                state.query = null;
                cm.removeOverlay(state.overlay);
                if (state.annotate) { state.annotate.clear(); state.annotate = null; }
              });}
            
              var replaceQueryDialog =
                'Replace: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
              var replacementQueryDialog = 'With: <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
              var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
              function replace(cm, all) {
                if (cm.getOption("readOnly")) return;
                var query = cm.getSelection() || getSearchState(cm).lastQuery;
                dialog(cm, replaceQueryDialog, "Replace:", query, function(query) {
                  if (!query) return;
                  query = parseQuery(query);
                  dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
                    if (all) {
                      cm.operation(function() {
                        for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
                          if (typeof query != "string") {
                            var match = cm.getRange(cursor.from(), cursor.to()).match(query);
                            cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
                          } else cursor.replace(text);
                        }
                      });
                    } else {
                      clearSearch(cm);
                      var cursor = getSearchCursor(cm, query, cm.getCursor());
                      var advance = function() {
                        var start = cursor.from(), match;
                        if (!(match = cursor.findNext())) {
                          cursor = getSearchCursor(cm, query);
                          if (!(match = cursor.findNext()) ||
                              (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
                        }
                        cm.setSelection(cursor.from(), cursor.to());
                        cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
                        confirmDialog(cm, doReplaceConfirm, "Replace?",
                                      [function() {doReplace(match);}, advance]);
                      };
                      var doReplace = function(match) {
                        cursor.replace(typeof query == "string" ? text :
                                       text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
                        advance();
                      };
                      advance();
                    }
                  });
                });
              }
            
              CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
              CodeMirror.commands.findNext = doSearch;
              CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
              CodeMirror.commands.clearSearch = clearSearch;
              CodeMirror.commands.replace = replace;
              CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
            });
            
          • searchcursor.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              var Pos = CodeMirror.Pos;
            
              function SearchCursor(doc, query, pos, caseFold) {
                this.atOccurrence = false; this.doc = doc;
                if (caseFold == null && typeof query == "string") caseFold = false;
            
                pos = pos ? doc.clipPos(pos) : Pos(0, 0);
                this.pos = {from: pos, to: pos};
            
                // The matches method is filled in based on the type of query.
                // It takes a position and a direction, and returns an object
                // describing the next occurrence of the query, or null if no
                // more matches were found.
                if (typeof query != "string") { // Regexp match
                  if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g");
                  this.matches = function(reverse, pos) {
                    if (reverse) {
                      query.lastIndex = 0;
                      var line = doc.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start;
                      for (;;) {
                        query.lastIndex = cutOff;
                        var newMatch = query.exec(line);
                        if (!newMatch) break;
                        match = newMatch;
                        start = match.index;
                        cutOff = match.index + (match[0].length || 1);
                        if (cutOff == line.length) break;
                      }
                      var matchLen = (match && match[0].length) || 0;
                      if (!matchLen) {
                        if (start == 0 && line.length == 0) {match = undefined;}
                        else if (start != doc.getLine(pos.line).length) {
                          matchLen++;
                        }
                      }
                    } else {
                      query.lastIndex = pos.ch;
                      var line = doc.getLine(pos.line), match = query.exec(line);
                      var matchLen = (match && match[0].length) || 0;
                      var start = match && match.index;
                      if (start + matchLen != line.length && !matchLen) matchLen = 1;
                    }
                    if (match && matchLen)
                      return {from: Pos(pos.line, start),
                              to: Pos(pos.line, start + matchLen),
                              match: match};
                  };
                } else { // String query
                  var origQuery = query;
                  if (caseFold) query = query.toLowerCase();
                  var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
                  var target = query.split("\n");
                  // Different methods for single-line and multi-line queries
                  if (target.length == 1) {
                    if (!query.length) {
                      // Empty string would match anything and never progress, so
                      // we define it to match nothing instead.
                      this.matches = function() {};
                    } else {
                      this.matches = function(reverse, pos) {
                        if (reverse) {
                          var orig = doc.getLine(pos.line).slice(0, pos.ch), line = fold(orig);
                          var match = line.lastIndexOf(query);
                          if (match > -1) {
                            match = adjustPos(orig, line, match);
                            return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)};
                          }
                         } else {
                           var orig = doc.getLine(pos.line).slice(pos.ch), line = fold(orig);
                           var match = line.indexOf(query);
                           if (match > -1) {
                             match = adjustPos(orig, line, match) + pos.ch;
                             return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)};
                           }
                        }
                      };
                    }
                  } else {
                    var origTarget = origQuery.split("\n");
                    this.matches = function(reverse, pos) {
                      var last = target.length - 1;
                      if (reverse) {
                        if (pos.line - (target.length - 1) < doc.firstLine()) return;
                        if (fold(doc.getLine(pos.line).slice(0, origTarget[last].length)) != target[target.length - 1]) return;
                        var to = Pos(pos.line, origTarget[last].length);
                        for (var ln = pos.line - 1, i = last - 1; i >= 1; --i, --ln)
                          if (target[i] != fold(doc.getLine(ln))) return;
                        var line = doc.getLine(ln), cut = line.length - origTarget[0].length;
                        if (fold(line.slice(cut)) != target[0]) return;
                        return {from: Pos(ln, cut), to: to};
                      } else {
                        if (pos.line + (target.length - 1) > doc.lastLine()) return;
                        var line = doc.getLine(pos.line), cut = line.length - origTarget[0].length;
                        if (fold(line.slice(cut)) != target[0]) return;
                        var from = Pos(pos.line, cut);
                        for (var ln = pos.line + 1, i = 1; i < last; ++i, ++ln)
                          if (target[i] != fold(doc.getLine(ln))) return;
                        if (fold(doc.getLine(ln).slice(0, origTarget[last].length)) != target[last]) return;
                        return {from: from, to: Pos(ln, origTarget[last].length)};
                      }
                    };
                  }
                }
              }
            
              SearchCursor.prototype = {
                findNext: function() {return this.find(false);},
                findPrevious: function() {return this.find(true);},
            
                find: function(reverse) {
                  var self = this, pos = this.doc.clipPos(reverse ? this.pos.from : this.pos.to);
                  function savePosAndFail(line) {
                    var pos = Pos(line, 0);
                    self.pos = {from: pos, to: pos};
                    self.atOccurrence = false;
                    return false;
                  }
            
                  for (;;) {
                    if (this.pos = this.matches(reverse, pos)) {
                      this.atOccurrence = true;
                      return this.pos.match || true;
                    }
                    if (reverse) {
                      if (!pos.line) return savePosAndFail(0);
                      pos = Pos(pos.line-1, this.doc.getLine(pos.line-1).length);
                    }
                    else {
                      var maxLine = this.doc.lineCount();
                      if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
                      pos = Pos(pos.line + 1, 0);
                    }
                  }
                },
            
                from: function() {if (this.atOccurrence) return this.pos.from;},
                to: function() {if (this.atOccurrence) return this.pos.to;},
            
                replace: function(newText, origin) {
                  if (!this.atOccurrence) return;
                  var lines = CodeMirror.splitLines(newText);
                  this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin);
                  this.pos.to = Pos(this.pos.from.line + lines.length - 1,
                                    lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
                }
              };
            
              // Maps a position in a case-folded line back to a position in the original line
              // (compensating for codepoints increasing in number during folding)
              function adjustPos(orig, folded, pos) {
                if (orig.length == folded.length) return pos;
                for (var pos1 = Math.min(pos, orig.length);;) {
                  var len1 = orig.slice(0, pos1).toLowerCase().length;
                  if (len1 < pos) ++pos1;
                  else if (len1 > pos) --pos1;
                  else return pos1;
                }
              }
            
              CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
                return new SearchCursor(this.doc, query, pos, caseFold);
              });
              CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
                return new SearchCursor(this, query, pos, caseFold);
              });
            
              CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
                var ranges = [];
                var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold);
                while (cur.findNext()) {
                  if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break;
                  ranges.push({anchor: cur.from(), head: cur.to()});
                }
                if (ranges.length)
                  this.setSelections(ranges, 0);
              });
            });
            
        • selection
          • active-line.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Because sometimes you need to style the cursor's line.
            //
            // Adds an option 'styleActiveLine' which, when enabled, gives the
            // active line's wrapping <div> the CSS class "CodeMirror-activeline",
            // and gives its background <div> the class "CodeMirror-activeline-background".
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              var WRAP_CLASS = "CodeMirror-activeline";
              var BACK_CLASS = "CodeMirror-activeline-background";
            
              CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
                var prev = old && old != CodeMirror.Init;
                if (val && !prev) {
                  cm.state.activeLines = [];
                  updateActiveLines(cm, cm.listSelections());
                  cm.on("beforeSelectionChange", selectionChange);
                } else if (!val && prev) {
                  cm.off("beforeSelectionChange", selectionChange);
                  clearActiveLines(cm);
                  delete cm.state.activeLines;
                }
              });
            
              function clearActiveLines(cm) {
                for (var i = 0; i < cm.state.activeLines.length; i++) {
                  cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);
                  cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);
                }
              }
            
              function sameArray(a, b) {
                if (a.length != b.length) return false;
                for (var i = 0; i < a.length; i++)
                  if (a[i] != b[i]) return false;
                return true;
              }
            
              function updateActiveLines(cm, ranges) {
                var active = [];
                for (var i = 0; i < ranges.length; i++) {
                  var range = ranges[i];
                  if (!range.empty()) continue;
                  var line = cm.getLineHandleVisualStart(range.head.line);
                  if (active[active.length - 1] != line) active.push(line);
                }
                if (sameArray(cm.state.activeLines, active)) return;
                cm.operation(function() {
                  clearActiveLines(cm);
                  for (var i = 0; i < active.length; i++) {
                    cm.addLineClass(active[i], "wrap", WRAP_CLASS);
                    cm.addLineClass(active[i], "background", BACK_CLASS);
                  }
                  cm.state.activeLines = active;
                });
              }
            
              function selectionChange(cm, sel) {
                updateActiveLines(cm, sel.ranges);
              }
            });
            
          • mark-selection.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Because sometimes you need to mark the selected *text*.
            //
            // Adds an option 'styleSelectedText' which, when enabled, gives
            // selected text the CSS class given as option value, or
            // "CodeMirror-selectedtext" when the value is not a string.
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) {
                var prev = old && old != CodeMirror.Init;
                if (val && !prev) {
                  cm.state.markedSelection = [];
                  cm.state.markedSelectionStyle = typeof val == "string" ? val : "CodeMirror-selectedtext";
                  reset(cm);
                  cm.on("cursorActivity", onCursorActivity);
                  cm.on("change", onChange);
                } else if (!val && prev) {
                  cm.off("cursorActivity", onCursorActivity);
                  cm.off("change", onChange);
                  clear(cm);
                  cm.state.markedSelection = cm.state.markedSelectionStyle = null;
                }
              });
            
              function onCursorActivity(cm) {
                cm.operation(function() { update(cm); });
              }
            
              function onChange(cm) {
                if (cm.state.markedSelection.length)
                  cm.operation(function() { clear(cm); });
              }
            
              var CHUNK_SIZE = 8;
              var Pos = CodeMirror.Pos;
              var cmp = CodeMirror.cmpPos;
            
              function coverRange(cm, from, to, addAt) {
                if (cmp(from, to) == 0) return;
                var array = cm.state.markedSelection;
                var cls = cm.state.markedSelectionStyle;
                for (var line = from.line;;) {
                  var start = line == from.line ? from : Pos(line, 0);
                  var endLine = line + CHUNK_SIZE, atEnd = endLine >= to.line;
                  var end = atEnd ? to : Pos(endLine, 0);
                  var mark = cm.markText(start, end, {className: cls});
                  if (addAt == null) array.push(mark);
                  else array.splice(addAt++, 0, mark);
                  if (atEnd) break;
                  line = endLine;
                }
              }
            
              function clear(cm) {
                var array = cm.state.markedSelection;
                for (var i = 0; i < array.length; ++i) array[i].clear();
                array.length = 0;
              }
            
              function reset(cm) {
                clear(cm);
                var ranges = cm.listSelections();
                for (var i = 0; i < ranges.length; i++)
                  coverRange(cm, ranges[i].from(), ranges[i].to());
              }
            
              function update(cm) {
                if (!cm.somethingSelected()) return clear(cm);
                if (cm.listSelections().length > 1) return reset(cm);
            
                var from = cm.getCursor("start"), to = cm.getCursor("end");
            
                var array = cm.state.markedSelection;
                if (!array.length) return coverRange(cm, from, to);
            
                var coverStart = array[0].find(), coverEnd = array[array.length - 1].find();
                if (!coverStart || !coverEnd || to.line - from.line < CHUNK_SIZE ||
                    cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0)
                  return reset(cm);
            
                while (cmp(from, coverStart.from) > 0) {
                  array.shift().clear();
                  coverStart = array[0].find();
                }
                if (cmp(from, coverStart.from) < 0) {
                  if (coverStart.to.line - from.line < CHUNK_SIZE) {
                    array.shift().clear();
                    coverRange(cm, from, coverStart.to, 0);
                  } else {
                    coverRange(cm, from, coverStart.from, 0);
                  }
                }
            
                while (cmp(to, coverEnd.to) < 0) {
                  array.pop().clear();
                  coverEnd = array[array.length - 1].find();
                }
                if (cmp(to, coverEnd.to) > 0) {
                  if (to.line - coverEnd.from.line < CHUNK_SIZE) {
                    array.pop().clear();
                    coverRange(cm, coverEnd.from, to);
                  } else {
                    coverRange(cm, coverEnd.to, to);
                  }
                }
              }
            });
            
          • selection-pointer.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineOption("selectionPointer", false, function(cm, val) {
                var data = cm.state.selectionPointer;
                if (data) {
                  CodeMirror.off(cm.getWrapperElement(), "mousemove", data.mousemove);
                  CodeMirror.off(cm.getWrapperElement(), "mouseout", data.mouseout);
                  CodeMirror.off(window, "scroll", data.windowScroll);
                  cm.off("cursorActivity", reset);
                  cm.off("scroll", reset);
                  cm.state.selectionPointer = null;
                  cm.display.lineDiv.style.cursor = "";
                }
                if (val) {
                  data = cm.state.selectionPointer = {
                    value: typeof val == "string" ? val : "default",
                    mousemove: function(event) { mousemove(cm, event); },
                    mouseout: function(event) { mouseout(cm, event); },
                    windowScroll: function() { reset(cm); },
                    rects: null,
                    mouseX: null, mouseY: null,
                    willUpdate: false
                  };
                  CodeMirror.on(cm.getWrapperElement(), "mousemove", data.mousemove);
                  CodeMirror.on(cm.getWrapperElement(), "mouseout", data.mouseout);
                  CodeMirror.on(window, "scroll", data.windowScroll);
                  cm.on("cursorActivity", reset);
                  cm.on("scroll", reset);
                }
              });
            
              function mousemove(cm, event) {
                var data = cm.state.selectionPointer;
                if (event.buttons == null ? event.which : event.buttons) {
                  data.mouseX = data.mouseY = null;
                } else {
                  data.mouseX = event.clientX;
                  data.mouseY = event.clientY;
                }
                scheduleUpdate(cm);
              }
            
              function mouseout(cm, event) {
                if (!cm.getWrapperElement().contains(event.relatedTarget)) {
                  var data = cm.state.selectionPointer;
                  data.mouseX = data.mouseY = null;
                  scheduleUpdate(cm);
                }
              }
            
              function reset(cm) {
                cm.state.selectionPointer.rects = null;
                scheduleUpdate(cm);
              }
            
              function scheduleUpdate(cm) {
                if (!cm.state.selectionPointer.willUpdate) {
                  cm.state.selectionPointer.willUpdate = true;
                  setTimeout(function() {
                    update(cm);
                    cm.state.selectionPointer.willUpdate = false;
                  }, 50);
                }
              }
            
              function update(cm) {
                var data = cm.state.selectionPointer;
                if (!data) return;
                if (data.rects == null && data.mouseX != null) {
                  data.rects = [];
                  if (cm.somethingSelected()) {
                    for (var sel = cm.display.selectionDiv.firstChild; sel; sel = sel.nextSibling)
                      data.rects.push(sel.getBoundingClientRect());
                  }
                }
                var inside = false;
                if (data.mouseX != null) for (var i = 0; i < data.rects.length; i++) {
                  var rect = data.rects[i];
                  if (rect.left <= data.mouseX && rect.right >= data.mouseX &&
                      rect.top <= data.mouseY && rect.bottom >= data.mouseY)
                    inside = true;
                }
                var cursor = inside ? data.value : "";
                if (cm.display.lineDiv.style.cursor != cursor)
                  cm.display.lineDiv.style.cursor = cursor;
              }
            });
            
        • tern
          • tern.css
            .CodeMirror-Tern-completion {
              padding-left: 22px;
              position: relative;
            }
            .CodeMirror-Tern-completion:before {
              position: absolute;
              left: 2px;
              bottom: 2px;
              border-radius: 50%;
              font-size: 12px;
              font-weight: bold;
              height: 15px;
              width: 15px;
              line-height: 16px;
              text-align: center;
              color: white;
              -moz-box-sizing: border-box;
              box-sizing: border-box;
            }
            .CodeMirror-Tern-completion-unknown:before {
              content: "?";
              background: #4bb;
            }
            .CodeMirror-Tern-completion-object:before {
              content: "O";
              background: #77c;
            }
            .CodeMirror-Tern-completion-fn:before {
              content: "F";
              background: #7c7;
            }
            .CodeMirror-Tern-completion-array:before {
              content: "A";
              background: #c66;
            }
            .CodeMirror-Tern-completion-number:before {
              content: "1";
              background: #999;
            }
            .CodeMirror-Tern-completion-string:before {
              content: "S";
              background: #999;
            }
            .CodeMirror-Tern-completion-bool:before {
              content: "B";
              background: #999;
            }
            
            .CodeMirror-Tern-completion-guess {
              color: #999;
            }
            
            .CodeMirror-Tern-tooltip {
              border: 1px solid silver;
              border-radius: 3px;
              color: #444;
              padding: 2px 5px;
              font-size: 90%;
              font-family: monospace;
              background-color: white;
              white-space: pre-wrap;
            
              max-width: 40em;
              position: absolute;
              z-index: 10;
              -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
              -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
              box-shadow: 2px 3px 5px rgba(0,0,0,.2);
            
              transition: opacity 1s;
              -moz-transition: opacity 1s;
              -webkit-transition: opacity 1s;
              -o-transition: opacity 1s;
              -ms-transition: opacity 1s;
            }
            
            .CodeMirror-Tern-hint-doc {
              max-width: 25em;
              margin-top: -3px;
            }
            
            .CodeMirror-Tern-fname { color: black; }
            .CodeMirror-Tern-farg { color: #70a; }
            .CodeMirror-Tern-farg-current { text-decoration: underline; }
            .CodeMirror-Tern-type { color: #07c; }
            .CodeMirror-Tern-fhint-guess { opacity: .7; }
            
          • tern.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Glue code between CodeMirror and Tern.
            //
            // Create a CodeMirror.TernServer to wrap an actual Tern server,
            // register open documents (CodeMirror.Doc instances) with it, and
            // call its methods to activate the assisting functions that Tern
            // provides.
            //
            // Options supported (all optional):
            // * defs: An array of JSON definition data structures.
            // * plugins: An object mapping plugin names to configuration
            //   options.
            // * getFile: A function(name, c) that can be used to access files in
            //   the project that haven't been loaded yet. Simply do c(null) to
            //   indicate that a file is not available.
            // * fileFilter: A function(value, docName, doc) that will be applied
            //   to documents before passing them on to Tern.
            // * switchToDoc: A function(name, doc) that should, when providing a
            //   multi-file view, switch the view or focus to the named file.
            // * showError: A function(editor, message) that can be used to
            //   override the way errors are displayed.
            // * completionTip: Customize the content in tooltips for completions.
            //   Is passed a single argument—the completion's data as returned by
            //   Tern—and may return a string, DOM node, or null to indicate that
            //   no tip should be shown. By default the docstring is shown.
            // * typeTip: Like completionTip, but for the tooltips shown for type
            //   queries.
            // * responseFilter: A function(doc, query, request, error, data) that
            //   will be applied to the Tern responses before treating them
            //
            //
            // It is possible to run the Tern server in a web worker by specifying
            // these additional options:
            // * useWorker: Set to true to enable web worker mode. You'll probably
            //   want to feature detect the actual value you use here, for example
            //   !!window.Worker.
            // * workerScript: The main script of the worker. Point this to
            //   wherever you are hosting worker.js from this directory.
            // * workerDeps: An array of paths pointing (relative to workerScript)
            //   to the Acorn and Tern libraries and any Tern plugins you want to
            //   load. Or, if you minified those into a single script and included
            //   them in the workerScript, simply leave this undefined.
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              // declare global: tern
            
              CodeMirror.TernServer = function(options) {
                var self = this;
                this.options = options || {};
                var plugins = this.options.plugins || (this.options.plugins = {});
                if (!plugins.doc_comment) plugins.doc_comment = true;
                if (this.options.useWorker) {
                  this.server = new WorkerServer(this);
                } else {
                  this.server = new tern.Server({
                    getFile: function(name, c) { return getFile(self, name, c); },
                    async: true,
                    defs: this.options.defs || [],
                    plugins: plugins
                  });
                }
                this.docs = Object.create(null);
                this.trackChange = function(doc, change) { trackChange(self, doc, change); };
            
                this.cachedArgHints = null;
                this.activeArgHints = null;
                this.jumpStack = [];
            
                this.getHint = function(cm, c) { return hint(self, cm, c); };
                this.getHint.async = true;
              };
            
              CodeMirror.TernServer.prototype = {
                addDoc: function(name, doc) {
                  var data = {doc: doc, name: name, changed: null};
                  this.server.addFile(name, docValue(this, data));
                  CodeMirror.on(doc, "change", this.trackChange);
                  return this.docs[name] = data;
                },
            
                delDoc: function(id) {
                  var found = resolveDoc(this, id);
                  if (!found) return;
                  CodeMirror.off(found.doc, "change", this.trackChange);
                  delete this.docs[found.name];
                  this.server.delFile(found.name);
                },
            
                hideDoc: function(id) {
                  closeArgHints(this);
                  var found = resolveDoc(this, id);
                  if (found && found.changed) sendDoc(this, found);
                },
            
                complete: function(cm) {
                  cm.showHint({hint: this.getHint});
                },
            
                showType: function(cm, pos, c) { showContextInfo(this, cm, pos, "type", c); },
            
                showDocs: function(cm, pos, c) { showContextInfo(this, cm, pos, "documentation", c); },
            
                updateArgHints: function(cm) { updateArgHints(this, cm); },
            
                jumpToDef: function(cm) { jumpToDef(this, cm); },
            
                jumpBack: function(cm) { jumpBack(this, cm); },
            
                rename: function(cm) { rename(this, cm); },
            
                selectName: function(cm) { selectName(this, cm); },
            
                request: function (cm, query, c, pos) {
                  var self = this;
                  var doc = findDoc(this, cm.getDoc());
                  var request = buildRequest(this, doc, query, pos);
            
                  this.server.request(request, function (error, data) {
                    if (!error && self.options.responseFilter)
                      data = self.options.responseFilter(doc, query, request, error, data);
                    c(error, data);
                  });
                },
            
                destroy: function () {
                  if (this.worker) {
                    this.worker.terminate();
                    this.worker = null;
                  }
                }
              };
            
              var Pos = CodeMirror.Pos;
              var cls = "CodeMirror-Tern-";
              var bigDoc = 250;
            
              function getFile(ts, name, c) {
                var buf = ts.docs[name];
                if (buf)
                  c(docValue(ts, buf));
                else if (ts.options.getFile)
                  ts.options.getFile(name, c);
                else
                  c(null);
              }
            
              function findDoc(ts, doc, name) {
                for (var n in ts.docs) {
                  var cur = ts.docs[n];
                  if (cur.doc == doc) return cur;
                }
                if (!name) for (var i = 0;; ++i) {
                  n = "[doc" + (i || "") + "]";
                  if (!ts.docs[n]) { name = n; break; }
                }
                return ts.addDoc(name, doc);
              }
            
              function resolveDoc(ts, id) {
                if (typeof id == "string") return ts.docs[id];
                if (id instanceof CodeMirror) id = id.getDoc();
                if (id instanceof CodeMirror.Doc) return findDoc(ts, id);
              }
            
              function trackChange(ts, doc, change) {
                var data = findDoc(ts, doc);
            
                var argHints = ts.cachedArgHints;
                if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) <= 0)
                  ts.cachedArgHints = null;
            
                var changed = data.changed;
                if (changed == null)
                  data.changed = changed = {from: change.from.line, to: change.from.line};
                var end = change.from.line + (change.text.length - 1);
                if (change.from.line < changed.to) changed.to = changed.to - (change.to.line - end);
                if (end >= changed.to) changed.to = end + 1;
                if (changed.from > change.from.line) changed.from = change.from.line;
            
                if (doc.lineCount() > bigDoc && change.to - changed.from > 100) setTimeout(function() {
                  if (data.changed && data.changed.to - data.changed.from > 100) sendDoc(ts, data);
                }, 200);
              }
            
              function sendDoc(ts, doc) {
                ts.server.request({files: [{type: "full", name: doc.name, text: docValue(ts, doc)}]}, function(error) {
                  if (error) window.console.error(error);
                  else doc.changed = null;
                });
              }
            
              // Completion
            
              function hint(ts, cm, c) {
                ts.request(cm, {type: "completions", types: true, docs: true, urls: true}, function(error, data) {
                  if (error) return showError(ts, cm, error);
                  var completions = [], after = "";
                  var from = data.start, to = data.end;
                  if (cm.getRange(Pos(from.line, from.ch - 2), from) == "[\"" &&
                      cm.getRange(to, Pos(to.line, to.ch + 2)) != "\"]")
                    after = "\"]";
            
                  for (var i = 0; i < data.completions.length; ++i) {
                    var completion = data.completions[i], className = typeToIcon(completion.type);
                    if (data.guess) className += " " + cls + "guess";
                    completions.push({text: completion.name + after,
                                      displayText: completion.name,
                                      className: className,
                                      data: completion});
                  }
            
                  var obj = {from: from, to: to, list: completions};
                  var tooltip = null;
                  CodeMirror.on(obj, "close", function() { remove(tooltip); });
                  CodeMirror.on(obj, "update", function() { remove(tooltip); });
                  CodeMirror.on(obj, "select", function(cur, node) {
                    remove(tooltip);
                    var content = ts.options.completionTip ? ts.options.completionTip(cur.data) : cur.data.doc;
                    if (content) {
                      tooltip = makeTooltip(node.parentNode.getBoundingClientRect().right + window.pageXOffset,
                                            node.getBoundingClientRect().top + window.pageYOffset, content);
                      tooltip.className += " " + cls + "hint-doc";
                    }
                  });
                  c(obj);
                });
              }
            
              function typeToIcon(type) {
                var suffix;
                if (type == "?") suffix = "unknown";
                else if (type == "number" || type == "string" || type == "bool") suffix = type;
                else if (/^fn\(/.test(type)) suffix = "fn";
                else if (/^\[/.test(type)) suffix = "array";
                else suffix = "object";
                return cls + "completion " + cls + "completion-" + suffix;
              }
            
              // Type queries
            
              function showContextInfo(ts, cm, pos, queryName, c) {
                ts.request(cm, queryName, function(error, data) {
                  if (error) return showError(ts, cm, error);
                  if (ts.options.typeTip) {
                    var tip = ts.options.typeTip(data);
                  } else {
                    var tip = elt("span", null, elt("strong", null, data.type || "not found"));
                    if (data.doc)
                      tip.appendChild(document.createTextNode(" — " + data.doc));
                    if (data.url) {
                      tip.appendChild(document.createTextNode(" "));
                      var child = tip.appendChild(elt("a", null, "[docs]"));
                      child.href = data.url;
                      child.target = "_blank";
                    }
                  }
                  tempTooltip(cm, tip);
                  if (c) c();
                }, pos);
              }
            
              // Maintaining argument hints
            
              function updateArgHints(ts, cm) {
                closeArgHints(ts);
            
                if (cm.somethingSelected()) return;
                var state = cm.getTokenAt(cm.getCursor()).state;
                var inner = CodeMirror.innerMode(cm.getMode(), state);
                if (inner.mode.name != "javascript") return;
                var lex = inner.state.lexical;
                if (lex.info != "call") return;
            
                var ch, argPos = lex.pos || 0, tabSize = cm.getOption("tabSize");
                for (var line = cm.getCursor().line, e = Math.max(0, line - 9), found = false; line >= e; --line) {
                  var str = cm.getLine(line), extra = 0;
                  for (var pos = 0;;) {
                    var tab = str.indexOf("\t", pos);
                    if (tab == -1) break;
                    extra += tabSize - (tab + extra) % tabSize - 1;
                    pos = tab + 1;
                  }
                  ch = lex.column - extra;
                  if (str.charAt(ch) == "(") {found = true; break;}
                }
                if (!found) return;
            
                var start = Pos(line, ch);
                var cache = ts.cachedArgHints;
                if (cache && cache.doc == cm.getDoc() && cmpPos(start, cache.start) == 0)
                  return showArgHints(ts, cm, argPos);
            
                ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) {
                  if (error || !data.type || !(/^fn\(/).test(data.type)) return;
                  ts.cachedArgHints = {
                    start: pos,
                    type: parseFnType(data.type),
                    name: data.exprName || data.name || "fn",
                    guess: data.guess,
                    doc: cm.getDoc()
                  };
                  showArgHints(ts, cm, argPos);
                });
              }
            
              function showArgHints(ts, cm, pos) {
                closeArgHints(ts);
            
                var cache = ts.cachedArgHints, tp = cache.type;
                var tip = elt("span", cache.guess ? cls + "fhint-guess" : null,
                              elt("span", cls + "fname", cache.name), "(");
                for (var i = 0; i < tp.args.length; ++i) {
                  if (i) tip.appendChild(document.createTextNode(", "));
                  var arg = tp.args[i];
                  tip.appendChild(elt("span", cls + "farg" + (i == pos ? " " + cls + "farg-current" : ""), arg.name || "?"));
                  if (arg.type != "?") {
                    tip.appendChild(document.createTextNode(":\u00a0"));
                    tip.appendChild(elt("span", cls + "type", arg.type));
                  }
                }
                tip.appendChild(document.createTextNode(tp.rettype ? ") ->\u00a0" : ")"));
                if (tp.rettype) tip.appendChild(elt("span", cls + "type", tp.rettype));
                var place = cm.cursorCoords(null, "page");
                ts.activeArgHints = makeTooltip(place.right + 1, place.bottom, tip);
              }
            
              function parseFnType(text) {
                var args = [], pos = 3;
            
                function skipMatching(upto) {
                  var depth = 0, start = pos;
                  for (;;) {
                    var next = text.charAt(pos);
                    if (upto.test(next) && !depth) return text.slice(start, pos);
                    if (/[{\[\(]/.test(next)) ++depth;
                    else if (/[}\]\)]/.test(next)) --depth;
                    ++pos;
                  }
                }
            
                // Parse arguments
                if (text.charAt(pos) != ")") for (;;) {
                  var name = text.slice(pos).match(/^([^, \(\[\{]+): /);
                  if (name) {
                    pos += name[0].length;
                    name = name[1];
                  }
                  args.push({name: name, type: skipMatching(/[\),]/)});
                  if (text.charAt(pos) == ")") break;
                  pos += 2;
                }
            
                var rettype = text.slice(pos).match(/^\) -> (.*)$/);
            
                return {args: args, rettype: rettype && rettype[1]};
              }
            
              // Moving to the definition of something
            
              function jumpToDef(ts, cm) {
                function inner(varName) {
                  var req = {type: "definition", variable: varName || null};
                  var doc = findDoc(ts, cm.getDoc());
                  ts.server.request(buildRequest(ts, doc, req), function(error, data) {
                    if (error) return showError(ts, cm, error);
                    if (!data.file && data.url) { window.open(data.url); return; }
            
                    if (data.file) {
                      var localDoc = ts.docs[data.file], found;
                      if (localDoc && (found = findContext(localDoc.doc, data))) {
                        ts.jumpStack.push({file: doc.name,
                                           start: cm.getCursor("from"),
                                           end: cm.getCursor("to")});
                        moveTo(ts, doc, localDoc, found.start, found.end);
                        return;
                      }
                    }
                    showError(ts, cm, "Could not find a definition.");
                  });
                }
            
                if (!atInterestingExpression(cm))
                  dialog(cm, "Jump to variable", function(name) { if (name) inner(name); });
                else
                  inner();
              }
            
              function jumpBack(ts, cm) {
                var pos = ts.jumpStack.pop(), doc = pos && ts.docs[pos.file];
                if (!doc) return;
                moveTo(ts, findDoc(ts, cm.getDoc()), doc, pos.start, pos.end);
              }
            
              function moveTo(ts, curDoc, doc, start, end) {
                doc.doc.setSelection(start, end);
                if (curDoc != doc && ts.options.switchToDoc) {
                  closeArgHints(ts);
                  ts.options.switchToDoc(doc.name, doc.doc);
                }
              }
            
              // The {line,ch} representation of positions makes this rather awkward.
              function findContext(doc, data) {
                var before = data.context.slice(0, data.contextOffset).split("\n");
                var startLine = data.start.line - (before.length - 1);
                var start = Pos(startLine, (before.length == 1 ? data.start.ch : doc.getLine(startLine).length) - before[0].length);
            
                var text = doc.getLine(startLine).slice(start.ch);
                for (var cur = startLine + 1; cur < doc.lineCount() && text.length < data.context.length; ++cur)
                  text += "\n" + doc.getLine(cur);
                if (text.slice(0, data.context.length) == data.context) return data;
            
                var cursor = doc.getSearchCursor(data.context, 0, false);
                var nearest, nearestDist = Infinity;
                while (cursor.findNext()) {
                  var from = cursor.from(), dist = Math.abs(from.line - start.line) * 10000;
                  if (!dist) dist = Math.abs(from.ch - start.ch);
                  if (dist < nearestDist) { nearest = from; nearestDist = dist; }
                }
                if (!nearest) return null;
            
                if (before.length == 1)
                  nearest.ch += before[0].length;
                else
                  nearest = Pos(nearest.line + (before.length - 1), before[before.length - 1].length);
                if (data.start.line == data.end.line)
                  var end = Pos(nearest.line, nearest.ch + (data.end.ch - data.start.ch));
                else
                  var end = Pos(nearest.line + (data.end.line - data.start.line), data.end.ch);
                return {start: nearest, end: end};
              }
            
              function atInterestingExpression(cm) {
                var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos);
                if (tok.start < pos.ch && (tok.type == "comment" || tok.type == "string")) return false;
                return /[\w)\]]/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
              }
            
              // Variable renaming
            
              function rename(ts, cm) {
                var token = cm.getTokenAt(cm.getCursor());
                if (!/\w/.test(token.string)) return showError(ts, cm, "Not at a variable");
                dialog(cm, "New name for " + token.string, function(newName) {
                  ts.request(cm, {type: "rename", newName: newName, fullDocs: true}, function(error, data) {
                    if (error) return showError(ts, cm, error);
                    applyChanges(ts, data.changes);
                  });
                });
              }
            
              function selectName(ts, cm) {
                var name = findDoc(ts, cm.doc).name;
                ts.request(cm, {type: "refs"}, function(error, data) {
                  if (error) return showError(ts, cm, error);
                  var ranges = [], cur = 0;
                  for (var i = 0; i < data.refs.length; i++) {
                    var ref = data.refs[i];
                    if (ref.file == name) {
                      ranges.push({anchor: ref.start, head: ref.end});
                      if (cmpPos(cur, ref.start) >= 0 && cmpPos(cur, ref.end) <= 0)
                        cur = ranges.length - 1;
                    }
                  }
                  cm.setSelections(ranges, cur);
                });
              }
            
              var nextChangeOrig = 0;
              function applyChanges(ts, changes) {
                var perFile = Object.create(null);
                for (var i = 0; i < changes.length; ++i) {
                  var ch = changes[i];
                  (perFile[ch.file] || (perFile[ch.file] = [])).push(ch);
                }
                for (var file in perFile) {
                  var known = ts.docs[file], chs = perFile[file];;
                  if (!known) continue;
                  chs.sort(function(a, b) { return cmpPos(b.start, a.start); });
                  var origin = "*rename" + (++nextChangeOrig);
                  for (var i = 0; i < chs.length; ++i) {
                    var ch = chs[i];
                    known.doc.replaceRange(ch.text, ch.start, ch.end, origin);
                  }
                }
              }
            
              // Generic request-building helper
            
              function buildRequest(ts, doc, query, pos) {
                var files = [], offsetLines = 0, allowFragments = !query.fullDocs;
                if (!allowFragments) delete query.fullDocs;
                if (typeof query == "string") query = {type: query};
                query.lineCharPositions = true;
                if (query.end == null) {
                  query.end = pos || doc.doc.getCursor("end");
                  if (doc.doc.somethingSelected())
                    query.start = doc.doc.getCursor("start");
                }
                var startPos = query.start || query.end;
            
                if (doc.changed) {
                  if (doc.doc.lineCount() > bigDoc && allowFragments !== false &&
                      doc.changed.to - doc.changed.from < 100 &&
                      doc.changed.from <= startPos.line && doc.changed.to > query.end.line) {
                    files.push(getFragmentAround(doc, startPos, query.end));
                    query.file = "#0";
                    var offsetLines = files[0].offsetLines;
                    if (query.start != null) query.start = Pos(query.start.line - -offsetLines, query.start.ch);
                    query.end = Pos(query.end.line - offsetLines, query.end.ch);
                  } else {
                    files.push({type: "full",
                                name: doc.name,
                                text: docValue(ts, doc)});
                    query.file = doc.name;
                    doc.changed = null;
                  }
                } else {
                  query.file = doc.name;
                }
                for (var name in ts.docs) {
                  var cur = ts.docs[name];
                  if (cur.changed && cur != doc) {
                    files.push({type: "full", name: cur.name, text: docValue(ts, cur)});
                    cur.changed = null;
                  }
                }
            
                return {query: query, files: files};
              }
            
              function getFragmentAround(data, start, end) {
                var doc = data.doc;
                var minIndent = null, minLine = null, endLine, tabSize = 4;
                for (var p = start.line - 1, min = Math.max(0, p - 50); p >= min; --p) {
                  var line = doc.getLine(p), fn = line.search(/\bfunction\b/);
                  if (fn < 0) continue;
                  var indent = CodeMirror.countColumn(line, null, tabSize);
                  if (minIndent != null && minIndent <= indent) continue;
                  minIndent = indent;
                  minLine = p;
                }
                if (minLine == null) minLine = min;
                var max = Math.min(doc.lastLine(), end.line + 20);
                if (minIndent == null || minIndent == CodeMirror.countColumn(doc.getLine(start.line), null, tabSize))
                  endLine = max;
                else for (endLine = end.line + 1; endLine < max; ++endLine) {
                  var indent = CodeMirror.countColumn(doc.getLine(endLine), null, tabSize);
                  if (indent <= minIndent) break;
                }
                var from = Pos(minLine, 0);
            
                return {type: "part",
                        name: data.name,
                        offsetLines: from.line,
                        text: doc.getRange(from, Pos(endLine, 0))};
              }
            
              // Generic utilities
            
              var cmpPos = CodeMirror.cmpPos;
            
              function elt(tagname, cls /*, ... elts*/) {
                var e = document.createElement(tagname);
                if (cls) e.className = cls;
                for (var i = 2; i < arguments.length; ++i) {
                  var elt = arguments[i];
                  if (typeof elt == "string") elt = document.createTextNode(elt);
                  e.appendChild(elt);
                }
                return e;
              }
            
              function dialog(cm, text, f) {
                if (cm.openDialog)
                  cm.openDialog(text + ": <input type=text>", f);
                else
                  f(prompt(text, ""));
              }
            
              // Tooltips
            
              function tempTooltip(cm, content) {
                if (cm.state.ternTooltip) remove(cm.state.ternTooltip);
                var where = cm.cursorCoords();
                var tip = cm.state.ternTooltip = makeTooltip(where.right + 1, where.bottom, content);
                function maybeClear() {
                  old = true;
                  if (!mouseOnTip) clear();
                }
                function clear() {
                  cm.state.ternTooltip = null;
                  if (!tip.parentNode) return;
                  cm.off("cursorActivity", clear);
                  cm.off('blur', clear);
                  cm.off('scroll', clear);
                  fadeOut(tip);
                }
                var mouseOnTip = false, old = false;
                CodeMirror.on(tip, "mousemove", function() { mouseOnTip = true; });
                CodeMirror.on(tip, "mouseout", function(e) {
                  if (!CodeMirror.contains(tip, e.relatedTarget || e.toElement)) {
                    if (old) clear();
                    else mouseOnTip = false;
                  }
                });
                setTimeout(maybeClear, 1700);
                cm.on("cursorActivity", clear);
                cm.on('blur', clear);
                cm.on('scroll', clear);
              }
            
              function makeTooltip(x, y, content) {
                var node = elt("div", cls + "tooltip", content);
                node.style.left = x + "px";
                node.style.top = y + "px";
                document.body.appendChild(node);
                return node;
              }
            
              function remove(node) {
                var p = node && node.parentNode;
                if (p) p.removeChild(node);
              }
            
              function fadeOut(tooltip) {
                tooltip.style.opacity = "0";
                setTimeout(function() { remove(tooltip); }, 1100);
              }
            
              function showError(ts, cm, msg) {
                if (ts.options.showError)
                  ts.options.showError(cm, msg);
                else
                  tempTooltip(cm, String(msg));
              }
            
              function closeArgHints(ts) {
                if (ts.activeArgHints) { remove(ts.activeArgHints); ts.activeArgHints = null; }
              }
            
              function docValue(ts, doc) {
                var val = doc.doc.getValue();
                if (ts.options.fileFilter) val = ts.options.fileFilter(val, doc.name, doc.doc);
                return val;
              }
            
              // Worker wrapper
            
              function WorkerServer(ts) {
                var worker = ts.worker = new Worker(ts.options.workerScript);
                worker.postMessage({type: "init",
                                    defs: ts.options.defs,
                                    plugins: ts.options.plugins,
                                    scripts: ts.options.workerDeps});
                var msgId = 0, pending = {};
            
                function send(data, c) {
                  if (c) {
                    data.id = ++msgId;
                    pending[msgId] = c;
                  }
                  worker.postMessage(data);
                }
                worker.onmessage = function(e) {
                  var data = e.data;
                  if (data.type == "getFile") {
                    getFile(ts, data.name, function(err, text) {
                      send({type: "getFile", err: String(err), text: text, id: data.id});
                    });
                  } else if (data.type == "debug") {
                    window.console.log(data.message);
                  } else if (data.id && pending[data.id]) {
                    pending[data.id](data.err, data.body);
                    delete pending[data.id];
                  }
                };
                worker.onerror = function(e) {
                  for (var id in pending) pending[id](e);
                  pending = {};
                };
            
                this.addFile = function(name, text) { send({type: "add", name: name, text: text}); };
                this.delFile = function(name) { send({type: "del", name: name}); };
                this.request = function(body, c) { send({type: "req", body: body}, c); };
              }
            });
            
          • worker.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // declare global: tern, server
            
            var server;
            
            this.onmessage = function(e) {
              var data = e.data;
              switch (data.type) {
              case "init": return startServer(data.defs, data.plugins, data.scripts);
              case "add": return server.addFile(data.name, data.text);
              case "del": return server.delFile(data.name);
              case "req": return server.request(data.body, function(err, reqData) {
                postMessage({id: data.id, body: reqData, err: err && String(err)});
              });
              case "getFile":
                var c = pending[data.id];
                delete pending[data.id];
                return c(data.err, data.text);
              default: throw new Error("Unknown message type: " + data.type);
              }
            };
            
            var nextId = 0, pending = {};
            function getFile(file, c) {
              postMessage({type: "getFile", name: file, id: ++nextId});
              pending[nextId] = c;
            }
            
            function startServer(defs, plugins, scripts) {
              if (scripts) importScripts.apply(null, scripts);
            
              server = new tern.Server({
                getFile: getFile,
                async: true,
                defs: defs,
                plugins: plugins
              });
            }
            
            this.console = {
              log: function(v) { postMessage({type: "debug", message: v}); }
            };
            
        • wrap
          • hardwrap.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var Pos = CodeMirror.Pos;
            
              function findParagraph(cm, pos, options) {
                var startRE = options.paragraphStart || cm.getHelper(pos, "paragraphStart");
                for (var start = pos.line, first = cm.firstLine(); start > first; --start) {
                  var line = cm.getLine(start);
                  if (startRE && startRE.test(line)) break;
                  if (!/\S/.test(line)) { ++start; break; }
                }
                var endRE = options.paragraphEnd || cm.getHelper(pos, "paragraphEnd");
                for (var end = pos.line + 1, last = cm.lastLine(); end <= last; ++end) {
                  var line = cm.getLine(end);
                  if (endRE && endRE.test(line)) { ++end; break; }
                  if (!/\S/.test(line)) break;
                }
                return {from: start, to: end};
              }
            
              function findBreakPoint(text, column, wrapOn, killTrailingSpace) {
                for (var at = column; at > 0; --at)
                  if (wrapOn.test(text.slice(at - 1, at + 1))) break;
                if (at == 0) at = column;
                var endOfText = at;
                if (killTrailingSpace)
                  while (text.charAt(endOfText - 1) == " ") --endOfText;
                return {from: endOfText, to: at};
              }
            
              function wrapRange(cm, from, to, options) {
                from = cm.clipPos(from); to = cm.clipPos(to);
                var column = options.column || 80;
                var wrapOn = options.wrapOn || /\s\S|-[^\.\d]/;
                var killTrailing = options.killTrailingSpace !== false;
                var changes = [], curLine = "", curNo = from.line;
                var lines = cm.getRange(from, to, false);
                if (!lines.length) return null;
                var leadingSpace = lines[0].match(/^[ \t]*/)[0];
            
                for (var i = 0; i < lines.length; ++i) {
                  var text = lines[i], oldLen = curLine.length, spaceInserted = 0;
                  if (curLine && text && !wrapOn.test(curLine.charAt(curLine.length - 1) + text.charAt(0))) {
                    curLine += " ";
                    spaceInserted = 1;
                  }
                  var spaceTrimmed = "";
                  if (i) {
                    spaceTrimmed = text.match(/^\s*/)[0];
                    text = text.slice(spaceTrimmed.length);
                  }
                  curLine += text;
                  if (i) {
                    var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed &&
                      findBreakPoint(curLine, column, wrapOn, killTrailing);
                    // If this isn't broken, or is broken at a different point, remove old break
                    if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) {
                      changes.push({text: [spaceInserted ? " " : ""],
                                    from: Pos(curNo, oldLen),
                                    to: Pos(curNo + 1, spaceTrimmed.length)});
                    } else {
                      curLine = leadingSpace + text;
                      ++curNo;
                    }
                  }
                  while (curLine.length > column) {
                    var bp = findBreakPoint(curLine, column, wrapOn, killTrailing);
                    changes.push({text: ["", leadingSpace],
                                  from: Pos(curNo, bp.from),
                                  to: Pos(curNo, bp.to)});
                    curLine = leadingSpace + curLine.slice(bp.to);
                    ++curNo;
                  }
                }
                if (changes.length) cm.operation(function() {
                  for (var i = 0; i < changes.length; ++i) {
                    var change = changes[i];
                    cm.replaceRange(change.text, change.from, change.to);
                  }
                });
                return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null;
              }
            
              CodeMirror.defineExtension("wrapParagraph", function(pos, options) {
                options = options || {};
                if (!pos) pos = this.getCursor();
                var para = findParagraph(this, pos, options);
                return wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options);
              });
            
              CodeMirror.commands.wrapLines = function(cm) {
                cm.operation(function() {
                  var ranges = cm.listSelections(), at = cm.lastLine() + 1;
                  for (var i = ranges.length - 1; i >= 0; i--) {
                    var range = ranges[i], span;
                    if (range.empty()) {
                      var para = findParagraph(cm, range.head, {});
                      span = {from: Pos(para.from, 0), to: Pos(para.to - 1)};
                    } else {
                      span = {from: range.from(), to: range.to()};
                    }
                    if (span.to.line >= at) continue;
                    at = span.from.line;
                    wrapRange(cm, span.from, span.to, {});
                  }
                });
              };
            
              CodeMirror.defineExtension("wrapRange", function(from, to, options) {
                return wrapRange(this, from, to, options || {});
              });
            
              CodeMirror.defineExtension("wrapParagraphsInRange", function(from, to, options) {
                options = options || {};
                var cm = this, paras = [];
                for (var line = from.line; line <= to.line;) {
                  var para = findParagraph(cm, Pos(line, 0), options);
                  paras.push(para);
                  line = para.to;
                }
                var madeChange = false;
                if (paras.length) cm.operation(function() {
                  for (var i = paras.length - 1; i >= 0; --i)
                    madeChange = madeChange || wrapRange(cm, Pos(paras[i].from, 0), Pos(paras[i].to - 1), options);
                });
                return madeChange;
              });
            });
            
      • bin
        • authors.sh
          # Combine existing list of authors with everyone known in git, sort, add header.
          tail --lines=+3 AUTHORS > AUTHORS.tmp
          git log --format='%aN' >> AUTHORS.tmp
          echo -e "List of CodeMirror contributors. Updated before every release.\n" > AUTHORS
          sort -u AUTHORS.tmp >> AUTHORS
          rm -f AUTHORS.tmp
          
        • compress
          #!/usr/bin/env node
          
          // Compression helper for CodeMirror
          //
          // Example:
          //
          //   bin/compress codemirror runmode javascript xml
          //
          // Will take lib/codemirror.js, addon/runmode/runmode.js,
          // mode/javascript/javascript.js, and mode/xml/xml.js, run them though
          // the online minifier at http://marijnhaverbeke.nl/uglifyjs, and spit
          // out the result.
          //
          //   bin/compress codemirror --local /path/to/bin/UglifyJS
          //
          // Will use a local minifier instead of the online default one.
          //
          // Script files are specified without .js ending. Prefixing them with
          // their full (local) path is optional. So you may say lib/codemirror
          // or mode/xml/xml to be more precise. In fact, even the .js suffix
          // may be speficied, if wanted.
          
          "use strict";
          
          var fs = require("fs");
          
          function help(ok) {
            console.log("usage: " + process.argv[1] + " [--local /path/to/uglifyjs] files...");
            process.exit(ok ? 0 : 1);
          }
          
          var local = null, args = [], extraArgs = null, files = [], blob = "";
          
          for (var i = 2; i < process.argv.length; ++i) {
            var arg = process.argv[i];
            if (arg == "--local" && i + 1 < process.argv.length) {
              var parts = process.argv[++i].split(/\s+/);
              local = parts[0];
              extraArgs = parts.slice(1);
              if (!extraArgs.length) extraArgs = ["-c", "-m"];
            } else if (arg == "--help") {
              help(true);
            } else if (arg[0] != "-") {
              files.push({name: arg, re: new RegExp("(?:\\/|^)" + arg + (/\.js$/.test(arg) ? "$" : "\\.js$"))});
            } else help(false);
          }
          
          function walk(dir) {
            fs.readdirSync(dir).forEach(function(fname) {
              if (/^[_\.]/.test(fname)) return;
              var file = dir + fname;
              if (fs.statSync(file).isDirectory()) return walk(file + "/");
              if (files.some(function(spec, i) {
                var match = spec.re.test(file);
                if (match) files.splice(i, 1);
                return match;
              })) {
                if (local) args.push(file);
                else blob += fs.readFileSync(file, "utf8");
              }
            });
          }
          
          walk("lib/");
          walk("addon/");
          walk("mode/");
          
          if (!local && !blob) help(false);
          
          if (files.length) {
            console.log("Some speficied files were not found: " +
                        files.map(function(a){return a.name;}).join(", "));
            process.exit(1);
          }
            
          if (local) {
            require("child_process").spawn(local, args.concat(extraArgs), {stdio: ["ignore", process.stdout, process.stderr]});
          } else {
            var data = new Buffer("js_code=" + require("querystring").escape(blob), "utf8");
            var req = require("http").request({
              host: "marijnhaverbeke.nl",
              port: 80,
              method: "POST",
              path: "/uglifyjs",
              headers: {"content-type": "application/x-www-form-urlencoded",
                        "content-length": data.length}
            });
            req.on("response", function(resp) {
              resp.on("data", function (chunk) { process.stdout.write(chunk); });
            });
            req.end(data);
          }
          
        • lint
          #!/usr/bin/env node
          
          process.exit(require("../test/lint").ok ? 0 : 1);
          
        • release
          #!/usr/bin/env node
          
          var fs = require("fs"), child = require("child_process");
          
          var number, bumpOnly;
          
          for (var i = 2; i < process.argv.length; i++) {
            if (process.argv[i] == "-bump") bumpOnly = true;
            else if (/^\d+\.\d+\.\d+$/.test(process.argv[i])) number = process.argv[i];
            else { console.log("Bogus command line arg: " + process.argv[i]); process.exit(1); }
          }
          
          if (!number) { console.log("Must give a version"); process.exit(1); }
          
          function rewrite(file, f) {
            fs.writeFileSync(file, f(fs.readFileSync(file, "utf8")), "utf8");
          }
          
          rewrite("lib/codemirror.js", function(lib) {
            return lib.replace(/CodeMirror\.version = "\d+\.\d+\.\d+"/,
                               "CodeMirror.version = \"" + number + "\"");
          });
          function rewriteJSON(pack) {
            return pack.replace(/"version":"\d+\.\d+\.\d+"/, "\"version\":\"" + number + "\"");
          }
          rewrite("package.json", rewriteJSON);
          rewrite("bower.json", rewriteJSON);
          rewrite("doc/manual.html", function(manual) {
            return manual.replace(/>version \d+\.\d+\.\d+<\/span>/, ">version " + number + "</span>");
          });
          
          if (bumpOnly) process.exit(0);
          
          child.exec("bash bin/authors.sh", function(){});
          
          var simple = number.slice(0, number.lastIndexOf("."));
          
          rewrite("doc/compress.html", function(cmp) {
            return cmp.replace(/<option value="http:\/\/codemirror.net\/">HEAD<\/option>/,
                               "<option value=\"http://codemirror.net/\">HEAD</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=" + number + ";f=\">" + simple + "</option>");
          });
          
          rewrite("index.html", function(index) {
            return index.replace(/\.zip">\d+\.\d+<\/a>/,
                                 ".zip\">" + simple + "</a>");
          });
          
        • source-highlight
          #!/usr/bin/env node
          
          // Simple command-line code highlighting tool. Reads code from stdin,
          // spits html to stdout. For example:
          //
          //   echo 'function foo(a) { return a; }' | bin/source-highlight -s javascript
          //   bin/source-highlight -s 
          
          var fs = require("fs");
          
          var CodeMirror = require("../addon/runmode/runmode.node.js");
          require("../mode/meta.js");
          
          var sPos = process.argv.indexOf("-s");
          if (sPos == -1 || sPos == process.argv.length - 1) {
             console.error("Usage: source-highlight -s language");
             process.exit(1);
          }
          var lang = process.argv[sPos + 1].toLowerCase(), modeName = lang;
          CodeMirror.modeInfo.forEach(function(info) {
            if (info.mime == lang) {
              modeName = info.mode;
            } else if (info.name.toLowerCase() == lang) {
              modeName = info.mode;
              lang = info.mime;
            }
          });
          
          if (!CodeMirror.modes[modeName])
            require("../mode/" + modeName + "/" + modeName + ".js");
          
          function esc(str) {
            return str.replace(/[<&]/g, function(ch) { return ch == "&" ? "&amp;" : "&lt;"; });
          }
          
          var code = fs.readFileSync("/dev/stdin", "utf8");
          var curStyle = null, accum = "";
          function flush() {
            if (curStyle) process.stdout.write("<span class=\"" + curStyle.replace(/(^|\s+)/g, "$1cm-") + "\">" + esc(accum) + "</span>");
            else process.stdout.write(esc(accum));
          }
          
          CodeMirror.runMode(code, lang, function(text, style) {
            if (style != curStyle) {
              flush();
              curStyle = style; accum = text;
            } else {
              accum += text;
            }
          });
          flush();
          
      • demo
        • activeline.html
          <!doctype html>
          
          <title>CodeMirror: Active Line Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../addon/selection/active-line.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Active Line</a>
            </ul>
          </div>
          
          <article>
          <h2>Active Line Demo</h2>
          <form><textarea id="code" name="code">
          <?xml version="1.0" encoding="UTF-8"?>
          <rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"
               xmlns:georss="http://www.georss.org/georss"
               xmlns:twitter="http://api.twitter.com">
            <channel>
              <title>Twitter / codemirror</title>
              <link>http://twitter.com/codemirror</link>
              <atom:link type="application/rss+xml"
                         href="http://twitter.com/statuses/user_timeline/242283288.rss" rel="self"/>
              <description>Twitter updates from CodeMirror / codemirror.</description>
              <language>en-us</language>
              <ttl>40</ttl>
            <item>
              <title>codemirror: http://cloud-ide.com &#8212; they're springing up like mushrooms. This one
                uses CodeMirror as its editor.</title>
              <description>codemirror: http://cloud-ide.com &#8212; they're springing up like mushrooms. This
                one uses CodeMirror as its editor.</description>
              <pubDate>Thu, 17 Mar 2011 23:34:47 +0000</pubDate>
              <guid>http://twitter.com/codemirror/statuses/48527733722058752</guid>
              <link>http://twitter.com/codemirror/statuses/48527733722058752</link>
              <twitter:source>web</twitter:source>
              <twitter:place/>
            </item>
            <item>
              <title>codemirror: Posted a description of the CodeMirror 2 internals at
                http://codemirror.net/2/internals.html</title>
              <description>codemirror: Posted a description of the CodeMirror 2 internals at
                http://codemirror.net/2/internals.html</description>
              <pubDate>Wed, 02 Mar 2011 12:15:09 +0000</pubDate>
              <guid>http://twitter.com/codemirror/statuses/42920879788789760</guid>
              <link>http://twitter.com/codemirror/statuses/42920879788789760</link>
              <twitter:source>web</twitter:source>
              <twitter:place/>
            </item>
            </channel>
          </rss></textarea></form>
          
              <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            mode: "application/xml",
            styleActiveLine: true,
            lineNumbers: true,
            lineWrapping: true
          });
          </script>
          
              <p>Styling the current cursor line.</p>
          
            </article>
          
        • anywordhint.html
          <!doctype html>
          
          <title>CodeMirror: Any Word Completion Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/hint/show-hint.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/hint/show-hint.js"></script>
          <script src="../addon/hint/anyword-hint.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Any Word Completion</a>
            </ul>
          </div>
          
          <article>
          <h2>Any Word Completion Demo</h2>
          <form><textarea id="code" name="code">
          (function() {
            "use strict";
          
            var WORD = /[\w$]+/g, RANGE = 500;
          
            CodeMirror.registerHelper("hint", "anyword", function(editor, options) {
              var word = options && options.word || WORD;
              var range = options && options.range || RANGE;
              var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
              var start = cur.ch, end = start;
              while (end < curLine.length && word.test(curLine.charAt(end))) ++end;
              while (start && word.test(curLine.charAt(start - 1))) --start;
              var curWord = start != end && curLine.slice(start, end);
          
              var list = [], seen = {};
              function scan(dir) {
                var line = cur.line, end = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
                for (; line != end; line += dir) {
                  var text = editor.getLine(line), m;
                  word.lastIndex = 0;
                  while (m = word.exec(text)) {
                    if ((!curWord || m[0].indexOf(curWord) == 0) && !seen.hasOwnProperty(m[0])) {
                      seen[m[0]] = true;
                      list.push(m[0]);
                    }
                  }
                }
              }
              scan(-1);
              scan(1);
              return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
            });
          })();
          </textarea></form>
          
          <p>Press <strong>ctrl-space</strong> to activate autocompletion. The
          completion uses
          the <a href="../doc/manual.html#addon_anyword-hint">anyword-hint.js</a>
          module, which simply looks at nearby words in the buffer and completes
          to those.</p>
          
              <script>
                CodeMirror.commands.autocomplete = function(cm) {
                  cm.showHint({hint: CodeMirror.hint.anyword});
                }
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  extraKeys: {"Ctrl-Space": "autocomplete"}
                });
              </script>
            </article>
          
        • bidi.html
          <!doctype html>
          
          <title>CodeMirror: Bi-directional Text Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Bi-directional Text</a>
            </ul>
          </div>
          
          <article>
          <h2>Bi-directional Text Demo</h2>
          <form><textarea id="code" name="code"><!-- Piece of the CodeMirror manual, 'translated' into Arabic by
               Google Translate -->
          
          <dl>
            <dt id=option_value><code>value (string or Doc)</code></dt>
            <dd>قيمة البداية المحرر. يمكن أن تكون سلسلة، أو. كائن مستند.</dd>
            <dt id=option_mode><code>mode (string or object)</code></dt>
            <dd>وضع الاستخدام. عندما لا تعطى، وهذا الافتراضي إلى الطريقة الاولى
            التي تم تحميلها. قد يكون من سلسلة، والتي إما أسماء أو ببساطة هو وضع
            MIME نوع المرتبطة اسطة. بدلا من ذلك، قد يكون من كائن يحتوي على
            خيارات التكوين لواسطة، مع <code>name</code> الخاصية التي وضع أسماء
            (على سبيل المثال <code>{name: "javascript", json: true}</code>).
            صفحات التجريبي لكل وضع تحتوي على معلومات حول ما معلمات تكوين وضع
            يدعمها. يمكنك أن تطلب CodeMirror التي تم تعريفها طرق وأنواع MIME
            الكشف على <code>CodeMirror.modes</code>
            و <code>CodeMirror.mimeModes</code> الكائنات. وضع خرائط الأسماء
            الأولى لمنشئات الخاصة بهم، وخرائط لأنواع MIME 2 المواصفات
            واسطة.</dd>
            <dt id=option_theme><code>theme (string)</code></dt>
            <dd>موضوع لنمط المحرر مع. يجب عليك التأكد من الملف CSS تحديد
            المقابلة <code>.cm-s-[name]</code> يتم تحميل أنماط (انظر
            <a href="../theme/"><code>theme</code></a> الدليل في التوزيع).
            الافتراضي هو <code>"default"</code> ، والتي تم تضمينها في
            الألوان <code>codemirror.css</code>. فمن الممكن استخدام فئات متعددة
            في تطبيق السمات مرة واحدة على سبيل المثال <code>"foo bar"</code>
            سيتم تعيين كل من <code>cm-s-foo</code> و <code>cm-s-bar</code>
            الطبقات إلى المحرر.</dd>
          </dl>
          </textarea></form>
          
              <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            mode: "text/html",
            lineNumbers: true
          });
          </script>
          
            <p>Demonstration of bi-directional text support. See
            the <a href="http://marijnhaverbeke.nl/blog/cursor-in-bidi-text.html">related
            blog post</a> for more background.</p>
          
            <p><strong>Note:</strong> There is
            a <a href="https://github.com/codemirror/CodeMirror/issues/1757">known
            bug</a> with cursor motion and mouse clicks in bi-directional lines
            that are line wrapped.</p>
          
          </article>
          
        • btree.html
          <!doctype html>
          
          <title>CodeMirror: B-Tree visualization</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <style type="text/css">
                .lineblock { display: inline-block; margin: 1px; height: 5px; }
                .CodeMirror {border: 1px solid #aaa; height: 400px}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">B-Tree visualization</a>
            </ul>
          </div>
          
          <article>
          <h2>B-Tree visualization</h2>
          <form><textarea id="code" name="code">type here, see a summary of the document b-tree below</textarea></form>
                </div>
                <div style="display: inline-block; height: 402px; overflow-y: auto" id="output"></div>
              </div>
          
              <script id="me">
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            lineNumbers: true,
            lineWrapping: true
          });
          var updateTimeout;
          editor.on("change", function(cm) {
            clearTimeout(updateTimeout);
            updateTimeout = setTimeout(updateVisual, 200);
          });
          updateVisual();
          
          function updateVisual() {
            var out = document.getElementById("output");
            out.innerHTML = "";
          
            function drawTree(out, node) {
              if (node.lines) {
                out.appendChild(document.createElement("div")).innerHTML =
                  "<b>leaf</b>: " + node.lines.length + " lines, " + Math.round(node.height) + " px";
                var lines = out.appendChild(document.createElement("div"));
                lines.style.lineHeight = "6px"; lines.style.marginLeft = "10px";
                for (var i = 0; i < node.lines.length; ++i) {
                  var line = node.lines[i], lineElt = lines.appendChild(document.createElement("div"));
                  lineElt.className = "lineblock";
                  var gray = Math.min(line.text.length * 3, 230), col = gray.toString(16);
                  if (col.length == 1) col = "0" + col;
                  lineElt.style.background = "#" + col + col + col;
                  lineElt.style.width = Math.max(Math.round(line.height / 3), 1) + "px";
                }
              } else {
                out.appendChild(document.createElement("div")).innerHTML =
                  "<b>node</b>: " + node.size + " lines, " + Math.round(node.height) + " px";
                var sub = out.appendChild(document.createElement("div"));
                sub.style.paddingLeft = "20px";
                for (var i = 0; i < node.children.length; ++i)
                  drawTree(sub, node.children[i]);
              }
            }
            drawTree(out, editor.getDoc());
          }
          
          function fillEditor() {
            var sc = document.getElementById("me");
            var doc = (sc.textContent || sc.innerText || sc.innerHTML).replace(/^\s*/, "") + "\n";
            doc += doc; doc += doc; doc += doc; doc += doc; doc += doc; doc += doc;
            editor.setValue(doc);
          }
              </script>
          
          <p><button onclick="fillEditor()">Add a lot of content</button></p>
          
            </article>
          
        • buffers.html
          <!doctype html>
          
          <title>CodeMirror: Multiple Buffer & Split View Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/css/css.js"></script>
          <style type="text/css" id=style>
                .CodeMirror {border: 1px solid black; height: 250px;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Multiple Buffer & Split View</a>
            </ul>
          </div>
          
          <article>
          <h2>Multiple Buffer & Split View Demo</h2>
          
          
              <div id=code_top></div>
              <div>
                Select buffer: <select id=buffers_top></select>
                &nbsp; &nbsp; <button onclick="newBuf('top')">New buffer</button>
              </div>
              <div id=code_bot></div>
              <div>
                Select buffer: <select id=buffers_bot></select>
                &nbsp; &nbsp; <button onclick="newBuf('bot')">New buffer</button>
              </div>
          
              <script id=script>
          var sel_top = document.getElementById("buffers_top");
          CodeMirror.on(sel_top, "change", function() {
            selectBuffer(ed_top, sel_top.options[sel_top.selectedIndex].value);
          });
          
          var sel_bot = document.getElementById("buffers_bot");
          CodeMirror.on(sel_bot, "change", function() {
            selectBuffer(ed_bot, sel_bot.options[sel_bot.selectedIndex].value);
          });
          
          var buffers = {};
          
          function openBuffer(name, text, mode) {
            buffers[name] = CodeMirror.Doc(text, mode);
            var opt = document.createElement("option");
            opt.appendChild(document.createTextNode(name));
            sel_top.appendChild(opt);
            sel_bot.appendChild(opt.cloneNode(true));
          }
          
          function newBuf(where) {
            var name = prompt("Name for the buffer", "*scratch*");
            if (name == null) return;
            if (buffers.hasOwnProperty(name)) {
              alert("There's already a buffer by that name.");
              return;
            }
            openBuffer(name, "", "javascript");
            selectBuffer(where == "top" ? ed_top : ed_bot, name);
            var sel = where == "top" ? sel_top : sel_bot;
            sel.value = name;
          }
          
          function selectBuffer(editor, name) {
            var buf = buffers[name];
            if (buf.getEditor()) buf = buf.linkedDoc({sharedHist: true});
            var old = editor.swapDoc(buf);
            var linked = old.iterLinkedDocs(function(doc) {linked = doc;});
            if (linked) {
              // Make sure the document in buffers is the one the other view is looking at
              for (var name in buffers) if (buffers[name] == old) buffers[name] = linked;
              old.unlinkDoc(linked);
            }
            editor.focus();
          }
          
          function nodeContent(id) {
            var node = document.getElementById(id), val = node.textContent || node.innerText;
            val = val.slice(val.match(/^\s*/)[0].length, val.length - val.match(/\s*$/)[0].length) + "\n";
            return val;
          }
          openBuffer("js", nodeContent("script"), "javascript");
          openBuffer("css", nodeContent("style"), "css");
          
          var ed_top = CodeMirror(document.getElementById("code_top"), {lineNumbers: true});
          selectBuffer(ed_top, "js");
          var ed_bot = CodeMirror(document.getElementById("code_bot"), {lineNumbers: true});
          selectBuffer(ed_bot, "js");
          </script>
          
              <p>Demonstration of
              using <a href="../doc/manual.html#linkedDoc">linked documents</a>
              to provide a split view on a document, and
              using <a href="../doc/manual.html#swapDoc"><code>swapDoc</code></a>
              to use a single editor to display multiple documents.</p>
          
            </article>
          
        • changemode.html
          <!doctype html>
          
          <title>CodeMirror: Mode-Changing Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/scheme/scheme.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid black;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Mode-Changing</a>
            </ul>
          </div>
          
          <article>
          <h2>Mode-Changing Demo</h2>
          <form><textarea id="code" name="code">
          ;; If there is Scheme code in here, the editor will be in Scheme mode.
          ;; If you put in JS instead, it'll switch to JS mode.
          
          (define (double x)
            (* x x))
          </textarea></form>
          
          <p>On changes to the content of the above editor, a (crude) script
          tries to auto-detect the language used, and switches the editor to
          either JavaScript or Scheme mode based on that.</p>
          
          <script>
            var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
              mode: "scheme",
              lineNumbers: true
            });
            var pending;
            editor.on("change", function() {
              clearTimeout(pending);
              pending = setTimeout(update, 400);
            });
            function looksLikeScheme(code) {
              return !/^\s*\(\s*function\b/.test(code) && /^\s*[;\(]/.test(code);
            }
            function update() {
              editor.setOption("mode", looksLikeScheme(editor.getValue()) ? "scheme" : "javascript");
            }
          </script>
            </article>
          
        • closebrackets.html
          <!doctype html>
          
          <title>CodeMirror: Closebrackets Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/edit/closebrackets.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Closebrackets</a>
            </ul>
          </div>
          
          <article>
          <h2>Closebrackets Demo</h2>
          <form><textarea id="code" name="code">function Grid(width, height) {
            this.width = width;
            this.height = height;
            this.cells = new Array(width * height);
          }
          Grid.prototype.valueAt = function(point) {
            return this.cells[point.y * this.width + point.x];
          };
          Grid.prototype.setValueAt = function(point, value) {
            this.cells[point.y * this.width + point.x] = value;
          };
          Grid.prototype.isInside = function(point) {
            return point.x >= 0 && point.y >= 0 &&
                   point.x < this.width && point.y < this.height;
          };
          Grid.prototype.moveValue = function(from, to) {
            this.setValueAt(to, this.valueAt(from));
            this.setValueAt(from, undefined);
          };</textarea></form>
          
              <script type="text/javascript">
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {autoCloseBrackets: true});
              </script>
            </article>
          
        • closetag.html
          <!doctype html>
          
          <title>CodeMirror: Close-Tag Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/edit/closetag.js"></script>
          <script src="../addon/fold/xml-fold.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/css/css.js"></script>
          <script src="../mode/htmlmixed/htmlmixed.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Close-Tag</a>
            </ul>
          </div>
          
          <article>
          <h2>Close-Tag Demo</h2>
          <form><textarea id="code" name="code"><html</textarea></form>
          
              <script type="text/javascript">
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  mode: 'text/html',
                  autoCloseTags: true
                });
              </script>
            </article>
          
        • complete.html
          <!doctype html>
          
          <title>CodeMirror: Autocomplete Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/hint/show-hint.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/hint/show-hint.js"></script>
          <script src="../addon/hint/javascript-hint.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Autocomplete</a>
            </ul>
          </div>
          
          <article>
          <h2>Autocomplete Demo</h2>
          <form><textarea id="code" name="code">
          function getCompletions(token, context) {
            var found = [], start = token.string;
            function maybeAdd(str) {
              if (str.indexOf(start) == 0) found.push(str);
            }
            function gatherCompletions(obj) {
              if (typeof obj == "string") forEach(stringProps, maybeAdd);
              else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
              else if (obj instanceof Function) forEach(funcProps, maybeAdd);
              for (var name in obj) maybeAdd(name);
            }
          
            if (context) {
              // If this is a property, see if it belongs to some object we can
              // find in the current environment.
              var obj = context.pop(), base;
              if (obj.className == "js-variable")
                base = window[obj.string];
              else if (obj.className == "js-string")
                base = "";
              else if (obj.className == "js-atom")
                base = 1;
              while (base != null && context.length)
                base = base[context.pop().string];
              if (base != null) gatherCompletions(base);
            }
            else {
              // If not, just look in the window object and any local scope
              // (reading into JS mode internals to get at the local variables)
              for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
              gatherCompletions(window);
              forEach(keywords, maybeAdd);
            }
            return found;
          }
          </textarea></form>
          
          <p>Press <strong>ctrl-space</strong> to activate autocompletion. Built
          on top of the <a href="../doc/manual.html#addon_show-hint"><code>show-hint</code></a>
          and <a href="../doc/manual.html#addon_javascript-hint"><code>javascript-hint</code></a>
          addons.</p>
          
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  extraKeys: {"Ctrl-Space": "autocomplete"},
                  mode: {name: "javascript", globalVars: true}
                });
              </script>
            </article>
          
        • emacs.html
          <!doctype html>
          
          <title>CodeMirror: Emacs bindings demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/dialog/dialog.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/clike/clike.js"></script>
          <script src="../keymap/emacs.js"></script>
          <script src="../addon/edit/matchbrackets.js"></script>
          <script src="../addon/comment/comment.js"></script>
          <script src="../addon/dialog/dialog.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../addon/search/search.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Emacs bindings</a>
            </ul>
          </div>
          
          <article>
          <h2>Emacs bindings demo</h2>
          <form><textarea id="code" name="code">
          #include "syscalls.h"
          /* getchar:  simple buffered version */
          int getchar(void)
          {
            static char buf[BUFSIZ];
            static char *bufp = buf;
            static int n = 0;
            if (n == 0) {  /* buffer is empty */
              n = read(0, buf, sizeof buf);
              bufp = buf;
            }
            return (--n >= 0) ? (unsigned char) *bufp++ : EOF;
          }
          </textarea></form>
          
          <p>The emacs keybindings are enabled by
          including <a href="../keymap/emacs.js">keymap/emacs.js</a> and setting
          the <code>keyMap</code> option to <code>"emacs"</code>. Because
          CodeMirror's internal API is quite different from Emacs, they are only
          a loose approximation of actual emacs bindings, though.</p>
          
          <p>Also note that a lot of browsers disallow certain keys from being
          captured. For example, Chrome blocks both Ctrl-W and Ctrl-N, with the
          result that idiomatic use of Emacs keys will constantly close your tab
          or open a new window.</p>
          
              <script>
                CodeMirror.commands.save = function() {
                  var elt = editor.getWrapperElement();
                  elt.style.background = "#def";
                  setTimeout(function() { elt.style.background = ""; }, 300);
                };
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  mode: "text/x-csrc",
                  keyMap: "emacs"
                });
              </script>
          
            </article>
          
        • folding.html
          <!doctype html>
          
          <head>
            <title>CodeMirror: Code Folding Demo</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../doc/docs.css">
          
            <link rel="stylesheet" href="../lib/codemirror.css">
            <link rel="stylesheet" href="../addon/fold/foldgutter.css" />
            <script src="../lib/codemirror.js"></script>
            <script src="../addon/fold/foldcode.js"></script>
            <script src="../addon/fold/foldgutter.js"></script>
            <script src="../addon/fold/brace-fold.js"></script>
            <script src="../addon/fold/xml-fold.js"></script>
            <script src="../addon/fold/markdown-fold.js"></script>
            <script src="../addon/fold/comment-fold.js"></script>
            <script src="../mode/javascript/javascript.js"></script>
            <script src="../mode/xml/xml.js"></script>
            <script src="../mode/markdown/markdown.js"></script>
            <style type="text/css">
              .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
            </style>
          </head>
          
          <body>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Code Folding</a>
            </ul>
          </div>
          
          <article>
            <h2>Code Folding Demo</h2>
            <form>
              <div style="max-width: 50em; margin-bottom: 1em">JavaScript:<br>
              <textarea id="code" name="code"></textarea></div>
              <div style="max-width: 50em; margin-bottom: 1em">HTML:<br>
              <textarea id="code-html" name="code-html"></textarea></div>
              <div style="max-width: 50em">Markdown:<br>
              <textarea id="code-markdown" name="code"></textarea></div>
            </form>
            <script id="script">
          /*
           * Demonstration of code folding
           */
          window.onload = function() {
            var te = document.getElementById("code");
            var sc = document.getElementById("script");
            te.value = (sc.textContent || sc.innerText || sc.innerHTML).replace(/^\s*/, "");
            sc.innerHTML = "";
            var te_html = document.getElementById("code-html");
            te_html.value = document.documentElement.innerHTML;
            var te_markdown = document.getElementById("code-markdown");
            te_markdown.value = "# Foo\n## Bar\n\nblah blah\n\n## Baz\n\nblah blah\n\n# Quux\n\nblah blah\n"
          
            window.editor = CodeMirror.fromTextArea(te, {
              mode: "javascript",
              lineNumbers: true,
              lineWrapping: true,
              extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
              foldGutter: true,
              gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
            });
            editor.foldCode(CodeMirror.Pos(13, 0));
          
            window.editor_html = CodeMirror.fromTextArea(te_html, {
              mode: "text/html",
              lineNumbers: true,
              lineWrapping: true,
              extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
              foldGutter: true,
              gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
            });
            editor_html.foldCode(CodeMirror.Pos(0, 0));
            editor_html.foldCode(CodeMirror.Pos(21, 0));
          
            window.editor_markdown = CodeMirror.fromTextArea(te_markdown, {
              mode: "markdown",
              lineNumbers: true,
              lineWrapping: true,
              extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
              foldGutter: true,
              gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
            });
          };
            </script>
          </article>
          </body>
          
        • fullscreen.html
          <!doctype html>
          
          <title>CodeMirror: Full Screen Editing</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/display/fullscreen.css">
          <link rel="stylesheet" href="../theme/night.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../addon/display/fullscreen.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Full Screen Editing</a>
            </ul>
          </div>
          
          <article>
          <h2>Full Screen Editing</h2>
          <form><textarea id="code" name="code" rows="5">
          <dl>
            <dt id="option_indentWithTabs"><code><strong>indentWithTabs</strong>: boolean</code></dt>
            <dd>Whether, when indenting, the first N*<code>tabSize</code>
            spaces should be replaced by N tabs. Default is false.</dd>
          
            <dt id="option_electricChars"><code><strong>electricChars</strong>: boolean</code></dt>
            <dd>Configures whether the editor should re-indent the current
            line when a character is typed that might change its proper
            indentation (only works if the mode supports indentation).
            Default is true.</dd>
          
            <dt id="option_specialChars"><code><strong>specialChars</strong>: RegExp</code></dt>
            <dd>A regular expression used to determine which characters
            should be replaced by a
            special <a href="#option_specialCharPlaceholder">placeholder</a>.
            Mostly useful for non-printing special characters. The default
            is <code>/[\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/</code>.</dd>
            <dt id="option_specialCharPlaceholder"><code><strong>specialCharPlaceholder</strong>: function(char) → Element</code></dt>
            <dd>A function that, given a special character identified by
            the <a href="#option_specialChars"><code>specialChars</code></a>
            option, produces a DOM node that is used to represent the
            character. By default, a red dot (<span style="color: red">•</span>)
            is shown, with a title tooltip to indicate the character code.</dd>
          
            <dt id="option_rtlMoveVisually"><code><strong>rtlMoveVisually</strong>: boolean</code></dt>
            <dd>Determines whether horizontal cursor movement through
            right-to-left (Arabic, Hebrew) text is visual (pressing the left
            arrow moves the cursor left) or logical (pressing the left arrow
            moves to the next lower index in the string, which is visually
            right in right-to-left text). The default is <code>false</code>
            on Windows, and <code>true</code> on other platforms.</dd>
          </dl>
          </textarea></form>
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                lineNumbers: true,
                theme: "night",
                extraKeys: {
                  "F11": function(cm) {
                    cm.setOption("fullScreen", !cm.getOption("fullScreen"));
                  },
                  "Esc": function(cm) {
                    if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
                  }
                }
              });
            </script>
          
              <p>Demonstration of
              the <a href="../doc/manual.html#addon_fullscreen">fullscreen</a>
              addon. Press <strong>F11</strong> when cursor is in the editor to
              toggle full screen editing. <strong>Esc</strong> can also be used
              to <i>exit</i> full screen editing.</p>
            </article>
          
        • hardwrap.html
          <!doctype html>
          
          <title>CodeMirror: Hard-wrapping Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/markdown/markdown.js"></script>
          <script src="../addon/wrap/hardwrap.js"></script>
          <style type="text/css">
            .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
          </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Hard-wrapping</a>
            </ul>
          </div>
          
          <article>
          <h2>Hard-wrapping Demo</h2>
          <form><textarea id="code" name="code">Lorem ipsum dolor sit amet, vim augue dictas constituto ex,
          sit falli simul viderer te. Graeco scaevola maluisset sit
          ut, in idque viris praesent sea. Ea sea eirmod indoctum
          repudiare. Vel noluisse suscipit pericula ut. In ius nulla
          alienum molestie. Mei essent discere democritum id.
          
          Equidem ponderum expetendis ius in, mea an erroribus
          constituto, congue timeam perfecto ad est. Ius ut primis
          timeam, per in ullum mediocrem. An case vero labitur pri,
          vel dicit laoreet et. An qui prompta conclusionemque, eam
          timeam sapientem in, cum dictas epicurei eu.
          
          Usu cu vide dictas deseruisse, eum choro graece adipiscing
          ut. Cibo qualisque ius ad, et dicat scripta mea, eam nihil
          mentitum aliquando cu. Debet aperiam splendide at quo, ad
          paulo nostro commodo duo. Sea adhuc utinam conclusionemque
          id, quas doming malorum nec ad. Tollit eruditi vivendum ad
          ius, eos soleat ignota ad.
          </textarea></form>
          
          <p>Demonstration of
          the <a href="../doc/manual.html#addon_hardwrap">hardwrap</a> addon.
          The above editor has its change event hooked up to
          the <code>wrapParagraphsInRange</code> method, so that the paragraphs
          are reflown as you are typing.</p>
          
          <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            mode: "markdown",
            lineNumbers: true,
            extraKeys: {
              "Ctrl-Q": function(cm) { cm.wrapParagraph(cm.getCursor(), options); }
            }
          });
          var wait, options = {column: 60};
          editor.on("change", function(cm, change) {
            clearTimeout(wait);
            wait = setTimeout(function() {
              console.log(cm.wrapParagraphsInRange(change.from, CodeMirror.changeEnd(change), options));
            }, 200);
          });
          </script>
          
          </article>
          
        • html5complete.html
          <!doctype html>
          
          <head>
            <title>CodeMirror: HTML completion demo</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../doc/docs.css">
          
            <link rel="stylesheet" href="../lib/codemirror.css">
            <link rel="stylesheet" href="../addon/hint/show-hint.css">
            <script src="../lib/codemirror.js"></script>
            <script src="../addon/hint/show-hint.js"></script>
            <script src="../addon/hint/xml-hint.js"></script>
            <script src="../addon/hint/html-hint.js"></script>
            <script src="../mode/xml/xml.js"></script>
            <script src="../mode/javascript/javascript.js"></script>
            <script src="../mode/css/css.js"></script>
            <script src="../mode/htmlmixed/htmlmixed.js"></script>
            <style type="text/css">
              .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
            </style>
          </head>
          
          <body>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
              <ul>
                <li><a href="../index.html">Home</a>
                <li><a href="../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a class=active href="#">HTML completion</a>
              </ul>
            </div>
          
            <article>
              <h2>HTML completion demo</h2>
          
              <p>Shows the <a href="xmlcomplete.html">XML completer</a>
              parameterized with information about the tags in HTML.
              Press <strong>ctrl-space</strong> to activate completion.</p>
          
              <div id="code"></div>
          
              <script type="text/javascript">
                window.onload = function() {
                  editor = CodeMirror(document.getElementById("code"), {
                    mode: "text/html",
                    extraKeys: {"Ctrl-Space": "autocomplete"},
                    value: document.documentElement.innerHTML
                  });
                };
              </script>
            </article>
          </body>
          
        • indentwrap.html
          <!doctype html>
          
          <title>CodeMirror: Indented wrapped line demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                .CodeMirror pre > * { text-indent: 0px; }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Indented wrapped line</a>
            </ul>
          </div>
          
          <article>
          <h2>Indented wrapped line demo</h2>
          <form><textarea id="code" name="code">
          <!doctype html>
          <body>
            <h2 id="overview">Overview</h2>
          
            <p>CodeMirror is a code-editor component that can be embedded in Web pages. The core library provides <em>only</em> the editor component, no accompanying buttons, auto-completion, or other IDE functionality. It does provide a rich API on top of which such functionality can be straightforwardly implemented. See the <a href="#addons">add-ons</a> included in the distribution, and the <a href="https://github.com/jagthedrummer/codemirror-ui">CodeMirror UI</a> project, for reusable implementations of extra features.</p>
          
            <p>CodeMirror works with language-specific modes. Modes are JavaScript programs that help color (and optionally indent) text written in a given language. The distribution comes with a number of modes (see the <a href="../mode/"><code>mode/</code></a> directory), and it isn't hard to <a href="#modeapi">write new ones</a> for other languages.</p>
          </body>
          </textarea></form>
          
              <p>This page uses a hack on top of the <code>"renderLine"</code>
              event to make wrapped text line up with the base indentation of
              the line.</p>
          
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  lineWrapping: true,
                  mode: "text/html"
                });
                var charWidth = editor.defaultCharWidth(), basePadding = 4;
                editor.on("renderLine", function(cm, line, elt) {
                  var off = CodeMirror.countColumn(line.text, null, cm.getOption("tabSize")) * charWidth;
                  elt.style.textIndent = "-" + off + "px";
                  elt.style.paddingLeft = (basePadding + off) + "px";
                });
                editor.refresh();
              </script>
          
            </article>
          
        • lint.html
          <!doctype html>
          
          <title>CodeMirror: Linter Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/lint/lint.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/css/css.js"></script>
          <script src="//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js"></script>
          <script src="https://rawgithub.com/zaach/jsonlint/79b553fb65c192add9066da64043458981b3972b/lib/jsonlint.js"></script>
          <script src="https://rawgithub.com/stubbornella/csslint/master/release/csslint.js"></script>
          <script src="../addon/lint/lint.js"></script>
          <script src="../addon/lint/javascript-lint.js"></script>
          <script src="../addon/lint/json-lint.js"></script>
          <script src="../addon/lint/css-lint.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid black;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Linter</a>
            </ul>
          </div>
          
          <article>
          <h2>Linter Demo</h2>
          
          
              <p><textarea id="code-js">var widgets = []
          function updateHints() {
            editor.operation(function(){
              for (var i = 0; i < widgets.length; ++i)
                editor.removeLineWidget(widgets[i]);
              widgets.length = 0;
          
              JSHINT(editor.getValue());
              for (var i = 0; i < JSHINT.errors.length; ++i) {
                var err = JSHINT.errors[i];
                if (!err) continue;
                var msg = document.createElement("div");
                var icon = msg.appendChild(document.createElement("span"));
                icon.innerHTML = "!!";
                icon.className = "lint-error-icon";
                msg.appendChild(document.createTextNode(err.reason));
                msg.className = "lint-error";
                widgets.push(editor.addLineWidget(err.line - 1, msg, {coverGutter: false, noHScroll: true}));
              }
            });
            var info = editor.getScrollInfo();
            var after = editor.charCoords({line: editor.getCursor().line + 1, ch: 0}, "local").top;
            if (info.top + info.clientHeight < after)
              editor.scrollTo(null, after - info.clientHeight + 3);
          }
          </textarea></p>
          
              <p><textarea id="code-json">[
           {
            _id: "post 1",
            "author": "Bob",
            "content": "...",
            "page_views": 5
           },
           {
            "_id": "post 2",
            "author": "Bob",
            "content": "...",
            "page_views": 9
           },
           {
            "_id": "post 3",
            "author": "Bob",
            "content": "...",
            "page_views": 8
           }
          ]
          </textarea></p>
          
              <p><textarea id="code-css">@charset "UTF-8";
          
          @import url("booya.css") print, screen;
          @import "whatup.css" screen;
          @import "wicked.css";
          
          /*Error*/
          @charset "UTF-8";
          
          
          @namespace "http://www.w3.org/1999/xhtml";
          @namespace svg "http://www.w3.org/2000/svg";
          
          /*Warning: empty ruleset */
          .foo {
          }
          
          h1 {
              font-weight: bold;
          }
          
          /*Warning: qualified heading */
          .foo h1 {
              font-weight: bold;
          }
          
          /*Warning: adjoining classes */
          .foo.bar {
              zoom: 1;
          }
          
          li.inline {
              width: 100%;  /*Warning: 100% can be problematic*/
          }
          
          li.last {
            display: inline;
            padding-left: 3px !important;
            padding-right: 3px;
            border-right: 0px;
          }
          
          @media print {
              li.inline {
                color: black;
              }
          }
          
          @page {
            margin: 10%;
            counter-increment: page;
          
            @top-center {
              font-family: sans-serif;
              font-weight: bold;
              font-size: 2em;
              content: counter(page);
            }
          }
          </textarea></p>
          <script>
            var editor = CodeMirror.fromTextArea(document.getElementById("code-js"), {
              lineNumbers: true,
              mode: "javascript",
              gutters: ["CodeMirror-lint-markers"],
              lint: true
            });
          
            var editor_json = CodeMirror.fromTextArea(document.getElementById("code-json"), {
              lineNumbers: true,
              mode: "application/json",
              gutters: ["CodeMirror-lint-markers"],
              lint: true
            });
            
            var editor_css = CodeMirror.fromTextArea(document.getElementById("code-css"), {
              lineNumbers: true,
              mode: "css",
              gutters: ["CodeMirror-lint-markers"],
              lint: true
            });
          </script>
          
            </article>
          
        • loadmode.html
          <!doctype html>
          
          <title>CodeMirror: Lazy Mode Loading Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/mode/loadmode.js"></script>
          <script src="../mode/meta.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Lazy Mode Loading</a>
            </ul>
          </div>
          
          <article>
          <h2>Lazy Mode Loading Demo</h2>
          <p style="color: gray">Current mode: <span id="modeinfo">text/plain</span></p>
          <form><textarea id="code" name="code">This is the editor.
          // It starts out in plain text mode,
          #  use the control below to load and apply a mode
            "you'll see the highlighting of" this text /*change*/.
          </textarea></form>
          <p>Filename, mime, or mode name: <input type=text value=foo.js id=mode> <button type=button onclick="change()">change mode</button></p>
          
              <script>
          CodeMirror.modeURL = "../mode/%N/%N.js";
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            lineNumbers: true
          });
          var modeInput = document.getElementById("mode");
          CodeMirror.on(modeInput, "keypress", function(e) {
            if (e.keyCode == 13) change();
          });
          function change() {
            var val = modeInput.value, m, mode, spec;
            if (m = /.+\.([^.]+)$/.exec(val)) {
              var info = CodeMirror.findModeByExtension(m[1]);
              if (info) {
                mode = info.mode;
                spec = info.mime;
              }
            } else if (/\//.test(val)) {
              var info = CodeMirror.findModeByMIME(val);
              if (info) {
                mode = info.mode;
                spec = val;
              }
            } else {
              mode = spec = val;
            }
            if (mode) {
              editor.setOption("mode", spec);
              CodeMirror.autoLoadMode(editor, mode);
              document.getElementById("modeinfo").textContent = spec;
            } else {
              alert("Could not find a mode corresponding to " + val);
            }
          }
          </script>
            </article>
          
        • marker.html
          <!doctype html>
          
          <title>CodeMirror: Breakpoint Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <style type="text/css">
                .breakpoints {width: .8em;}
                .breakpoint { color: #822; }
                .CodeMirror {border: 1px solid #aaa;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Breakpoint</a>
            </ul>
          </div>
          
          <article>
          <h2>Breakpoint Demo</h2>
          <form><textarea id="code" name="code">
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            lineNumbers: true,
            gutters: ["CodeMirror-linenumbers", "breakpoints"]
          });
          editor.on("gutterClick", function(cm, n) {
            var info = cm.lineInfo(n);
            cm.setGutterMarker(n, "breakpoints", info.gutterMarkers ? null : makeMarker());
          });
          
          function makeMarker() {
            var marker = document.createElement("div");
            marker.style.color = "#822";
            marker.innerHTML = "●";
            return marker;
          }
          </textarea></form>
          
          <p>Click the line-number gutter to add or remove 'breakpoints'.</p>
          
              <script>eval(document.getElementById("code").value);</script>
          
            </article>
          
        • markselection.html
          <!doctype html>
          
          <title>CodeMirror: Selection Marking Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../addon/selection/mark-selection.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                .CodeMirror-selected  { background-color: blue !important; }
                .CodeMirror-selectedtext { color: white; }
                .styled-background { background-color: #ff7; }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Selection Marking</a>
            </ul>
          </div>
          
          <article>
          <h2>Selection Marking Demo</h2>
          <form><textarea id="code" name="code">
          Select something from here. You'll see that the selection's foreground
          color changes to white! Since, by default, CodeMirror only puts an
          independent "marker" layer behind the text, you'll need something like
          this to change its colour.
          
          Also notice that turning this addon on (with the default style) allows
          you to safely give text a background color without screwing up the
          visibility of the selection.</textarea></form>
          
              <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            lineNumbers: true,
            styleSelectedText: true
          });
          editor.markText({line: 6, ch: 26}, {line: 6, ch: 42}, {className: "styled-background"});
          </script>
          
              <p>Simple addon to easily mark (and style) selected text. <a href="../doc/manual.html#addon_mark-selection">Docs</a>.</p>
          
            </article>
          
        • matchhighlighter.html
          <!doctype html>
          
          <title>CodeMirror: Match Highlighter Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../addon/search/match-highlighter.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                .CodeMirror-focused .cm-matchhighlight {
                  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==);
                  background-position: bottom;
                  background-repeat: repeat-x;
                }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Match Highlighter</a>
            </ul>
          </div>
          
          <article>
          <h2>Match Highlighter Demo</h2>
          <form><textarea id="code" name="code">Select this text: hardToSpotVar
          	And everywhere else in your code where hardToSpotVar appears will automatically illuminate.
          Give it a try!  No more hardToSpotVars.</textarea></form>
          
              <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            lineNumbers: true,
            highlightSelectionMatches: {showToken: /\w/}
          });
          </script>
          
              <p>Search and highlight occurences of the selected text.</p>
          
            </article>
          
        • matchtags.html
          <!doctype html>
          
          <title>CodeMirror: Tag Matcher Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/fold/xml-fold.js"></script>
          <script src="../addon/edit/matchtags.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Tag Matcher</a>
            </ul>
          </div>
          
          <article>
          <h2>Tag Matcher Demo</h2>
          
          
              <div id="editor"></div>
          
              <script>
          window.onload = function() {
            editor = CodeMirror(document.getElementById("editor"), {
              value: "<html>\n  " + document.documentElement.innerHTML + "\n</html>",
              mode: "text/html",
              matchTags: {bothTags: true},
              extraKeys: {"Ctrl-J": "toMatchingTag"}
            });
          };
              </script>
          
              <p>Put the cursor on or inside a pair of tags to highlight them.
              Press Ctrl-J to jump to the tag that matches the one under the
              cursor.</p>
            </article>
          
        • merge.html
          <!doctype html>
          
          <title>CodeMirror: merge view demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel=stylesheet href="../lib/codemirror.css">
          <link rel=stylesheet href="../addon/merge/merge.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../mode/css/css.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/htmlmixed/htmlmixed.js"></script>
          <script src="//cdnjs.cloudflare.com/ajax/libs/diff_match_patch/20121119/diff_match_patch.js"></script>
          <script src="../addon/merge/merge.js"></script>
          <style>
              .CodeMirror { line-height: 1.2; }
              @media screen and (min-width: 1300px) {
                article { max-width: 1000px; }
                #nav { border-right: 499px solid transparent; }
              }
              span.clicky {
                cursor: pointer;
                background: #d70;
                color: white;
                padding: 0 3px;
                border-radius: 3px;
              }
            </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">merge view</a>
            </ul>
          </div>
          
          <article>
          <h2>merge view demo</h2>
          
          
          <div id=view></div>
          
          <p>The <a href="../doc/manual.html#addon_merge"><code>merge</code></a>
          addon provides an interface for displaying and merging diffs,
          either <span class=clicky onclick="panes = 2; initUI()">two-way</span>
          or <span class=clicky onclick="panes = 3; initUI()">three-way</span>.
          The left (or center) pane is editable, and the differences with the
          other pane(s) are <span class=clicky
          onclick="toggleDifferences()">optionally</span> shown live as you edit
          it. In the two-way configuration, there are also options to pad changed
          sections to <span class=clicky onclick="connect = connect ? null :
          'align'; initUI()">align</span> them, and to <span class=clicky
          onclick="collapse = !collapse; initUI()">collapse</span> unchanged
          stretches of text.</p>
          
          <p>This addon depends on
          the <a href="https://code.google.com/p/google-diff-match-patch/">google-diff-match-patch</a>
          library to compute the diffs.</p>
          
          <script>
          var value, orig1, orig2, dv, panes = 2, highlight = true, connect = null, collapse = false;
          function initUI() {
            if (value == null) return;
            var target = document.getElementById("view");
            target.innerHTML = "";
            dv = CodeMirror.MergeView(target, {
              value: value,
              origLeft: panes == 3 ? orig1 : null,
              orig: orig2,
              lineNumbers: true,
              mode: "text/html",
              highlightDifferences: highlight,
              connect: connect,
              collapseIdentical: collapse
            });
          }
          
          function toggleDifferences() {
            dv.setShowDifferences(highlight = !highlight);
          }
          
          window.onload = function() {
            value = document.documentElement.innerHTML;
            orig1 = "<!doctype html>\n\n" + value.replace(/\.\.\//g, "codemirror/").replace("yellow", "orange");
            orig2 = value.replace(/\u003cscript/g, "\u003cscript type=text/javascript ")
              .replace("white", "purple;\n      font: comic sans;\n      text-decoration: underline;\n      height: 15em");
            initUI();
          };
          
          function mergeViewHeight(mergeView) {
            function editorHeight(editor) {
              if (!editor) return 0;
              return editor.getScrollInfo().height;
            }
            return Math.max(editorHeight(mergeView.leftOriginal()),
                            editorHeight(mergeView.editor()),
                            editorHeight(mergeView.rightOriginal()));
          }
          
          function resize(mergeView) {
            var height = mergeViewHeight(mergeView);
            for(;;) {
              if (mergeView.leftOriginal())
                mergeView.leftOriginal().setSize(null, height);
              mergeView.editor().setSize(null, height);
              if (mergeView.rightOriginal())
                mergeView.rightOriginal().setSize(null, height);
          
              var newHeight = mergeViewHeight(mergeView);
              if (newHeight >= height) break;
              else height = newHeight;
            }
            mergeView.wrap.style.height = height + "px";
          }
          </script>
          </article>
          
        • multiplex.html
          <!doctype html>
          
          <title>CodeMirror: Multiplexing Parser Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/mode/multiplex.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid black;}
                .cm-delimit {color: #fa4;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Multiplexing Parser</a>
            </ul>
          </div>
          
          <article>
          <h2>Multiplexing Parser Demo</h2>
          <form><textarea id="code" name="code">
          <html>
            <body style="<<magic>>">
              <h1><< this is not <html >></h1>
              <<
                  multiline
                  not html
                  at all : &amp;amp; <link/>
              >>
              <p>this is html again</p>
            </body>
          </html>
          </textarea></form>
          
              <script>
          CodeMirror.defineMode("demo", function(config) {
            return CodeMirror.multiplexingMode(
              CodeMirror.getMode(config, "text/html"),
              {open: "<<", close: ">>",
               mode: CodeMirror.getMode(config, "text/plain"),
               delimStyle: "delimit"}
              // .. more multiplexed styles can follow here
            );
          });
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            mode: "demo",
            lineNumbers: true,
            lineWrapping: true
          });
          </script>
          
              <p>Demonstration of a multiplexing mode, which, at certain
              boundary strings, switches to one or more inner modes. The out
              (HTML) mode does not get fed the content of the <code>&lt;&lt;
              >></code> blocks. See
              the <a href="../doc/manual.html#addon_multiplex">manual</a> and
              the <a href="../addon/mode/multiplex.js">source</a> for more
              information.</p>
          
              <p>
                <strong>Parsing/Highlighting Tests:</strong>
                <a href="../test/index.html#multiplexing_*">normal</a>,
                <a href="../test/index.html#verbose,multiplexing_*">verbose</a>.
              </p>
          
            </article>
          
        • mustache.html
          <!doctype html>
          
          <title>CodeMirror: Overlay Parser Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/mode/overlay.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid black;}
                .cm-mustache {color: #0ca;}
          </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Overlay Parser</a>
            </ul>
          </div>
          
          <article>
          <h2>Overlay Parser Demo</h2>
          <form><textarea id="code" name="code">
          <html>
            <body>
              <h1>{{title}}</h1>
              <p>These are links to {{things}}:</p>
              <ul>{{#links}}
                <li><a href="{{url}}">{{text}}</a></li>
              {{/links}}</ul>
            </body>
          </html>
          </textarea></form>
          
              <script>
          CodeMirror.defineMode("mustache", function(config, parserConfig) {
            var mustacheOverlay = {
              token: function(stream, state) {
                var ch;
                if (stream.match("{{")) {
                  while ((ch = stream.next()) != null)
                    if (ch == "}" && stream.next() == "}") {
                      stream.eat("}");
                      return "mustache";
                    }
                }
                while (stream.next() != null && !stream.match("{{", false)) {}
                return null;
              }
            };
            return CodeMirror.overlayMode(CodeMirror.getMode(config, parserConfig.backdrop || "text/html"), mustacheOverlay);
          });
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {mode: "mustache"});
          </script>
          
              <p>Demonstration of a mode that parses HTML, highlighting
              the <a href="http://mustache.github.com/">Mustache</a> templating
              directives inside of it by using the code
              in <a href="../addon/mode/overlay.js"><code>overlay.js</code></a>. View
              source to see the 15 lines of code needed to accomplish this.</p>
          
            </article>
          
        • panel.html
          <!doctype html>
          
          <title>CodeMirror: Panel Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../mode/htmlmixed/htmlmixed.js"></script>
          <script src="../addon/display/panel.js"></script>
          <style type="text/css">
            .border {
              border: 1px solid #f7f7f7;
            }
            .add-panel {
              background: orange;
              padding: 3px 6px;
              color: white !important; 
              border-radius: 3px;
            }
            .add-panel, .remove-panel {
              cursor: pointer;
            }
            .remove-panel {
              float: right;
            }
            .panel {
              background: #f7f7f7;
              padding: 3px 7px;
              font-size: 0.85em;
            }
            .panel.top, .panel.after-top {
              border-bottom: 1px solid #ddd;
            }
            .panel.bottom, .panel.before-bottom {
              border-top: 1px solid #ddd;
            }
          </style>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Panel</a>
            </ul>
          </div>
          
          <article>
          
          <h2>Panel Demo</h2>
          
          <div class="border">
              <textarea id="code" name="code"></textarea>
          </div>
          
          <p>
            The <a href="../doc/manual.html#addon_panel"><code>panel</code></a>
            addon allows you to display panels above or below an editor.
            <br>
            Click the links below to add panels at the given position:
          </p>
          
          <div id="demo">
          <p>
            <a class="add-panel" onclick="addPanel('top')">top</a>
            <a class="add-panel" onclick="addPanel('after-top')">after-top</a>
            <a class="add-panel" onclick="addPanel('before-bottom')">before-bottom</a>
            <a class="add-panel" onclick="addPanel('bottom')">bottom</a>
          </p>
          <p>
            You can also replace an existing panel:
          </p>
          <form onsubmit="return replacePanel(this);" name="replace_panel">
            <input type="submit" value="Replace panel n°" />
            <input type="number" name="panel_id" min="1" value="1" />
          </form>
          
          <script>
          var textarea = document.getElementById("code");
          var demo = document.getElementById("demo");
          var numPanels = 0;
          var panels = {};
          var editor;
          
          textarea.value = demo.innerHTML.trim();
          editor = CodeMirror.fromTextArea(textarea, {
            lineNumbers: true,
            mode: "htmlmixed"
          });
          
          function makePanel(where) {
            var node = document.createElement("div");
            var id = ++numPanels;
            var widget, close, label;
          
            node.id = "panel-" + id;
            node.className = "panel " + where;
            close = node.appendChild(document.createElement("a"));
            close.setAttribute("title", "Remove me!");
            close.setAttribute("class", "remove-panel");
            close.textContent = "✖";
            CodeMirror.on(close, "click", function() {
              panels[node.id].clear();
            });
            label = node.appendChild(document.createElement("span"));
            label.textContent = "I'm panel n°" + id;
            return node;
          }
          function addPanel(where) {
            var node = makePanel(where);
            panels[node.id] = editor.addPanel(node, {position: where});
          }
          
          addPanel("top");
          addPanel("bottom");
          
          function replacePanel(form) {
            var id = form.elements.panel_id.value;
            var panel = panels["panel-" + id];
            var node = makePanel("");
          
            panels[node.id] = editor.addPanel(node, {replace: panel, position: "after-top"});
            return false;
          }
          </script>
          
          </div>
          
          </article>
          
        • placeholder.html
          <!doctype html>
          
          <title>CodeMirror: Placeholder demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/display/placeholder.js"></script>
          <style type="text/css">
                .CodeMirror { border: 1px solid silver; }
                .CodeMirror-empty { outline: 1px solid #c22; }
                .CodeMirror-empty.CodeMirror-focused { outline: none; }
                .CodeMirror pre.CodeMirror-placeholder { color: #999; }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Placeholder</a>
            </ul>
          </div>
          
          <article>
          <h2>Placeholder demo</h2>
          <form><textarea id="code" name="code" placeholder="Code goes here..."></textarea></form>
          
              <p>The <a href="../doc/manual.html#addon_placeholder">placeholder</a>
              plug-in adds an option <code>placeholder</code> that can be set to
              make text appear in the editor when it is empty and not focused.
              If the source textarea has a <code>placeholder</code> attribute,
              it will automatically be inherited.</p>
          
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true
                });
              </script>
          
            </article>
          
        • preview.html
          <!doctype html>
          
          <title>CodeMirror: HTML5 preview</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel=stylesheet href=../lib/codemirror.css>
          <script src=../lib/codemirror.js></script>
          <script src=../mode/xml/xml.js></script>
          <script src=../mode/javascript/javascript.js></script>
          <script src=../mode/css/css.js></script>
          <script src=../mode/htmlmixed/htmlmixed.js></script>
          <style type=text/css>
                .CodeMirror {
                  float: left;
                  width: 50%;
                  border: 1px solid black;
                }
                iframe {
                  width: 49%;
                  float: left;
                  height: 300px;
                  border: 1px solid black;
                  border-left: 0px;
                }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">HTML5 preview</a>
            </ul>
          </div>
          
          <article>
          <h2>HTML5 preview</h2>
          
              <textarea id=code name=code>
          <!doctype html>
          <html>
            <head>
              <meta charset=utf-8>
              <title>HTML5 canvas demo</title>
              <style>p {font-family: monospace;}</style>
            </head>
            <body>
              <p>Canvas pane goes here:</p>
              <canvas id=pane width=300 height=200></canvas>
              <script>
                var canvas = document.getElementById('pane');
                var context = canvas.getContext('2d');
          
                context.fillStyle = 'rgb(250,0,0)';
                context.fillRect(10, 10, 55, 50);
          
                context.fillStyle = 'rgba(0, 0, 250, 0.5)';
                context.fillRect(30, 30, 55, 50);
              </script>
            </body>
          </html></textarea>
              <iframe id=preview></iframe>
              <script>
                var delay;
                // Initialize CodeMirror editor with a nice html5 canvas demo.
                var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
                  mode: 'text/html'
                });
                editor.on("change", function() {
                  clearTimeout(delay);
                  delay = setTimeout(updatePreview, 300);
                });
                
                function updatePreview() {
                  var previewFrame = document.getElementById('preview');
                  var preview =  previewFrame.contentDocument ||  previewFrame.contentWindow.document;
                  preview.open();
                  preview.write(editor.getValue());
                  preview.close();
                }
                setTimeout(updatePreview, 300);
              </script>
            </article>
          
        • requirejs.html
          <!doctype html>
          
          <head>
            <title>CodeMirror: HTML completion demo</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../doc/docs.css">
          
            <link rel="stylesheet" href="../lib/codemirror.css">
            <link rel="stylesheet" href="../addon/hint/show-hint.css">
            <script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.14/require.min.js"></script>
            <style type="text/css">
              .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
            </style>
          </head>
          
          <body>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
              <ul>
                <li><a href="../index.html">Home</a>
                <li><a href="../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a class=active href="#">HTML completion</a>
              </ul>
            </div>
          
            <article>
              <h2>RequireJS module loading demo</h2>
          
              <p>This demo does the same thing as
              the <a href="html5complete.html">HTML5 completion demo</a>, but
              loads its dependencies
              with <a href="http://requirejs.org/">Require.js</a>, rather than
              explicitly. Press <strong>ctrl-space</strong> to activate
              completion.</p>
          
              <div id="code"></div>
          
              <script type="text/javascript">
                require(["../lib/codemirror", "../mode/htmlmixed/htmlmixed",
                         "../addon/hint/show-hint", "../addon/hint/html-hint"], function(CodeMirror) {
                  editor = CodeMirror(document.getElementById("code"), {
                    mode: "text/html",
                    extraKeys: {"Ctrl-Space": "autocomplete"},
                    value: document.documentElement.innerHTML
                  });
                });
              </script>
            </article>
          </body>
          
        • resize.html
          <!doctype html>
          
          <title>CodeMirror: Autoresize Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/css/css.js"></script>
          <style type="text/css">
                .CodeMirror {
                  border: 1px solid #eee;
                  height: auto;
                }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Autoresize</a>
            </ul>
          </div>
          
          <article>
          <h2>Autoresize Demo</h2>
          <form><textarea id="code" name="code">
          .CodeMirror {
            border: 1px solid #eee;
            height: auto;
          }
          </textarea></form>
          
          <p>By setting an editor's <code>height</code> style
          to <code>auto</code> and giving
          the <a href="../doc/manual.html#option_viewportMargin"><code>viewportMargin</code></a>
          a value of <code>Infinity</code>, CodeMirror can be made to
          automatically resize to fit its content.</p>
          
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  viewportMargin: Infinity
                });
              </script>
          
            </article>
          
        • rulers.html
          <!doctype html>
          
          <title>CodeMirror: Ruler Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/display/rulers.js"></script>
          <style type="text/css">
            .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
          </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Ruler demo</a>
            </ul>
          </div>
          
          <article>
          <h2>Ruler Demo</h2>
          
          <script type="text/javascript">
            var nums = "0123456789", space = "          ";
            var colors = ["#fcc", "#f5f577", "#cfc", "#aff", "#ccf", "#fcf"];
            var rulers = [], value = "";
            for (var i = 1; i <= 6; i++) {
              rulers.push({color: colors[i], column: i * 10, lineStyle: "dashed"});
              for (var j = 1; j < i; j++) value += space;
              value += nums + "\n";
            }
            var editor = CodeMirror(document.body.lastChild, {
              rulers: rulers,
              value: value + value + value,
              lineNumbers: true
          });
          </script>
          
          <p>Demonstration of
          the <a href="../doc/manual.html#addon_rulers">rulers</a> addon, which
          displays vertical lines at given column offsets.</p>
          
          </article>
          
        • runmode.html
          <!doctype html>
          
          <title>CodeMirror: Mode Runner Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/runmode/runmode.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Mode Runner</a>
            </ul>
          </div>
          
          <article>
          <h2>Mode Runner Demo</h2>
          
          
              <textarea id="code" style="width: 90%; height: 7em; border: 1px solid black; padding: .2em .4em;">
          <foobar>
            <blah>Enter your xml here and press the button below to display
              it as highlighted by the CodeMirror XML mode</blah>
            <tag2 foo="2" bar="&amp;quot;bar&amp;quot;"/>
          </foobar></textarea><br>
              <button onclick="doHighlight();">Highlight!</button>
              <pre id="output" class="cm-s-default"></pre>
          
              <script>
          function doHighlight() {
            CodeMirror.runMode(document.getElementById("code").value, "application/xml",
                               document.getElementById("output"));
          }
          </script>
          
              <p>Running a CodeMirror mode outside of the editor.
              The <code>CodeMirror.runMode</code> function, defined
              in <code><a href="../addon/runmode/runmode.js">lib/runmode.js</a></code> takes the following arguments:</p>
          
              <dl>
                <dt><code>text (string)</code></dt>
                <dd>The document to run through the highlighter.</dd>
                <dt><code>mode (<a href="../doc/manual.html#option_mode">mode spec</a>)</code></dt>
                <dd>The mode to use (must be loaded as normal).</dd>
                <dt><code>output (function or DOM node)</code></dt>
                <dd>If this is a function, it will be called for each token with
                two arguments, the token's text and the token's style class (may
                be <code>null</code> for unstyled tokens). If it is a DOM node,
                the tokens will be converted to <code>span</code> elements as in
                an editor, and inserted into the node
                (through <code>innerHTML</code>).</dd>
              </dl>
          
            </article>
          
        • search.html
          <!doctype html>
          
          <title>CodeMirror: Search/Replace Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/dialog/dialog.css">
          <link rel="stylesheet" href="../addon/search/matchesonscrollbar.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../addon/dialog/dialog.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../addon/search/search.js"></script>
          <script src="../addon/scroll/annotatescrollbar.js"></script>
          <script src="../addon/search/matchesonscrollbar.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                dt {font-family: monospace; color: #666;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Search/Replace</a>
            </ul>
          </div>
          
          <article>
          <h2>Search/Replace Demo</h2>
          <form><textarea id="code" name="code">
          <dl>
            <dt id="option_indentWithTabs"><code><strong>indentWithTabs</strong>: boolean</code></dt>
            <dd>Whether, when indenting, the first N*<code>tabSize</code>
            spaces should be replaced by N tabs. Default is false.</dd>
          
            <dt id="option_electricChars"><code><strong>electricChars</strong>: boolean</code></dt>
            <dd>Configures whether the editor should re-indent the current
            line when a character is typed that might change its proper
            indentation (only works if the mode supports indentation).
            Default is true.</dd>
          
            <dt id="option_specialChars"><code><strong>specialChars</strong>: RegExp</code></dt>
            <dd>A regular expression used to determine which characters
            should be replaced by a
            special <a href="#option_specialCharPlaceholder">placeholder</a>.
            Mostly useful for non-printing special characters. The default
            is <code>/[\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/</code>.</dd>
            <dt id="option_specialCharPlaceholder"><code><strong>specialCharPlaceholder</strong>: function(char) → Element</code></dt>
            <dd>A function that, given a special character identified by
            the <a href="#option_specialChars"><code>specialChars</code></a>
            option, produces a DOM node that is used to represent the
            character. By default, a red dot (<span style="color: red">•</span>)
            is shown, with a title tooltip to indicate the character code.</dd>
          
            <dt id="option_rtlMoveVisually"><code><strong>rtlMoveVisually</strong>: boolean</code></dt>
            <dd>Determines whether horizontal cursor movement through
            right-to-left (Arabic, Hebrew) text is visual (pressing the left
            arrow moves the cursor left) or logical (pressing the left arrow
            moves to the next lower index in the string, which is visually
            right in right-to-left text). The default is <code>false</code>
            on Windows, and <code>true</code> on other platforms.</dd>
          </dl>
          </textarea></form>
          
              <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            mode: "text/html",
            lineNumbers: true
          });
          </script>
          
              <p>Demonstration of primitive search/replace functionality. The
              keybindings (which can be overridden by custom keymaps) are:</p>
              <dl>
                <dt>Ctrl-F / Cmd-F</dt><dd>Start searching</dd>
                <dt>Ctrl-G / Cmd-G</dt><dd>Find next</dd>
                <dt>Shift-Ctrl-G / Shift-Cmd-G</dt><dd>Find previous</dd>
                <dt>Shift-Ctrl-F / Cmd-Option-F</dt><dd>Replace</dd>
                <dt>Shift-Ctrl-R / Shift-Cmd-Option-F</dt><dd>Replace all</dd>
              </dl>
              <p>Searching is enabled by
              including <a href="../addon/search/search.js">addon/search/search.js</a>
              and <a href="../addon/search/searchcursor.js">addon/search/searchcursor.js</a>.
              For good-looking input dialogs, you also want to include
              <a href="../addon/dialog/dialog.js">addon/dialog/dialog.js</a>
              and <a href="../addon/dialog/dialog.css">addon/dialog/dialog.css</a>.</p>
            </article>
          
        • simplemode.html
          <!doctype html>
          
          <title>CodeMirror: Simple Mode Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/mode/simple.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
            .CodeMirror {border: 1px solid silver; margin-bottom: 1em; }
            dt { text-indent: -2em; padding-left: 2em; margin-top: 1em; }
            dd { margin-left: 1.5em; margin-bottom: 1em; }
            dt {margin-top: 1em;}
          </style>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Simple Mode</a>
            </ul>
          </div>
          
          <article>
          <h2>Simple Mode Demo</h2>
          
          <p>The <a href="../addon/mode/simple.js"><code>mode/simple</code></a>
          addon allows CodeMirror modes to be specified using a relatively simple
          declarative format. This format is not as powerful as writing code
          directly against the <a href="../doc/manual.html#modeapi">mode
          interface</a>, but is a lot easier to get started with, and
          sufficiently expressive for many simple language modes.</p>
          
          <p>This interface is still in flux. It is unlikely to be scrapped or
          overhauled completely, so do start writing code against it, but
          details might change as it stabilizes, and you might have to tweak
          your code when upgrading.</p>
          
          <p>Simple modes (loosely based on
          the <a href="https://github.com/mozilla/skywriter/wiki/Common-JavaScript-Syntax-Highlighting-Specification">Common
          JavaScript Syntax Highlighting Specification</a>, which never took
          off), are state machines, where each state has a number of rules that
          match tokens. A rule describes a type of token that may occur in the
          current state, and possibly a transition to another state caused by
          that token.</p>
          
          <p>The <code>CodeMirror.defineSimpleMode(name, states)</code> method
          takes a mode name and an object that describes the mode's states. The
          editor below shows an example of such a mode (and is itself
          highlighted by the mode shown in it).</p>
          
          <div id="code"></div>
          
          <p>Each state is an array of rules. A rule may have the following properties:</p>
          
          <dl>
            <dt><code><strong>regex</strong>: string | RegExp</code></dt>
            <dd>The regular expression that matches the token. May be a string
            or a regex object. When a regex, the <code>ignoreCase</code> flag
            will be taken into account when matching the token. This regex
            should only capture groups when the <code>token</code> property is
            an array.</dd>
            <dt><code><strong>token</strong></code>: string | null</dt>
            <dd>An optional token style. Multiple styles can be specified by
            separating them with dots or spaces. When the <code>regex</code> for
            this rule captures groups, it must capture <em>all</em> of the
            string (since JS provides no way to find out where a group matched),
            and this property must hold an array of token styles that has one
            style for each matched group.</dd>
            <dt><code><strong>sol</strong></code>: boolean</dt>
            <dd>When true, this token will only match at the start of the line.
            (The <code>^</code> regexp marker doesn't work as you'd expect in
            this context because of limitations in JavaScript's RegExp
            API.)</dd>
            <dt><code><strong>next</strong>: string</code></dt>
            <dd>When a <code>next</code> property is present, the mode will
            transfer to the state named by the property when the token is
            encountered.</dd>
            <dt><code><strong>push</strong>: string</code></dt>
            <dd>Like <code>next</code>, but instead replacing the current state
            by the new state, the current state is kept on a stack, and can be
            returned to with the <code>pop</code> directive.</dd>
            <dt><code><strong>pop</strong>: bool</code></dt>
            <dd>When true, and there is another state on the state stack, will
            cause the mode to pop that state off the stack and transition to
            it.</dd>
            <dt><code><strong>mode</strong>: {spec, end, persistent}</code></dt>
            <dd>Can be used to embed another mode inside a mode. When present,
            must hold an object with a <code>spec</code> property that describes
            the embedded mode, and an optional <code>end</code> end property
            that specifies the regexp that will end the extent of the mode. When
            a <code>persistent</code> property is set (and true), the nested
            mode's state will be preserved between occurrences of the mode.</dd>
            <dt><code><strong>indent</strong>: bool</code></dt>
            <dd>When true, this token changes the indentation to be one unit
            more than the current line's indentation.</dd>
            <dt><code><strong>dedent</strong>: bool</code></dt>
            <dd>When true, this token will pop one scope off the indentation
            stack.</dd>
            <dt><code><strong>dedentIfLineStart</strong>: bool</code></dt>
            <dd>If a token has its <code>dedent</code> property set, it will, by
            default, cause lines where it appears at the start to be dedented.
            Set this property to false to prevent that behavior.</dd>
          </dl>
          
          <p>The <code>meta</code> property of the states object is special, and
          will not be interpreted as a state. Instead, properties set on it will
          be set on the mode, which is useful for properties
          like <a href="../doc/manual.html#addon_comment"><code>lineComment</code></a>,
          which sets the comment style for a mode. The simple mode addon also
          recognizes a few such properties:</p>
          
          <dl>
            <dt><code><strong>dontIndentStates</strong>: array&lt;string&gt;</code></dt>
            <dd>An array of states in which the mode's auto-indentation should
            not take effect. Usually used for multi-line comment and string
            states.</dd>
          </dl>
          
          <script id="modecode">/* Example definition of a simple mode that understands a subset of
           * JavaScript:
           */
          
          CodeMirror.defineSimpleMode("simplemode", {
            // The start state contains the rules that are intially used
            start: [
              // The regex matches the token, the token property contains the type
              {regex: /"(?:[^\\]|\\.)*?"/, token: "string"},
              // You can match multiple tokens at once. Note that the captured
              // groups must span the whole string in this case
              {regex: /(function)(\s+)([a-z$][\w$]*)/,
               token: ["keyword", null, "variable-2"]},
              // Rules are matched in the order in which they appear, so there is
              // no ambiguity between this one and the one above
              {regex: /(?:function|var|return|if|for|while|else|do|this)\b/,
               token: "keyword"},
              {regex: /true|false|null|undefined/, token: "atom"},
              {regex: /0x[a-f\d]+|[-+]?(?:\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/i,
               token: "number"},
              {regex: /\/\/.*/, token: "comment"},
              {regex: /\/(?:[^\\]|\\.)*?\//, token: "variable-3"},
              // A next property will cause the mode to move to a different state
              {regex: /\/\*/, token: "comment", next: "comment"},
              {regex: /[-+\/*=<>!]+/, token: "operator"},
              // indent and dedent properties guide autoindentation
              {regex: /[\{\[\(]/, indent: true},
              {regex: /[\}\]\)]/, dedent: true},
              {regex: /[a-z$][\w$]*/, token: "variable"},
              // You can embed other modes with the mode property. This rule
              // causes all code between << and >> to be highlighted with the XML
              // mode.
              {regex: /<</, token: "meta", mode: {spec: "xml", end: />>/}}
            ],
            // The multi-line comment state.
            comment: [
              {regex: /.*?\*\//, token: "comment", next: "start"},
              {regex: /.*/, token: "comment"}
            ],
            // The meta property contains global information about the mode. It
            // can contain properties like lineComment, which are supported by
            // all modes, and also directives like dontIndentStates, which are
            // specific to simple modes.
            meta: {
              dontIndentStates: ["comment"],
              lineComment: "//"
            }
          });
          </script>
          
          <script>
          var sc = document.getElementById("modecode");
          var code = document.getElementById("code");
          var editor = CodeMirror(code, {
            value: (sc.textContent || sc.innerText || sc.innerHTML),
            mode: "simplemode"
          });
          </script>
          
          </article>
          
        • simplescrollbars.html
          <!doctype html>
          
          <title>CodeMirror: Simple Scrollbar Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/scroll/simplescrollbars.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/markdown/markdown.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../addon/scroll/simplescrollbars.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Simple Scrollbar</a>
            </ul>
          </div>
          
          <article>
          <h2>Simple Scrollbar Demo</h2>
          <form><textarea id="code" name="code"># Custom Scrollbars
          
          This is a piece of text that creates scrollbars
          
          Lorem ipsum dolor sit amet, turpis nec facilisis neque vestibulum adipiscing, magna nunc est luctus orci a,
          aliquam duis ad volutpat nostra. Vestibulum ultricies suspendisse commodo volutpat pede sed. Bibendum odio
          dignissim, ad vitae mollis ac sed nibh quis, suspendisse diam, risus quas blandit phasellus luctus nec,
          integer nunc vitae posuere scelerisque. Lobortis quam porta conubia nulla. Et nisl ac, imperdiet vitae ac.
          Parturient sit. Et vestibulum euismod, rutrum nunc libero mauris purus convallis. Cum id adipiscing et eget
          pretium rutrum, ultrices sapien magnis fringilla sit lorem, eu vitae scelerisque ipsum aliquet, magna sed
          fusce vel.
          
          Lectus ultricies libero dolor convallis, sed etiam vel hendrerit egestas viverra, at urna mauris, eget
          vulputate dolor voluptatem, nulla eget sollicitudin. Sed tincidunt, elit sociis. Mattis mi tortor dui id
          sodales mi, maecenas nam fringilla risus turpis mauris praesent, imperdiet maecenas ultrices nonummy tellus
          quis est. Scelerisque nec pharetra quis varius fringilla. Varius vestibulum non dictum pharetra, tincidunt in
          vestibulum iaculis molestie, id condimentum blandit elit urna magna pulvinar, quam suspendisse pellentesque
          donec. Vel amet ad ac. Nec aut viverra, morbi mi neque massa, turpis enim proin. Tellus eu, fermentum velit
          est convallis aliquam velit, rutrum in diam lacus, praesent tempor pellentesque dictum semper augue. Felis
          explicabo massa amet lectus phasellus dolor. Ut lorem quis arcu neque felis ultricies, senectus vitae
          curabitur sed pellentesque et, id sed risus in sed ac accumsan, blandit arcu quam duis nunc.
          
          Sed leo sollicitudin odio vitae, purus sit egestas, justo eros inceptos auctor fermentum lectus. Ligula luctus
          turpis, quod massa vitae elementum orci, nullam fringilla elit tortor. Justo ante tempor amet quam posuere
          volutpat. Facilisis pede erat ut hac ultrices ipsum, wisi duis sit metus. Dolor vitae est sed sed vitae. Sed
          eu ligula, morbi vestibulum nunc nibh velit ut taciti, ligula elit semper sagittis in, auctor arcu vel eget.
          Mauris at vitae nec suspendisse et, aenean proin blandit suscipit. Morbi quam, dolor ultricies. Viverra
          tempus. Suspendisse sit dapibus, ac fuga aenean, magna nisl nonummy augue posuere, dictum ut fuga velit
          parturient augue interdum, mattis sit tellus.
          
          Vehicula commodo tempus curabitur eros, lacinia erat vulputate lorem vel fermentum donec, lectus sed conubia
          id pellentesque. Vel senectus donec pede aliquet dolor sit, nec vivamus justo placerat interdum maecenas,
          sodales euismod. Quis netus sapien amet, vestibulum quam nec amet lacinia, quis aliquet, tempor vivamus tellus
          enim, suscipit quis eleifend. Amet class phasellus orci pretium, risus in nulla. Neque sit ullamcorper,
          ultricies platea id nec suspendisse ac. Et elementum. Dictum nam, ut dui fermentum egestas facilisis elit
          augue, adipiscing donec ipsum erat nam pellentesque convallis, vestibulum vestibulum risus id nulla ut mauris,
          curabitur aute aptent. Ultrices orci wisi dui ipsum praesent, pharetra felis eu quis. Est fringilla etiam,
          maxime sem dapibus et eget, mi enim dignissim nec pretium, augue vehicula, volutpat proin. Et occaecati
          lobortis viverra, cum in sed, vivamus tellus. Libero at malesuada est vivamus leo tortor.
          </textarea></form>
          
          <p>The <a href="../doc/manual.html#addon_simplescrollbars"><code>simplescrollbars</code></a> addon defines two
          styles of non-native scrollbars: <a href="javascript:editor.setOption('scrollbarStyle', 'simple')"><code>"simple"</code></a> and <a href="javascript:editor.setOption('scrollbarStyle', 'overlay')"><code>"overlay"</code></a> (click to try), which can be passed to
          the <a href="../doc/manual.html#option_scrollbarStyle"><code>scrollbarStyle</code></a> option. These implement
          the scrollbar using DOM elements, allowing more control over
          its <a href="../addon/scroll/simplescrollbars.css">appearance</a>.</p>
          
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                lineNumbers: true,
                scrollbarStyle: "simple"
              });
            </script>
          </article>
          
        • spanaffectswrapping_shim.html
          <!doctype html>
          
          <title>CodeMirror: Automatically derive odd wrapping behavior for your browser</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Automatically derive odd wrapping behavior for your browser</a>
            </ul>
          </div>
          
          <article>
          <h2>Automatically derive odd wrapping behavior for your browser</h2>
          
          
              <p>This is a hack to automatically derive
              a <code>spanAffectsWrapping</code> regexp for a browser. See the
              comments above that variable
              in <a href="../lib/codemirror.js"><code>lib/codemirror.js</code></a>
              for some more details.</p>
          
              <div style="white-space: pre-wrap; width: 50px;" id="area"></div>
              <pre id="output"></pre>
          
              <script id="script">
                var a = document.getElementById("area"), bad = Object.create(null);
                var chars = "a~`!@#$%^&*()-_=+}{[]\\|'\"/?.>,<:;", l = chars.length;
                for (var x = 0; x < l; ++x) for (var y = 0; y < l; ++y) {
                  var s1 = "foooo" + chars.charAt(x), s2 = chars.charAt(y) + "br";
                  a.appendChild(document.createTextNode(s1 + s2));
                  var h1 = a.offsetHeight;
                  a.innerHTML = "";
                  a.appendChild(document.createElement("span")).appendChild(document.createTextNode(s1));
                  a.appendChild(document.createElement("span")).appendChild(document.createTextNode(s2));
                  if (a.offsetHeight != h1)
                    bad[chars.charAt(x)] = (bad[chars.charAt(x)] || "") + chars.charAt(y);
                  a.innerHTML = "";
                }
          
                var re = "";
                function toREElt(str) {
                  if (str.length > 1) {
                    var invert = false;
                    if (str.length > chars.length * .6) {
                      invert = true;
                      var newStr = "";
                      for (var i = 0; i < l; ++i) if (str.indexOf(chars.charAt(i)) == -1) newStr += chars.charAt(i);
                      str = newStr;
                    }
                    str = str.replace(/[\-\.\]\"\'\\\/\^a]/g, function(orig) { return orig == "a" ? "\\w" : "\\" + orig; });
                    return "[" + (invert ? "^" : "") + str + "]";
                  } else if (str == "a") {
                    return "\\w";
                  } else if (/[?$*()+{}[\]\.|/\'\"]/.test(str)) {
                    return "\\" + str;
                  } else {
                    return str;
                  }
                }
          
                var newRE = "";
                for (;;) {
                  var left = null;
                  for (var left in bad) break;
                  if (left == null) break;
                  var right = bad[left];
                  delete bad[left];
                  for (var other in bad) if (bad[other] == right) {
                    left += other;
                    delete bad[other];
                  }
                  newRE += (newRE ? "|" : "") + toREElt(left) + toREElt(right);
                }
          
                document.getElementById("output").appendChild(document.createTextNode("Your regexp is: " + (newRE || "^$")));
              </script>
            </article>
          
        • sublime.html
          <!doctype html>
          
          <title>CodeMirror: Sublime Text bindings demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/fold/foldgutter.css">
          <link rel="stylesheet" href="../addon/dialog/dialog.css">
          <link rel="stylesheet" href="../theme/monokai.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../addon/search/search.js"></script>
          <script src="../addon/dialog/dialog.js"></script>
          <script src="../addon/edit/matchbrackets.js"></script>
          <script src="../addon/edit/closebrackets.js"></script>
          <script src="../addon/comment/comment.js"></script>
          <script src="../addon/wrap/hardwrap.js"></script>
          <script src="../addon/fold/foldcode.js"></script>
          <script src="../addon/fold/brace-fold.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../keymap/sublime.js"></script>
          <style type="text/css">
            .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee; line-height: 1.3; height: 500px}
            .CodeMirror-linenumbers { padding: 0 8px; }
          </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Sublime bindings</a>
            </ul>
          </div>
          
          <article>
          <h2>Sublime Text bindings demo</h2>
          
          <p>The <code>sublime</code> keymap defines many Sublime Text-specific
          bindings for CodeMirror. See the code below for an overview.</p>
          
          <p>Enable the keymap by
          loading <a href="../keymap/sublime.js"><code>keymap/sublime.js</code></a>
          and setting
          the <a href="../doc/manual.html#option_keyMap"><code>keyMap</code></a>
          option to <code>"sublime"</code>.</p>
          
          <p>(A lot of the search functionality is still missing.)
          
          <script>
            var value = "// The bindings defined specifically in the Sublime Text mode\nvar bindings = {\n";
            var map = CodeMirror.keyMap.sublime;
            for (var key in map) {
              var val = map[key];
              if (key != "fallthrough" && val != "..." && (!/find/.test(val) || /findUnder/.test(val)))
                value += "  \"" + key + "\": \"" + val + "\",\n";
            }
            value += "}\n\n// The implementation of joinLines\n";
            value += CodeMirror.commands.joinLines.toString().replace(/^function\s*\(/, "function joinLines(").replace(/\n  /g, "\n") + "\n";
            var editor = CodeMirror(document.body.getElementsByTagName("article")[0], {
              value: value,
              lineNumbers: true,
              mode: "javascript",
              keyMap: "sublime",
              autoCloseBrackets: true,
              matchBrackets: true,
              showCursorWhenSelecting: true,
              theme: "monokai"
            });
          </script>
          
          </article>
          
        • tern.html
          <!doctype html>
          
          <title>CodeMirror: Tern Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/dialog/dialog.css">
          <link rel="stylesheet" href="../addon/hint/show-hint.css">
          <link rel="stylesheet" href="../addon/tern/tern.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../addon/dialog/dialog.js"></script>
          <script src="../addon/hint/show-hint.js"></script>
          <script src="../addon/tern/tern.js"></script>
          <script src="http://ternjs.net/node_modules/acorn/dist/acorn.js"></script>
          <script src="http://ternjs.net/node_modules/acorn/dist/acorn_loose.js"></script>
          <script src="http://ternjs.net/node_modules/acorn/dist/walk.js"></script>
          <script src="http://ternjs.net/doc/demo/polyfill.js"></script>
          <script src="http://ternjs.net/lib/signal.js"></script>
          <script src="http://ternjs.net/lib/tern.js"></script>
          <script src="http://ternjs.net/lib/def.js"></script>
          <script src="http://ternjs.net/lib/comment.js"></script>
          <script src="http://ternjs.net/lib/infer.js"></script>
          <script src="http://ternjs.net/plugin/doc_comment.js"></script>
          <style>
                .CodeMirror {border: 1px solid #ddd;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Tern</a>
            </ul>
          </div>
          
          <article>
          <h2>Tern Demo</h2>
          <form><textarea id="code" name="code">// Use ctrl-space to complete something
          // Put the cursor in or after an expression, press ctrl-o to
          // find its type
          
          var foo = ["array", "of", "strings"];
          var bar = foo.slice(0, 2).join("").split("a")[0];
          
          // Works for locally defined types too.
          
          function CTor() { this.size = 10; }
          CTor.prototype.hallo = "hallo";
          
          var baz = new CTor;
          baz.
          
          // You can press ctrl-q when the cursor is on a variable name to
          // rename it. Try it with CTor...
          
          // When the cursor is in an argument list, the arguments are
          // shown below the editor.
          
          [1].reduce(  );
          
          // And a little more advanced code...
          
          (function(exports) {
            exports.randomElt = function(arr) {
              return arr[Math.floor(arr.length * Math.random())];
            };
            exports.strList = "foo".split("");
            exports.intList = exports.strList.map(function(s) { return s.charCodeAt(0); });
          })(window.myMod = {});
          
          var randomStr = myMod.randomElt(myMod.strList);
          var randomInt = myMod.randomElt(myMod.intList);
          </textarea></p>
          
          <p>Demonstrates integration of <a href="http://ternjs.net/">Tern</a>
          and CodeMirror. The following keys are bound:</p>
          
          <dl>
            <dt>Ctrl-Space</dt><dd>Autocomplete</dd>
            <dt>Ctrl-O</dt><dd>Find docs for the expression at the cursor</dd>
            <dt>Ctrl-I</dt><dd>Find type at cursor</dd>
            <dt>Alt-.</dt><dd>Jump to definition (Alt-, to jump back)</dd>
            <dt>Ctrl-Q</dt><dd>Rename variable</dd>
            <dt>Ctrl-.</dt><dd>Select all occurrences of a variable</dd>
          </dl>
          
          <p>Documentation is sparse for now. See the top of
          the <a href="../addon/tern/tern.js">script</a> for a rough API
          overview.</p>
          
          <script>
            function getURL(url, c) {
              var xhr = new XMLHttpRequest();
              xhr.open("get", url, true);
              xhr.send();
              xhr.onreadystatechange = function() {
                if (xhr.readyState != 4) return;
                if (xhr.status < 400) return c(null, xhr.responseText);
                var e = new Error(xhr.responseText || "No response");
                e.status = xhr.status;
                c(e);
              };
            }
          
            var server;
            getURL("http://ternjs.net/defs/ecma5.json", function(err, code) {
              if (err) throw new Error("Request for ecma5.json: " + err);
              server = new CodeMirror.TernServer({defs: [JSON.parse(code)]});
              editor.setOption("extraKeys", {
                "Ctrl-Space": function(cm) { server.complete(cm); },
                "Ctrl-I": function(cm) { server.showType(cm); },
                "Ctrl-O": function(cm) { server.showDocs(cm); },
                "Alt-.": function(cm) { server.jumpToDef(cm); },
                "Alt-,": function(cm) { server.jumpBack(cm); },
                "Ctrl-Q": function(cm) { server.rename(cm); },
                "Ctrl-.": function(cm) { server.selectName(cm); }
              })
              editor.on("cursorActivity", function(cm) { server.updateArgHints(cm); });
            });
          
            var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
              lineNumbers: true,
              mode: "javascript"
            });
          </script>
          
            </article>
          
        • theme.html
          <!doctype html>
          
          <title>CodeMirror: Theme Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../theme/3024-day.css">
          <link rel="stylesheet" href="../theme/3024-night.css">
          <link rel="stylesheet" href="../theme/ambiance.css">
          <link rel="stylesheet" href="../theme/base16-dark.css">
          <link rel="stylesheet" href="../theme/base16-light.css">
          <link rel="stylesheet" href="../theme/blackboard.css">
          <link rel="stylesheet" href="../theme/cobalt.css">
          <link rel="stylesheet" href="../theme/colorforth.css">
          <link rel="stylesheet" href="../theme/eclipse.css">
          <link rel="stylesheet" href="../theme/elegant.css">
          <link rel="stylesheet" href="../theme/erlang-dark.css">
          <link rel="stylesheet" href="../theme/lesser-dark.css">
          <link rel="stylesheet" href="../theme/liquibyte.css">
          <link rel="stylesheet" href="../theme/mbo.css">
          <link rel="stylesheet" href="../theme/mdn-like.css">
          <link rel="stylesheet" href="../theme/midnight.css">
          <link rel="stylesheet" href="../theme/monokai.css">
          <link rel="stylesheet" href="../theme/neat.css">
          <link rel="stylesheet" href="../theme/neo.css">
          <link rel="stylesheet" href="../theme/night.css">
          <link rel="stylesheet" href="../theme/paraiso-dark.css">
          <link rel="stylesheet" href="../theme/paraiso-light.css">
          <link rel="stylesheet" href="../theme/pastel-on-dark.css">
          <link rel="stylesheet" href="../theme/rubyblue.css">
          <link rel="stylesheet" href="../theme/solarized.css">
          <link rel="stylesheet" href="../theme/the-matrix.css">
          <link rel="stylesheet" href="../theme/tomorrow-night-bright.css">
          <link rel="stylesheet" href="../theme/tomorrow-night-eighties.css">
          <link rel="stylesheet" href="../theme/ttcn.css">
          <link rel="stylesheet" href="../theme/twilight.css">
          <link rel="stylesheet" href="../theme/vibrant-ink.css">
          <link rel="stylesheet" href="../theme/xq-dark.css">
          <link rel="stylesheet" href="../theme/xq-light.css">
          <link rel="stylesheet" href="../theme/zenburn.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../addon/selection/active-line.js"></script>
          <script src="../addon/edit/matchbrackets.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid black; font-size:13px}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Theme</a>
            </ul>
          </div>
          
          <article>
          <h2>Theme Demo</h2>
          <form><textarea id="code" name="code">
          function findSequence(goal) {
            function find(start, history) {
              if (start == goal)
                return history;
              else if (start > goal)
                return null;
              else
                return find(start + 5, "(" + history + " + 5)") ||
                       find(start * 3, "(" + history + " * 3)");
            }
            return find(1, "1");
          }</textarea></form>
          
          <p>Select a theme: <select onchange="selectTheme()" id=select>
              <option selected>default</option>
              <option>3024-day</option>
              <option>3024-night</option>
              <option>ambiance</option>
              <option>base16-dark</option>
              <option>base16-light</option>
              <option>blackboard</option>
              <option>cobalt</option>
              <option>colorforth</option>
              <option>eclipse</option>
              <option>elegant</option>
              <option>erlang-dark</option>
              <option>lesser-dark</option>
              <option>liquibyte</option>
              <option>mbo</option>
              <option>mdn-like</option>
              <option>midnight</option>
              <option>monokai</option>
              <option>neat</option>
              <option>neo</option>
              <option>night</option>
              <option>paraiso-dark</option>
              <option>paraiso-light</option>
              <option>pastel-on-dark</option>
              <option>rubyblue</option>
              <option>solarized dark</option>
              <option>solarized light</option>
              <option>the-matrix</option>
              <option>tomorrow-night-bright</option>
              <option>tomorrow-night-eighties</option>
              <option>ttcn</option>
              <option>twilight</option>
              <option>vibrant-ink</option>
              <option>xq-dark</option>
              <option>xq-light</option>
              <option>zenburn</option>
          </select>
          </p>
          
          <script>
            var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
              lineNumbers: true,
              styleActiveLine: true,
              matchBrackets: true
            });
            var input = document.getElementById("select");
            function selectTheme() {
              var theme = input.options[input.selectedIndex].innerHTML;
              editor.setOption("theme", theme);
            }
            var choice = document.location.search &&
                         decodeURIComponent(document.location.search.slice(1));
            if (choice) {
              input.value = choice;
              editor.setOption("theme", choice);
            }
          </script>
            </article>
          
        • trailingspace.html
          <!doctype html>
          
          <title>CodeMirror: Trailing Whitespace Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/edit/trailingspace.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                .cm-trailingspace {
                  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QUXCToH00Y1UgAAACFJREFUCNdjPMDBUc/AwNDAAAFMTAwMDA0OP34wQgX/AQBYgwYEx4f9lQAAAABJRU5ErkJggg==);
                  background-position: bottom left;
                  background-repeat: repeat-x;
                }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Trailing Whitespace</a>
            </ul>
          </div>
          
          <article>
          <h2>Trailing Whitespace Demo</h2>
          <form><textarea id="code" name="code">This text  
           has some	 
          trailing whitespace!</textarea></form>
          
              <script>
          var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            lineNumbers: true,
            showTrailingSpace: true
          });
          </script>
          
          <p>Uses
          the <a href="../doc/manual.html#addon_trailingspace">trailingspace</a>
          addon to highlight trailing whitespace.</p>
          
            </article>
          
        • variableheight.html
          <!doctype html>
          
          <title>CodeMirror: Variable Height Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/markdown/markdown.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid silver; border-width: 1px 2px; }
                .cm-header { font-family: arial; }
                .cm-header-1 { font-size: 150%; }
                .cm-header-2 { font-size: 130%; }
                .cm-header-3 { font-size: 120%; }
                .cm-header-4 { font-size: 110%; }
                .cm-header-5 { font-size: 100%; }
                .cm-header-6 { font-size: 90%; }
                .cm-strong { font-size: 140%; }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Variable Height</a>
            </ul>
          </div>
          
          <article>
          <h2>Variable Height Demo</h2>
          <form><textarea id="code" name="code"># A First Level Header
          
          **Bold** text in a normal-size paragraph.
          
          And a very long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long, wrapped line with a piece of **big** text inside of it.
          
          ## A Second Level Header
          
          Now is the time for all good men to come to
          the aid of their country. This is just a
          regular paragraph.
          
          The quick brown fox jumped over the lazy
          dog's back.
          
          ### Header 3
          
          > This is a blockquote.
          > 
          > This is the second paragraph in the blockquote.
          >
          > ## This is an H2 in a blockquote       
          </textarea></form>
              <script id="script">
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  lineWrapping: true,
                  mode: "markdown"
                });
              </script>
            </article>
          
        • vim.html
          <!doctype html>
          
          <title>CodeMirror: Vim bindings demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/dialog/dialog.css">
          <link rel="stylesheet" href="../theme/midnight.css">
          <link rel="stylesheet" href="../theme/solarized.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/dialog/dialog.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../mode/clike/clike.js"></script>
          <script src="../addon/edit/matchbrackets.js"></script>
          <script src="../keymap/vim.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Vim bindings</a>
            </ul>
          </div>
          
          <article>
          <h2>Vim bindings demo</h2>
          <form><textarea id="code" name="code">
          #include "syscalls.h"
          /* getchar:  simple buffered version */
          int getchar(void)
          {
            static char buf[BUFSIZ];
            static char *bufp = buf;
            static int n = 0;
            if (n == 0) {  /* buffer is empty */
              n = read(0, buf, sizeof buf);
              bufp = buf;
            }
            return (--n >= 0) ? (unsigned char) *bufp++ : EOF;
          }
          </textarea></form>
          <div style="font-size: 13px; width: 300px; height: 30px;">Key buffer: <span id="command-display"></span></div>
          
          <p>The vim keybindings are enabled by including <code><a
          href="../keymap/vim.js">keymap/vim.js</a></code> and setting the
          <code>keyMap</code> option to <code>vim</code>.</p>
          
          <p><strong>Features</strong></p>
          
          <ul>
            <li>All common motions and operators, including text objects</li>
            <li>Operator motion orthogonality</li>
            <li>Visual mode - characterwise, linewise, blockwise</li>
            <li>Full macro support (q, @)</li>
            <li>Incremental highlighted search (/, ?, #, *, g#, g*)</li>
            <li>Search/replace with confirm (:substitute, :%s)</li>
            <li>Search history</li>
            <li>Jump lists (Ctrl-o, Ctrl-i)</li>
            <li>Key/command mapping with API (:map, :nmap, :vmap)</li>
            <li>Sort (:sort)</li>
            <li>Marks (`, ')</li>
            <li>:global</li>
            <li>Insert mode behaves identical to base CodeMirror</li>
            <li>Cross-buffer yank/paste</li>
          </ul>
          
          <p>For the full list of key mappings and Ex commands, refer to the
          <code>defaultKeymap</code> and <code>defaultExCommandMap</code> at the
          top of <code><a href="../keymap/vim.js">keymap/vim.js</a></code>.
          
          <p>Note that while the vim mode tries to emulate the most useful
          features of vim as faithfully as possible, it does not strive to
          become a complete vim implementation</p>
          
              <script>
                CodeMirror.commands.save = function(){ alert("Saving"); };
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  mode: "text/x-csrc",
                  keyMap: "vim",
                  matchBrackets: true,
                  showCursorWhenSelecting: true
                });
                var commandDisplay = document.getElementById('command-display');
                var keys = '';
                CodeMirror.on(editor, 'vim-keypress', function(key) {
                  keys = keys + key;
                  commandDisplay.innerHTML = keys;
                });
                CodeMirror.on(editor, 'vim-command-done', function(e) {
                  keys = '';
                  commandDisplay.innerHTML = keys;
                });
              </script>
          
            </article>
          
        • visibletabs.html
          <!doctype html>
          
          <title>CodeMirror: Visible tabs demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/clike/clike.js"></script>
          <style type="text/css">
                .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}
                .cm-tab {
                   background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);
                   background-position: right;
                   background-repeat: no-repeat;
                }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Visible tabs</a>
            </ul>
          </div>
          
          <article>
          <h2>Visible tabs demo</h2>
          <form><textarea id="code" name="code">
          #include "syscalls.h"
          /* getchar:  simple buffered version */
          int getchar(void)
          {
          	static char buf[BUFSIZ];
          	static char *bufp = buf;
          	static int n = 0;
          	if (n == 0) {  /* buffer is empty */
          		n = read(0, buf, sizeof buf);
          		bufp = buf;
          	}
          	return (--n >= 0) ? (unsigned char) *bufp++ : EOF;
          }
          </textarea></form>
          
          <p>Tabs inside the editor are spans with the
          class <code>cm-tab</code>, and can be styled.</p>
          
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  tabSize: 4,
                  indentUnit: 4,
                  indentWithTabs: true,
                  mode: "text/x-csrc"
                });
              </script>
          
            </article>
          
        • widget.html
          <!doctype html>
          
          <title>CodeMirror: Inline Widget Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js"></script>
          <style type="text/css">
                .CodeMirror {border: 1px solid black;}
                .lint-error {font-family: arial; font-size: 70%; background: #ffa; color: #a00; padding: 2px 5px 3px; }
                .lint-error-icon {color: white; background-color: red; font-weight: bold; border-radius: 50%; padding: 0 3px; margin-right: 7px;}
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Inline Widget</a>
            </ul>
          </div>
          
          <article>
          <h2>Inline Widget Demo</h2>
          
          
              <div id=code></div>
              <script id="script">var widgets = []
          function updateHints() {
            editor.operation(function(){
              for (var i = 0; i < widgets.length; ++i)
                editor.removeLineWidget(widgets[i]);
              widgets.length = 0;
          
              JSHINT(editor.getValue());
              for (var i = 0; i < JSHINT.errors.length; ++i) {
                var err = JSHINT.errors[i];
                if (!err) continue;
                var msg = document.createElement("div");
                var icon = msg.appendChild(document.createElement("span"));
                icon.innerHTML = "!!";
                icon.className = "lint-error-icon";
                msg.appendChild(document.createTextNode(err.reason));
                msg.className = "lint-error";
                widgets.push(editor.addLineWidget(err.line - 1, msg, {coverGutter: false, noHScroll: true}));
              }
            });
            var info = editor.getScrollInfo();
            var after = editor.charCoords({line: editor.getCursor().line + 1, ch: 0}, "local").top;
            if (info.top + info.clientHeight < after)
              editor.scrollTo(null, after - info.clientHeight + 3);
          }
          
          window.onload = function() {
            var sc = document.getElementById("script");
            var content = sc.textContent || sc.innerText || sc.innerHTML;
          
            window.editor = CodeMirror(document.getElementById("code"), {
              lineNumbers: true,
              mode: "javascript",
              value: content
            });
          
            var waiting;
            editor.on("change", function() {
              clearTimeout(waiting);
              waiting = setTimeout(updateHints, 500);
            });
          
            setTimeout(updateHints, 100);
          };
          
          "long line to create a horizontal scrollbar, in order to test whether the (non-inline) widgets stay in place when scrolling to the right";
          </script>
          <p>This demo runs <a href="http://jshint.com">JSHint</a> over the code
          in the editor (which is the script used on this page), and
          inserts <a href="../doc/manual.html#addLineWidget">line widgets</a> to
          display the warnings that JSHint comes up with.</p>
            </article>
          
        • xmlcomplete.html
          <!doctype html>
          
          <title>CodeMirror: XML Autocomplete Demo</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="../addon/hint/show-hint.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/hint/show-hint.js"></script>
          <script src="../addon/hint/xml-hint.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <style type="text/css">
                .CodeMirror { border: 1px solid #eee; }
              </style>
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">XML Autocomplete</a>
            </ul>
          </div>
          
          <article>
          <h2>XML Autocomplete Demo</h2>
          <form><textarea id="code" name="code"><!-- write some xml below -->
          </textarea></form>
          
              <p>Press <strong>ctrl-space</strong>, or type a '<' character to
              activate autocompletion. This demo defines a simple schema that
              guides completion. The schema can be customized—see
              the <a href="../doc/manual.html#addon_xml-hint">manual</a>.</p>
          
              <p>Development of the <code>xml-hint</code> addon was kindly
              sponsored
              by <a href="http://www.xperiment.mobi">www.xperiment.mobi</a>.</p>
          
              <script>
                var dummy = {
                  attrs: {
                    color: ["red", "green", "blue", "purple", "white", "black", "yellow"],
                    size: ["large", "medium", "small"],
                    description: null
                  },
                  children: []
                };
          
                var tags = {
                  "!top": ["top"],
                  "!attrs": {
                    id: null,
                    class: ["A", "B", "C"]
                  },
                  top: {
                    attrs: {
                      lang: ["en", "de", "fr", "nl"],
                      freeform: null
                    },
                    children: ["animal", "plant"]
                  },
                  animal: {
                    attrs: {
                      name: null,
                      isduck: ["yes", "no"]
                    },
                    children: ["wings", "feet", "body", "head", "tail"]
                  },
                  plant: {
                    attrs: {name: null},
                    children: ["leaves", "stem", "flowers"]
                  },
                  wings: dummy, feet: dummy, body: dummy, head: dummy, tail: dummy,
                  leaves: dummy, stem: dummy, flowers: dummy
                };
          
                function completeAfter(cm, pred) {
                  var cur = cm.getCursor();
                  if (!pred || pred()) setTimeout(function() {
                    if (!cm.state.completionActive)
                      cm.showHint({completeSingle: false});
                  }, 100);
                  return CodeMirror.Pass;
                }
          
                function completeIfAfterLt(cm) {
                  return completeAfter(cm, function() {
                    var cur = cm.getCursor();
                    return cm.getRange(CodeMirror.Pos(cur.line, cur.ch - 1), cur) == "<";
                  });
                }
          
                function completeIfInTag(cm) {
                  return completeAfter(cm, function() {
                    var tok = cm.getTokenAt(cm.getCursor());
                    if (tok.type == "string" && (!/['"]/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1)) return false;
                    var inner = CodeMirror.innerMode(cm.getMode(), tok.state).state;
                    return inner.tagName;
                  });
                }
          
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  mode: "xml",
                  lineNumbers: true,
                  extraKeys: {
                    "'<'": completeAfter,
                    "'/'": completeIfAfterLt,
                    "' '": completeIfInTag,
                    "'='": completeIfInTag,
                    "Ctrl-Space": "autocomplete"
                  },
                  hintOptions: {schemaInfo: tags}
                });
              </script>
            </article>
          
      • doc
        • activebookmark.js
          // Kludge in HTML5 tag recognition in IE8
          document.createElement("section");
          document.createElement("article");
          
          (function() {
            if (!window.addEventListener) return;
            var pending = false, prevVal = null;
          
            function updateSoon() {
              if (!pending) {
                pending = true;
                setTimeout(update, 250);
              }
            }
          
            function update() {
              pending = false;
              var marks = document.getElementById("nav").getElementsByTagName("a"), found;
              for (var i = 0; i < marks.length; ++i) {
                var mark = marks[i], m;
                if (mark.getAttribute("data-default")) {
                  if (found == null) found = i;
                } else if (m = mark.href.match(/#(.*)/)) {
                  var ref = document.getElementById(m[1]);
                  if (ref && ref.getBoundingClientRect().top < 50)
                    found = i;
                }
              }
              if (found != null && found != prevVal) {
                prevVal = found;
                var lis = document.getElementById("nav").getElementsByTagName("li");
                for (var i = 0; i < lis.length; ++i) lis[i].className = "";
                for (var i = 0; i < marks.length; ++i) {
                  if (found == i) {
                    marks[i].className = "active";
                    for (var n = marks[i]; n; n = n.parentNode)
                      if (n.nodeName == "LI") n.className = "active";
                  } else {
                    marks[i].className = "";
                  }
                }
              }
            }
          
            window.addEventListener("scroll", updateSoon);
            window.addEventListener("load", updateSoon);
            window.addEventListener("hashchange", function() {
              setTimeout(function() {
                var hash = document.location.hash, found = null, m;
                var marks = document.getElementById("nav").getElementsByTagName("a");
                for (var i = 0; i < marks.length; i++)
                  if ((m = marks[i].href.match(/(#.*)/)) && m[1] == hash) { found = i; break; }
                if (found != null) for (var i = 0; i < marks.length; i++)
                  marks[i].className = i == found ? "active" : "";
              }, 300);
            });
          })();
          
        • compress.html
          <!doctype html>
          
          <title>CodeMirror: Compression Helper</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          <script src="../lib/codemirror.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <link rel=stylesheet href="../lib/codemirror.css">
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Compression helper</a>
            </ul>
          </div>
          
          <article>
          
          <h2>Script compression helper</h2>
          
              <p>To optimize loading CodeMirror, especially when including a
              bunch of different modes, it is recommended that you combine and
              minify (and preferably also gzip) the scripts. This page makes
              those first two steps very easy. Simply select the version and
              scripts you need in the form below, and
              click <strong>Compress</strong> to download the minified script
              file.</p>
          
              <form id="form" action="http://marijnhaverbeke.nl/uglifyjs" method="post" onsubmit="generateHeader();">
                <input type="hidden" id="download" name="download" value="codemirror-compressed.js"/>
                <p>Version: <select id="version" onchange="setVersion(this);" style="padding: 1px;">
                  <option value="http://codemirror.net/">HEAD</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=5.2.0;f=">5.2</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=5.1.0;f=">5.1</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=5.0.0;f=">5.0</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.13.0;f=">4.13</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.12.0;f=">4.12</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.11.0;f=">4.11</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.10.0;f=">4.10</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.9.0;f=">4.9</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.8.0;f=">4.8</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.7.0;f=">4.7</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.6.0;f=">4.6</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.5.0;f=">4.5</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.4.0;f=">4.4</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.3.0;f=">4.3</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.2.1;f=">4.2</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.2.0;f=">4.2</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.1.0;f=">4.1</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.0.3;f=">4.0</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.23.0;f=">3.23</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.22.0;f=">3.22</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.21.0;f=">3.21</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.20.0;f=">3.20</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.19.0;f=">3.19</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.18.0;f=">3.18</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.16.0;f=">3.16</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.15.0;f=">3.15</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.14.0;f=">3.14</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.13.0;f=">3.13</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.12;f=">3.12</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.11;f=">3.11</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.1;f=">3.1</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.02;f=">3.02</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.01;f=">3.01</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.0;f=">3.0</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.38;f=">2.38</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.37;f=">2.37</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.36;f=">2.36</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.35;f=">2.35</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.34;f=">2.34</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.33;f=">2.33</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.32;f=">2.32</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.31;f=">2.31</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.3;f=">2.3</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.25;f=">2.25</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.24;f=">2.24</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.23;f=">2.23</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.22;f=">2.22</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.21;f=">2.21</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.2;f=">2.2</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.18;f=">2.18</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.16;f=">2.16</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.15;f=">2.15</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.13;f=">2.13</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.12;f=">2.12</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.11;f=">2.11</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.1;f=">2.1</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.02;f=">2.02</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.01;f=">2.01</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.0;f=">2.0</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=beta2;f=">beta2</option>
                  <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=beta1;f=">beta1</option>
                </select></p>
          
                <select multiple="multiple" size="20" name="code_url" style="width: 40em;" class="field" id="files">
                  <optgroup label="CodeMirror Library">
                    <option value="http://codemirror.net/lib/codemirror.js" selected>codemirror.js</option>
                  </optgroup>
                  <optgroup label="Modes">
                    <option value="http://codemirror.net/mode/apl/apl.js">apl.js</option>
                    <option value="http://codemirror.net/mode/asn.1/asn.1.js">asn.1.js</option>
                    <option value="http://codemirror.net/mode/asterisk/asterisk.js">asterisk.js</option>
                    <option value="http://codemirror.net/mode/asciiarmor/asciiarmor.js">asciiarmor.js</option>
                    <option value="http://codemirror.net/mode/clike/clike.js">clike.js</option>
                    <option value="http://codemirror.net/mode/clojure/clojure.js">clojure.js</option>
                    <option value="http://codemirror.net/mode/cmake/cmake.js">cmake.js</option>
                    <option value="http://codemirror.net/mode/cobol/cobol.js">cobol.js</option>
                    <option value="http://codemirror.net/mode/coffeescript/coffeescript.js">coffeescript.js</option>
                    <option value="http://codemirror.net/mode/commonlisp/commonlisp.js">commonlisp.js</option>
                    <option value="http://codemirror.net/mode/css/css.js">css.js</option>
                    <option value="http://codemirror.net/mode/cypher/cypher.js">cypher.js</option>
                    <option value="http://codemirror.net/mode/d/d.js">d.js</option>
                    <option value="http://codemirror.net/mode/dart/dart.js">dart.js</option>
                    <option value="http://codemirror.net/mode/diff/diff.js">diff.js</option>
                    <option value="http://codemirror.net/mode/django/django.js">django.js</option>
                    <option value="http://codemirror.net/mode/dockerfile/dockerfile.js">dockerfile.js</option>
                    <option value="http://codemirror.net/mode/dtd/dtd.js">dtd.js</option>
                    <option value="http://codemirror.net/mode/dylan/dylan.js">dylan.js</option>
                    <option value="http://codemirror.net/mode/ebnf/ebnf.js">ebnf.js</option>
                    <option value="http://codemirror.net/mode/ecl/ecl.js">ecl.js</option>
                    <option value="http://codemirror.net/mode/eiffel/eiffel.js">eiffel.js</option>
                    <option value="http://codemirror.net/mode/erlang/erlang.js">erlang.js</option>
                    <option value="http://codemirror.net/mode/forth/forth.js">forth.js</option>
                    <option value="http://codemirror.net/mode/fortran/fortran.js">fortran.js</option>
                    <option value="http://codemirror.net/mode/gfm/gfm.js">gfm.js</option>
                    <option value="http://codemirror.net/mode/gas/gas.js">gas.js</option>
                    <option value="http://codemirror.net/mode/gherkin/gherkin.js">gherkin.js</option>
                    <option value="http://codemirror.net/mode/go/go.js">go.js</option>
                    <option value="http://codemirror.net/mode/groovy/groovy.js">groovy.js</option>
                    <option value="http://codemirror.net/mode/haml/haml.js">haml.js</option>
                    <option value="http://codemirror.net/mode/handlebars/handlebars.js">handlebars.js</option>
                    <option value="http://codemirror.net/mode/haskell/haskell.js">haskell.js</option>
                    <option value="http://codemirror.net/mode/haxe/haxe.js">haxe.js</option>
                    <option value="http://codemirror.net/mode/htmlembedded/htmlembedded.js">htmlembedded.js</option>
                    <option value="http://codemirror.net/mode/htmlmixed/htmlmixed.js">htmlmixed.js</option>
                    <option value="http://codemirror.net/mode/http/http.js">http.js</option>
                    <option value="http://codemirror.net/mode/idl/idl.js">idl.js</option>
                    <option value="http://codemirror.net/mode/jade/jade.js">jade.js</option>
                    <option value="http://codemirror.net/mode/javascript/javascript.js">javascript.js</option>
                    <option value="http://codemirror.net/mode/jinja2/jinja2.js">jinja2.js</option>
                    <option value="http://codemirror.net/mode/julia/julia.js">julia.js</option>
                    <option value="http://codemirror.net/mode/kotlin/kotlin.js">kotlin.js</option>
                    <option value="http://codemirror.net/mode/livescript/livescript.js">livescript.js</option>
                    <option value="http://codemirror.net/mode/lua/lua.js">lua.js</option>
                    <option value="http://codemirror.net/mode/markdown/markdown.js">markdown.js</option>
                    <option value="http://codemirror.net/mode/mathematica/mathematica.js">mathematica.js</option>
                    <option value="http://codemirror.net/mode/mirc/mirc.js">mirc.js</option>
                    <option value="http://codemirror.net/mode/mllike/mllike.js">mllike.js</option>
                    <option value="http://codemirror.net/mode/modelica/modelica.js">modelica.js</option>
                    <option value="http://codemirror.net/mode/mumps/mumps.js">mumps.js</option>
                    <option value="http://codemirror.net/mode/nginx/nginx.js">nginx.js</option>
                    <option value="http://codemirror.net/mode/ntriples/ntriples.js">ntriples.js</option>
                    <option value="http://codemirror.net/mode/octave/octave.js">octave.js</option>
                    <option value="http://codemirror.net/mode/pascal/pascal.js">pascal.js</option>
                    <option value="http://codemirror.net/mode/pegjs/pegjs.js">pegjs.js</option>
                    <option value="http://codemirror.net/mode/perl/perl.js">perl.js</option>
                    <option value="http://codemirror.net/mode/php/php.js">php.js</option>
                    <option value="http://codemirror.net/mode/pig/pig.js">pig.js</option>
                    <option value="http://codemirror.net/mode/properties/properties.js">properties.js</option>
                    <option value="http://codemirror.net/mode/python/python.js">python.js</option>
                    <option value="http://codemirror.net/mode/puppet/puppet.js">puppet.js</option>
                    <option value="http://codemirror.net/mode/q/q.js">q.js</option>
                    <option value="http://codemirror.net/mode/r/r.js">r.js</option>
                    <option value="http://codemirror.net/mode/rpm/rpm.js">rpm.js</option>
                    <option value="http://codemirror.net/mode/rst/rst.js">rst.js</option>
                    <option value="http://codemirror.net/mode/ruby/ruby.js">ruby.js</option>
                    <option value="http://codemirror.net/mode/rust/rust.js">rust.js</option>
                    <option value="http://codemirror.net/mode/sass/sass.js">sass.js</option>
                    <option value="http://codemirror.net/mode/scala/scala.js">scala.js</option>
                    <option value="http://codemirror.net/mode/scheme/scheme.js">scheme.js</option>
                    <option value="http://codemirror.net/mode/shell/shell.js">shell.js</option>
                    <option value="http://codemirror.net/mode/sieve/sieve.js">sieve.js</option>
                    <option value="http://codemirror.net/mode/slim/slim.js">slim.js</option>
                    <option value="http://codemirror.net/mode/smalltalk/smalltalk.js">smalltalk.js</option>
                    <option value="http://codemirror.net/mode/smarty/smarty.js">smarty.js</option>
                    <option value="http://codemirror.net/mode/solr/solr.js">solr.js</option>
                    <option value="http://codemirror.net/mode/soy/soy.js">soy.js</option>
                    <option value="http://codemirror.net/mode/sparql/sparql.js">sparql.js</option>
                    <option value="http://codemirror.net/mode/spreadsheet/spreadsheet.js">spreadsheet.js</option>
                    <option value="http://codemirror.net/mode/stylus/stylus.js">stylus.js</option>
                    <option value="http://codemirror.net/mode/sql/sql.js">sql.js</option>
                    <option value="http://codemirror.net/mode/stex/stex.js">stex.js</option>
                    <option value="http://codemirror.net/mode/tcl/tcl.js">tcl.js</option>
                    <option value="http://codemirror.net/mode/textile/textile.js">textile.js</option>
                    <option value="http://codemirror.net/mode/tiddlywiki/tiddlywiki.js">tiddlywiki.js</option>
                    <option value="http://codemirror.net/mode/tiki/tiki.js">tiki.js</option>
                    <option value="http://codemirror.net/mode/toml/toml.js">toml.js</option>
                    <option value="http://codemirror.net/mode/tornado/tornado.js">tornado.js</option>
                    <option value="http://codemirror.net/mode/troff/troff.js">troff.js</option>
                    <option value="http://codemirror.net/mode/ttcn/ttcn.js">ttcn.js</option>
                    <option value="http://codemirror.net/mode/ttcn-cfg/ttcn-cfg.js">ttcn-cfg.js</option>
                    <option value="http://codemirror.net/mode/turtle/turtle.js">turtle.js</option>
                    <option value="http://codemirror.net/mode/vb/vb.js">vb.js</option>
                    <option value="http://codemirror.net/mode/vbscript/vbscript.js">vbscript.js</option>
                    <option value="http://codemirror.net/mode/velocity/velocity.js">velocity.js</option>
                    <option value="http://codemirror.net/mode/verilog/verilog.js">verilog.js</option>
                    <option value="http://codemirror.net/mode/xml/xml.js">xml.js</option>
                    <option value="http://codemirror.net/mode/xquery/xquery.js">xquery.js</option>
                    <option value="http://codemirror.net/mode/yaml/yaml.js">yaml.js</option>
                    <option value="http://codemirror.net/mode/z80/z80.js">z80.js</option>
                  </optgroup>
                  <optgroup label="Add-ons">
                    <option value="http://codemirror.net/addon/selection/active-line.js">active-line.js</option>
                    <option value="http://codemirror.net/addon/hint/anyword-hint.js">anyword-hint.js</option>
                    <option value="http://codemirror.net/addon/fold/brace-fold.js">brace-fold.js</option>
                    <option value="http://codemirror.net/addon/edit/closebrackets.js">closebrackets.js</option>
                    <option value="http://codemirror.net/addon/edit/closetag.js">closetag.js</option>
                    <option value="http://codemirror.net/addon/runmode/colorize.js">colorize.js</option>
                    <option value="http://codemirror.net/addon/comment/comment.js">comment.js</option>
                    <option value="http://codemirror.net/addon/fold/comment-fold.js">comment-fold.js</option>
                    <option value="http://codemirror.net/addon/comment/continuecomment.js">continuecomment.js</option>
                    <option value="http://codemirror.net/addon/edit/continuelist.js">continuelist.js</option>
                    <option value="http://codemirror.net/addon/hint/css-hint.js">css-hint.js</option>
                    <option value="http://codemirror.net/addon/dialog/dialog.js">dialog.js</option>
                    <option value="http://codemirror.net/addon/fold/foldcode.js">foldcode.js</option>
                    <option value="http://codemirror.net/addon/fold/foldgutter.js">foldgutter.js</option>
                    <option value="http://codemirror.net/addon/display/fullscreen.js">fullscreen.js</option>
                    <option value="http://codemirror.net/addon/wrap/hardwrap.js">hardwrap.js</option>
                    <option value="http://codemirror.net/addon/hint/html-hint.js">html-hint.js</option>
                    <option value="http://codemirror.net/addon/fold/indent-fold.js">indent-fold.js</option>
                    <option value="http://codemirror.net/addon/hint/javascript-hint.js">javascript-hint.js</option>
                    <option value="http://codemirror.net/addon/lint/javascript-lint.js">javascript-lint.js</option>
                    <option value="http://codemirror.net/addon/lint/json-lint.js">json-lint.js</option>
                    <option value="http://codemirror.net/addon/lint/lint.js">lint.js</option>
                    <option value="http://codemirror.net/addon/mode/loadmode.js">loadmode.js</option>
                    <option value="http://codemirror.net/addon/fold/markdown-fold.js">markdown-fold.js</option>
                    <option value="http://codemirror.net/addon/selection/mark-selection.js">mark-selection.js</option>
                    <option value="http://codemirror.net/addon/search/match-highlighter.js">match-highlighter.js</option>
                    <option value="http://codemirror.net/addon/edit/matchbrackets.js">matchbrackets.js</option>
                    <option value="http://codemirror.net/addon/edit/matchtags.js">matchtags.js</option>
                    <option value="http://codemirror.net/addon/merge/merge.js">merge.js</option>
                    <option value="http://codemirror.net/addon/mode/multiplex.js">multiplex.js</option>
                    <option value="http://codemirror.net/addon/mode/overlay.js">overlay.js</option>
                    <option value="http://codemirror.net/addon/display/placeholder.js">placeholder.js</option>
                    <option value="http://codemirror.net/addon/display/rulers.js">rulers.js</option>
                    <option value="http://codemirror.net/addon/runmode/runmode.js">runmode.js</option>
                    <option value="http://codemirror.net/addon/runmode/runmode.node.js">runmode.node.js</option>
                    <option value="http://codemirror.net/addon/runmode/runmode-standalone.js">runmode-standalone.js</option>
                    <option value="http://codemirror.net/addon/search/search.js">search.js</option>
                    <option value="http://codemirror.net/addon/search/searchcursor.js">searchcursor.js</option>
                    <option value="http://codemirror.net/addon/hint/show-hint.js">show-hint.js</option>
                    <option value="http://codemirror.net/addon/mode/simple.js">simple.js</option>
                    <option value="http://codemirror.net/addon/scroll/simplescrollbars.js">simplescrollbars.js</option>
                    <option value="http://codemirror.net/addon/hint/sql-hint.js">sql-hint.js</option>
                    <option value="http://codemirror.net/addon/edit/trailingspace.js">trailingspace.js</option>
                    <option value="http://codemirror.net/addon/tern/tern.js">tern.js</option>
                    <option value="http://codemirror.net/addon/fold/xml-fold.js">xml-fold.js</option>
                    <option value="http://codemirror.net/addon/hint/xml-hint.js">xml-hint.js</option>
                    <option value="http://codemirror.net/addon/hint/yaml-lint.js">yaml-lint.js</option>
                  </optgroup>
                  <optgroup label="Keymaps">
                    <option value="http://codemirror.net/keymap/emacs.js">emacs.js</option>
                    <option value="http://codemirror.net/keymap/sublime.js">sublime.js</option>
                    <option value="http://codemirror.net/keymap/vim.js">vim.js</option>
                  </optgroup>
                </select>
          
                <p>
                  <button type="submit">Compress</button> with <a href="http://github.com/mishoo/UglifyJS/">UglifyJS</a>
                </p>
                <input type="hidden" id="header" name="header">
                <p>Custom code to add to the compressed file:<textarea name="js_code" style="width: 100%; height: 15em;" class="field" id="js_code"></textarea></p>
              </form>
          
              <script type="text/javascript">
                CodeMirror.fromTextArea(document.getElementById("js_code")).getWrapperElement().className += " field";
          
                function setVersion(ver) {
                  var urlprefix = ver.options[ver.selectedIndex].value;
                  var select = document.getElementById("files"), m;
                  for (var optgr = select.firstChild; optgr; optgr = optgr.nextSibling)
                    for (var opt = optgr.firstChild; opt; opt = opt.nextSibling) {
                      if (opt.nodeName != "OPTION")
                        continue;
                      else if (m = opt.value.match(/^http:\/\/codemirror.net\/(.*)$/))
                        opt.value = urlprefix + m[1];
                      else if (m = opt.value.match(/http:\/\/marijnhaverbeke.nl\/git\/codemirror\?a=blob_plain;hb=[^;]+;f=(.*)$/))
                        opt.value = urlprefix + m[1];
                    }
                 }
                 
                 function generateHeader() {
                   var versionNode = document.getElementById("version");
                   var version = versionNode.options[versionNode.selectedIndex].label
                   var filesNode = document.getElementById("files");
                   var optGroupHeaderIncluded;
          
                   // Generate the comment
                   var str = "/* CodeMirror - Minified & Bundled\n";
                   str += "   Generated on " + new Date().toLocaleDateString() + " with http://codemirror.net/doc/compress.html\n";
                   str += "   Version: " + version + "\n\n";
          
                   for (var group = filesNode.firstChild; group; group = group.nextSibling) {
                     optGroupHeaderIncluded = false;
                     for (var option = group.firstChild; option; option = option.nextSibling) {
                       if (option.nodeName !== "OPTION") {
                         continue;
                       } else if (option.selected) {
                         if (!optGroupHeaderIncluded) {
                           str += "   " + group.label + ":\n";
                           optGroupHeaderIncluded = true;
                         }
                         str += "   - " + option.label + "\n";
                       }
                     }
                   }
                   str += " */\n\n";
          
                   document.getElementById("header").value = str;
                 }
              </script>
          
          </article>
          
        • docs.css
          @font-face {
            font-family: 'Source Sans Pro';
            font-style: normal;
            font-weight: 400;
            src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url(//themes.googleusercontent.com/static/fonts/sourcesanspro/v5/ODelI1aHBYDBqgeIAH2zlBM0YzuT7MdOe03otPbuUS0.woff) format('woff');
          }
          
          body, html { margin: 0; padding: 0; height: 100%; }
          section, article { display: block; padding: 0; }
          
          body {
            background: #f8f8f8;
            font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif;
            line-height: 1.5;
          }
          
          p { margin-top: 0; }
          
          h2, h3, h1 {
            font-weight: normal;
            margin-bottom: .7em;
          }
          h1 { font-size: 140%; }
          h2 { font-size: 120%; }
          h3 { font-size: 110%; }
          article > h2:first-child, section:first-child > h2 { margin-top: 0; }
          
          #nav h1 {
            margin-right: 12px;
            margin-top: 0;
            margin-bottom: 2px;
            color: #d30707;
            letter-spacing: .5px;
          }
          
          a, a:visited, a:link, .quasilink {
            color: #A21313;
            text-decoration: none;
          }
          
          em {
            padding-right: 2px;
          }
          
          .quasilink {
            cursor: pointer;
          }
          
          article {
            max-width: 700px;
            margin: 0 0 0 160px;
            border-left: 2px solid #E30808;
            border-right: 1px solid #ddd;
            padding: 30px 50px 100px 50px;
            background: white;
            z-index: 2;
            position: relative;
            min-height: 100%;
            box-sizing: border-box;
            -moz-box-sizing: border-box;
          }
          
          #nav {
            position: fixed;
            padding-top: 30px;
            max-height: 100%;
            box-sizing: -moz-border-box;
            box-sizing: border-box;
            overflow-y: auto;
            left: 0; right: none;
            width: 160px;
            text-align: right;
            z-index: 1;
          }
          
          @media screen and (min-width: 1000px) {
            article {
              margin: 0 auto;
            }
            #nav {
              right: 50%;
              width: auto;
              border-right: 349px solid transparent;
            }
          }
          
          #nav ul {
            display: block;
            margin: 0; padding: 0;
            margin-bottom: 32px;
          }
          
          #nav li {
            display: block;
            margin-bottom: 4px;
          }
          
          #nav li ul {
            font-size: 80%;
            margin-bottom: 0;
            display: none;
          }
          
          #nav li.active ul {
            display: block;
          }
          
          #nav li li a {
            padding-right: 20px;
            display: inline-block;
          }
          
          #nav ul a {
            color: black;
            padding: 0 7px 1px 11px;
          }
          
          #nav ul a.active, #nav ul a:hover {
            border-bottom: 1px solid #E30808;
            margin-bottom: -1px;
            color: #E30808;
          }
          
          #logo {
            border: 0;
            margin-right: 12px;
            margin-bottom: 25px;
          }
          
          section {
            border-top: 1px solid #E30808;
            margin: 1.5em 0;
          }
          
          section.first {
            border: none;
            margin-top: 0;
          }
          
          #demo {
            position: relative;
          }
          
          #demolist {
            position: absolute;
            right: 5px;
            top: 5px;
            z-index: 25;
          }
          
          .yinyang {
            position: absolute;
            top: -10px;
            left: 0; right: 0;
            margin: auto;
            display: block;
            height: 120px;
          }
          
          .actions {
            margin: 1em 0 0;
            min-height: 100px;
            position: relative;
          }
          
          .actionspicture {
            pointer-events: none;
            position: absolute;
            height: 100px;
            top: 0; left: 0; right: 0;
          }
          
          .actionlink {
            pointer-events: auto;
            font-family: arial;
            font-size: 80%;
            font-weight: bold;
            position: absolute;
            top: 0; bottom: 0;
            line-height: 1;
            height: 1em;
            margin: auto;
          }
          
          .actionlink.download {
            color: white;
            right: 50%;
            margin-right: 13px;
            text-shadow: -1px 1px 3px #b00, -1px -1px 3px #b00, 1px 0px 3px #b00;
          }
          
          .actionlink.fund {
            color: #b00;
            left: 50%;
            margin-left: 15px;
          }
          
          .actionlink:hover {
            text-decoration: underline;
          }
          
          .actionlink a {
            color: inherit;
          }
          
          .actionsleft {
            float: left;
          }
          
          .actionsright {
            float: right;
            text-align: right;
          }
          
          @media screen and (max-width: 800px) {
            .actions {
              padding-top: 120px;
            }
            .actionsleft, .actionsright {
              float: none;
              text-align: left;
              margin-bottom: 1em;
            }
          }
          
          th {
            text-decoration: underline;
            font-weight: normal;
            text-align: left;
          }
          
          #features ul {
            list-style: none;
            margin: 0 0 1em;
            padding: 0 0 0 1.2em;
          }
          
          #features li:before {
            content: "-";
            width: 1em;
            display: inline-block;
            padding: 0;
            margin: 0;
            margin-left: -1em;
          }
          
          .rel {
            margin-bottom: 0;
          }
          .rel-note {
            margin-top: 0;
            color: #555;
          }
          
          pre {
            padding-left: 15px;
            border-left: 2px solid #ddd;
          }
          
          code {
            padding: 0 2px;
          }
          
          strong {
            text-decoration: underline;
            font-weight: normal;
          }
          
          .field {
            border: 1px solid #A21313;
          }
          
        • internals.html
          <!doctype html>
          
          <title>CodeMirror: Internals</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          <style>dl dl {margin: 0;} .update {color: #d40 !important}</style>
          <script src="activebookmark.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a href="#top">Introduction</a></li>
              <li><a href="#approach">General Approach</a></li>
              <li><a href="#input">Input</a></li>
              <li><a href="#selection">Selection</a></li>
              <li><a href="#update">Intelligent Updating</a></li>
              <li><a href="#parse">Parsing</a></li>
              <li><a href="#summary">What Gives?</a></li>
              <li><a href="#btree">Content Representation</a></li>
              <li><a href="#keymap">Key Maps</a></li>
            </ul>
          </div>
          
          <article>
          
          <h2 id=top>(Re-) Implementing A Syntax-Highlighting Editor in JavaScript</h2>
          
          <p style="font-size: 85%" id="intro">
            <strong>Topic:</strong> JavaScript, code editor implementation<br>
            <strong>Author:</strong> Marijn Haverbeke<br>
            <strong>Date:</strong> March 2nd 2011 (updated November 13th 2011)
          </p>
          
          <p style="padding: 0 3em 0 2em"><strong>Caution</strong>: this text was written briefly after
          version 2 was initially written. It no longer (even including the
          update at the bottom) fully represents the current implementation. I'm
          leaving it here as a historic document. For more up-to-date
          information, look at the entries
          tagged <a href="http://marijnhaverbeke.nl/blog/#cm-internals">cm-internals</a>
          on my blog.</p>
          
          <p>This is a followup to
          my <a href="http://codemirror.net/story.html">Brutal Odyssey to the
          Dark Side of the DOM Tree</a> story. That one describes the
          mind-bending process of implementing (what would become) CodeMirror 1.
          This one describes the internals of CodeMirror 2, a complete rewrite
          and rethink of the old code base. I wanted to give this piece another
          Hunter Thompson copycat subtitle, but somehow that would be out of
          place—the process this time around was one of straightforward
          engineering, requiring no serious mind-bending whatsoever.</p>
          
          <p>So, what is wrong with CodeMirror 1? I'd estimate, by mailing list
          activity and general search-engine presence, that it has been
          integrated into about a thousand systems by now. The most prominent
          one, since a few weeks,
          being <a href="http://googlecode.blogspot.com/2011/01/make-quick-fixes-quicker-on-google.html">Google
          code's project hosting</a>. It works, and it's being used widely.</p>
          
          <p>Still, I did not start replacing it because I was bored. CodeMirror
          1 was heavily reliant on <code>designMode</code>
          or <code>contentEditable</code> (depending on the browser). Neither of
          these are well specified (HTML5 tries
          to <a href="http://www.w3.org/TR/html5/editing.html#contenteditable">specify</a>
          their basics), and, more importantly, they tend to be one of the more
          obscure and buggy areas of browser functionality—CodeMirror, by using
          this functionality in a non-typical way, was constantly running up
          against browser bugs. WebKit wouldn't show an empty line at the end of
          the document, and in some releases would suddenly get unbearably slow.
          Firefox would show the cursor in the wrong place. Internet Explorer
          would insist on linkifying everything that looked like a URL or email
          address, a behaviour that can't be turned off. Some bugs I managed to
          work around (which was often a frustrating, painful process), others,
          such as the Firefox cursor placement, I gave up on, and had to tell
          user after user that they were known problems, but not something I
          could help.</p>
          
          <p>Also, there is the fact that <code>designMode</code> (which seemed
          to be less buggy than <code>contentEditable</code> in Webkit and
          Firefox, and was thus used by CodeMirror 1 in those browsers) requires
          a frame. Frames are another tricky area. It takes some effort to
          prevent getting tripped up by domain restrictions, they don't
          initialize synchronously, behave strangely in response to the back
          button, and, on several browsers, can't be moved around the DOM
          without having them re-initialize. They did provide a very nice way to
          namespace the library, though—CodeMirror 1 could freely pollute the
          namespace inside the frame.</p>
          
          <p>Finally, working with an editable document means working with
          selection in arbitrary DOM structures. Internet Explorer (8 and
          before) has an utterly different (and awkward) selection API than all
          of the other browsers, and even among the different implementations of
          <code>document.selection</code>, details about how exactly a selection
          is represented vary quite a bit. Add to that the fact that Opera's
          selection support tended to be very buggy until recently, and you can
          imagine why CodeMirror 1 contains 700 lines of selection-handling
          code.</p>
          
          <p>And that brings us to the main issue with the CodeMirror 1
          code base: The proportion of browser-bug-workarounds to real
          application code was getting dangerously high. By building on top of a
          few dodgy features, I put the system in a vulnerable position—any
          incompatibility and bugginess in these features, I had to paper over
          with my own code. Not only did I have to do some serious stunt-work to
          get it to work on older browsers (as detailed in the
          previous <a href="http://codemirror.net/story.html">story</a>), things
          also kept breaking in newly released versions, requiring me to come up
          with <em>new</em> scary hacks in order to keep up. This was starting
          to lose its appeal.</p>
          
          <section id=approach>
            <h2>General Approach</h2>
          
          <p>What CodeMirror 2 does is try to sidestep most of the hairy hacks
          that came up in version 1. I owe a lot to the
          <a href="http://ace.ajax.org">ACE</a> editor for inspiration on how to
          approach this.</p>
          
          <p>I absolutely did not want to be completely reliant on key events to
          generate my input. Every JavaScript programmer knows that key event
          information is horrible and incomplete. Some people (most awesomely
          Mihai Bazon with <a href="http://ymacs.org">Ymacs</a>) have been able
          to build more or less functioning editors by directly reading key
          events, but it takes a lot of work (the kind of never-ending, fragile
          work I described earlier), and will never be able to properly support
          things like multi-keystoke international character
          input. <a href="#keymap" class="update">[see below for caveat]</a></p>
          
          <p>So what I do is focus a hidden textarea, and let the browser
          believe that the user is typing into that. What we show to the user is
          a DOM structure we built to represent his document. If this is updated
          quickly enough, and shows some kind of believable cursor, it feels
          like a real text-input control.</p>
          
          <p>Another big win is that this DOM representation does not have to
          span the whole document. Some CodeMirror 1 users insisted that they
          needed to put a 30 thousand line XML document into CodeMirror. Putting
          all that into the DOM takes a while, especially since, for some
          reason, an editable DOM tree is slower than a normal one on most
          browsers. If we have full control over what we show, we must only
          ensure that the visible part of the document has been added, and can
          do the rest only when needed. (Fortunately, the <code>onscroll</code>
          event works almost the same on all browsers, and lends itself well to
          displaying things only as they are scrolled into view.)</p>
          </section>
          <section id="input">
            <h2>Input</h2>
          
          <p>ACE uses its hidden textarea only as a text input shim, and does
          all cursor movement and things like text deletion itself by directly
          handling key events. CodeMirror's way is to let the browser do its
          thing as much as possible, and not, for example, define its own set of
          key bindings. One way to do this would have been to have the whole
          document inside the hidden textarea, and after each key event update
          the display DOM to reflect what's in that textarea.</p>
          
          <p>That'd be simple, but it is not realistic. For even medium-sized
          document the editor would be constantly munging huge strings, and get
          terribly slow. What CodeMirror 2 does is put the current selection,
          along with an extra line on the top and on the bottom, into the
          textarea.</p>
          
          <p>This means that the arrow keys (and their ctrl-variations), home,
          end, etcetera, do not have to be handled specially. We just read the
          cursor position in the textarea, and update our cursor to match it.
          Also, copy and paste work pretty much for free, and people get their
          native key bindings, without any special work on my part. For example,
          I have emacs key bindings configured for Chrome and Firefox. There is
          no way for a script to detect this. <a class="update"
          href="#keymap">[no longer the case]</a></p>
          
          <p>Of course, since only a small part of the document sits in the
          textarea, keys like page up and ctrl-end won't do the right thing.
          CodeMirror is catching those events and handling them itself.</p>
          </section>
          <section id="selection">
            <h2>Selection</h2>
          
          <p>Getting and setting the selection range of a textarea in modern
          browsers is trivial—you just use the <code>selectionStart</code>
          and <code>selectionEnd</code> properties. On IE you have to do some
          insane stuff with temporary ranges and compensating for the fact that
          moving the selection by a 'character' will treat \r\n as a single
          character, but even there it is possible to build functions that
          reliably set and get the selection range.</p>
          
          <p>But consider this typical case: When I'm somewhere in my document,
          press shift, and press the up arrow, something gets selected. Then, if
          I, still holding shift, press the up arrow again, the top of my
          selection is adjusted. The selection remembers where its <em>head</em>
          and its <em>anchor</em> are, and moves the head when we shift-move.
          This is a generally accepted property of selections, and done right by
          every editing component built in the past twenty years.</p>
          
          <p>But not something that the browser selection APIs expose.</p>
          
          <p>Great. So when someone creates an 'upside-down' selection, the next
          time CodeMirror has to update the textarea, it'll re-create the
          selection as an 'upside-up' selection, with the anchor at the top, and
          the next cursor motion will behave in an unexpected way—our second
          up-arrow press in the example above will not do anything, since it is
          interpreted in exactly the same way as the first.</p>
          
          <p>No problem. We'll just, ehm, detect that the selection is
          upside-down (you can tell by the way it was created), and then, when
          an upside-down selection is present, and a cursor-moving key is
          pressed in combination with shift, we quickly collapse the selection
          in the textarea to its start, allow the key to take effect, and then
          combine its new head with its old anchor to get the <em>real</em>
          selection.</p>
          
          <p>In short, scary hacks could not be avoided entirely in CodeMirror
          2.</p>
          
          <p>And, the observant reader might ask, how do you even know that a
          key combo is a cursor-moving combo, if you claim you support any
          native key bindings? Well, we don't, but we can learn. The editor
          keeps a set known cursor-movement combos (initialized to the
          predictable defaults), and updates this set when it observes that
          pressing a certain key had (only) the effect of moving the cursor.
          This, of course, doesn't work if the first time the key is used was
          for extending an inverted selection, but it works most of the
          time.</p>
          </section>
          <section id="update">
            <h2>Intelligent Updating</h2>
          
          <p>One thing that always comes up when you have a complicated internal
          state that's reflected in some user-visible external representation
          (in this case, the displayed code and the textarea's content) is
          keeping the two in sync. The naive way is to just update the display
          every time you change your state, but this is not only error prone
          (you'll forget), it also easily leads to duplicate work on big,
          composite operations. Then you start passing around flags indicating
          whether the display should be updated in an attempt to be efficient
          again and, well, at that point you might as well give up completely.</p>
          
          <p>I did go down that road, but then switched to a much simpler model:
          simply keep track of all the things that have been changed during an
          action, and then, only at the end, use this information to update the
          user-visible display.</p>
          
          <p>CodeMirror uses a concept of <em>operations</em>, which start by
          calling a specific set-up function that clears the state and end by
          calling another function that reads this state and does the required
          updating. Most event handlers, and all the user-visible methods that
          change state are wrapped like this. There's a method
          called <code>operation</code> that accepts a function, and returns
          another function that wraps the given function as an operation.</p>
          
          <p>It's trivial to extend this (as CodeMirror does) to detect nesting,
          and, when an operation is started inside an operation, simply
          increment the nesting count, and only do the updating when this count
          reaches zero again.</p>
          
          <p>If we have a set of changed ranges and know the currently shown
          range, we can (with some awkward code to deal with the fact that
          changes can add and remove lines, so we're dealing with a changing
          coordinate system) construct a map of the ranges that were left
          intact. We can then compare this map with the part of the document
          that's currently visible (based on scroll offset and editor height) to
          determine whether something needs to be updated.</p>
          
          <p>CodeMirror uses two update algorithms—a full refresh, where it just
          discards the whole part of the DOM that contains the edited text and
          rebuilds it, and a patch algorithm, where it uses the information
          about changed and intact ranges to update only the out-of-date parts
          of the DOM. When more than 30 percent (which is the current heuristic,
          might change) of the lines need to be updated, the full refresh is
          chosen (since it's faster to do than painstakingly finding and
          updating all the changed lines), in the other case it does the
          patching (so that, if you scroll a line or select another character,
          the whole screen doesn't have to be
          re-rendered). <span class="update">[the full-refresh
          algorithm was dropped, it wasn't really faster than the patching
          one]</span></p>
          
          <p>All updating uses <code>innerHTML</code> rather than direct DOM
          manipulation, since that still seems to be by far the fastest way to
          build documents. There's a per-line function that combines the
          highlighting, <a href="manual.html#markText">marking</a>, and
          selection info for that line into a snippet of HTML. The patch updater
          uses this to reset individual lines, the refresh updater builds an
          HTML chunk for the whole visible document at once, and then uses a
          single <code>innerHTML</code> update to do the refresh.</p>
          </section>
          <section id="parse">
            <h2>Parsers can be Simple</h2>
          
          <p>When I wrote CodeMirror 1, I
          thought <a href="http://codemirror.net/story.html#parser">interruptable
          parsers</a> were a hugely scary and complicated thing, and I used a
          bunch of heavyweight abstractions to keep this supposed complexity
          under control: parsers
          were <a href="http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/">iterators</a>
          that consumed input from another iterator, and used funny
          closure-resetting tricks to copy and resume themselves.</p>
          
          <p>This made for a rather nice system, in that parsers formed strictly
          separate modules, and could be composed in predictable ways.
          Unfortunately, it was quite slow (stacking three or four iterators on
          top of each other), and extremely intimidating to people not used to a
          functional programming style.</p>
          
          <p>With a few small changes, however, we can keep all those
          advantages, but simplify the API and make the whole thing less
          indirect and inefficient. CodeMirror
          2's <a href="manual.html#modeapi">mode API</a> uses explicit state
          objects, and makes the parser/tokenizer a function that simply takes a
          state and a character stream abstraction, advances the stream one
          token, and returns the way the token should be styled. This state may
          be copied, optionally in a mode-defined way, in order to be able to
          continue a parse at a given point. Even someone who's never touched a
          lambda in his life can understand this approach. Additionally, far
          fewer objects are allocated in the course of parsing now.</p>
          
          <p>The biggest speedup comes from the fact that the parsing no longer
          has to touch the DOM though. In CodeMirror 1, on an older browser, you
          could <em>see</em> the parser work its way through the document,
          managing some twenty lines in each 50-millisecond time slice it got. It
          was reading its input from the DOM, and updating the DOM as it went
          along, which any experienced JavaScript programmer will immediately
          spot as a recipe for slowness. In CodeMirror 2, the parser usually
          finishes the whole document in a single 100-millisecond time slice—it
          manages some 1500 lines during that time on Chrome. All it has to do
          is munge strings, so there is no real reason for it to be slow
          anymore.</p>
          </section>
          <section id="summary">
            <h2>What Gives?</h2>
          
          <p>Given all this, what can you expect from CodeMirror 2?</p>
          
          <ul>
          
          <li><strong>Small.</strong> the base library is
          some <span class="update">45k</span> when minified
          now, <span class="update">17k</span> when gzipped. It's smaller than
          its own logo.</li>
          
          <li><strong>Lightweight.</strong> CodeMirror 2 initializes very
          quickly, and does almost no work when it is not focused. This means
          you can treat it almost like a textarea, have multiple instances on a
          page without trouble.</li>
          
          <li><strong>Huge document support.</strong> Since highlighting is
          really fast, and no DOM structure is being built for non-visible
          content, you don't have to worry about locking up your browser when a
          user enters a megabyte-sized document.</li>
          
          <li><strong>Extended API.</strong> Some things kept coming up in the
          mailing list, such as marking pieces of text or lines, which were
          extremely hard to do with CodeMirror 1. The new version has proper
          support for these built in.</li>
          
          <li><strong>Tab support.</strong> Tabs inside editable documents were,
          for some reason, a no-go. At least six different people announced they
          were going to add tab support to CodeMirror 1, none survived (I mean,
          none delivered a working version). CodeMirror 2 no longer removes tabs
          from your document.</li>
          
          <li><strong>Sane styling.</strong> <code>iframe</code> nodes aren't
          really known for respecting document flow. Now that an editor instance
          is a plain <code>div</code> element, it is much easier to size it to
          fit the surrounding elements. You don't even have to make it scroll if
          you do not <a href="../demo/resize.html">want to</a>.</li>
          
          </ul>
          
          <p>On the downside, a CodeMirror 2 instance is <em>not</em> a native
          editable component. Though it does its best to emulate such a
          component as much as possible, there is functionality that browsers
          just do not allow us to hook into. Doing select-all from the context
          menu, for example, is not currently detected by CodeMirror.</p>
          
          <p id="changes" style="margin-top: 2em;"><span style="font-weight:
          bold">[Updates from November 13th 2011]</span> Recently, I've made
          some changes to the codebase that cause some of the text above to no
          longer be current. I've left the text intact, but added markers at the
          passages that are now inaccurate. The new situation is described
          below.</p>
          </section>
          <section id="btree">
            <h2>Content Representation</h2>
          
          <p>The original implementation of CodeMirror 2 represented the
          document as a flat array of line objects. This worked well—splicing
          arrays will require the part of the array after the splice to be
          moved, but this is basically just a simple <code>memmove</code> of a
          bunch of pointers, so it is cheap even for huge documents.</p>
          
          <p>However, I recently added line wrapping and code folding (line
          collapsing, basically). Once lines start taking up a non-constant
          amount of vertical space, looking up a line by vertical position
          (which is needed when someone clicks the document, and to determine
          the visible part of the document during scrolling) can only be done
          with a linear scan through the whole array, summing up line heights as
          you go. Seeing how I've been going out of my way to make big documents
          fast, this is not acceptable.</p>
          
          <p>The new representation is based on a B-tree. The leaves of the tree
          contain arrays of line objects, with a fixed minimum and maximum size,
          and the non-leaf nodes simply hold arrays of child nodes. Each node
          stores both the amount of lines that live below them and the vertical
          space taken up by these lines. This allows the tree to be indexed both
          by line number and by vertical position, and all access has
          logarithmic complexity in relation to the document size.</p>
          
          <p>I gave line objects and tree nodes parent pointers, to the node
          above them. When a line has to update its height, it can simply walk
          these pointers to the top of the tree, adding or subtracting the
          difference in height from each node it encounters. The parent pointers
          also make it cheaper (in complexity terms, the difference is probably
          tiny in normal-sized documents) to find the current line number when
          given a line object. In the old approach, the whole document array had
          to be searched. Now, we can just walk up the tree and count the sizes
          of the nodes coming before us at each level.</p>
          
          <p>I chose B-trees, not regular binary trees, mostly because they
          allow for very fast bulk insertions and deletions. When there is a big
          change to a document, it typically involves adding, deleting, or
          replacing a chunk of subsequent lines. In a regular balanced tree, all
          these inserts or deletes would have to be done separately, which could
          be really expensive. In a B-tree, to insert a chunk, you just walk
          down the tree once to find where it should go, insert them all in one
          shot, and then break up the node if needed. This breaking up might
          involve breaking up nodes further up, but only requires a single pass
          back up the tree. For deletion, I'm somewhat lax in keeping things
          balanced—I just collapse nodes into a leaf when their child count goes
          below a given number. This means that there are some weird editing
          patterns that may result in a seriously unbalanced tree, but even such
          an unbalanced tree will perform well, unless you spend a day making
          strangely repeating edits to a really big document.</p>
          </section>
          <section id="keymap">
            <h2>Keymaps</h2>
          
          <p><a href="#approach">Above</a>, I claimed that directly catching key
          events for things like cursor movement is impractical because it
          requires some browser-specific kludges. I then proceeded to explain
          some awful <a href="#selection">hacks</a> that were needed to make it
          possible for the selection changes to be detected through the
          textarea. In fact, the second hack is about as bad as the first.</p>
          
          <p>On top of that, in the presence of user-configurable tab sizes and
          collapsed and wrapped lines, lining up cursor movement in the textarea
          with what's visible on the screen becomes a nightmare. Thus, I've
          decided to move to a model where the textarea's selection is no longer
          depended on.</p>
          
          <p>So I moved to a model where all cursor movement is handled by my
          own code. This adds support for a goal column, proper interaction of
          cursor movement with collapsed lines, and makes it possible for
          vertical movement to move through wrapped lines properly, instead of
          just treating them like non-wrapped lines.</p>
          
          <p>The key event handlers now translate the key event into a string,
          something like <code>Ctrl-Home</code> or <code>Shift-Cmd-R</code>, and
          use that string to look up an action to perform. To make keybinding
          customizable, this lookup goes through
          a <a href="manual.html#option_keyMap">table</a>, using a scheme that
          allows such tables to be chained together (for example, the default
          Mac bindings fall through to a table named 'emacsy', which defines
          basic Emacs-style bindings like <code>Ctrl-F</code>, and which is also
          used by the custom Emacs bindings).</p>
          
          <p>A new
          option <a href="manual.html#option_extraKeys"><code>extraKeys</code></a>
          allows ad-hoc keybindings to be defined in a much nicer way than what
          was possible with the
          old <a href="manual.html#option_onKeyEvent"><code>onKeyEvent</code></a>
          callback. You simply provide an object mapping key identifiers to
          functions, instead of painstakingly looking at raw key events.</p>
          
          <p>Built-in commands map to strings, rather than functions, for
          example <code>"goLineUp"</code> is the default action bound to the up
          arrow key. This allows new keymaps to refer to them without
          duplicating any code. New commands can be defined by assigning to
          the <code>CodeMirror.commands</code> object, which maps such commands
          to functions.</p>
          
          <p>The hidden textarea now only holds the current selection, with no
          extra characters around it. This has a nice advantage: polling for
          input becomes much, much faster. If there's a big selection, this text
          does not have to be read from the textarea every time—when we poll,
          just noticing that something is still selected is enough to tell us
          that no new text was typed.</p>
          
          <p>The reason that cheap polling is important is that many browsers do
          not fire useful events on IME (input method engine) input, which is
          the thing where people inputting a language like Japanese or Chinese
          use multiple keystrokes to create a character or sequence of
          characters. Most modern browsers fire <code>input</code> when the
          composing is finished, but many don't fire anything when the character
          is updated <em>during</em> composition. So we poll, whenever the
          editor is focused, to provide immediate updates of the display.</p>
          
          </article>
          
        • logo.png
          �PNG
          
          
        • realworld.html
          <!doctype html>
          
          <title>CodeMirror: Real-world Uses</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Real-world uses</a>
            </ul>
          </div>
          
          <article>
          
          <h2>CodeMirror real-world uses</h2>
          
              <p>Create a <a href="https://github.com/codemirror/codemirror">pull
              request</a> if you'd like your project to be added to this list.</p>
          
              <ul>
                <li><a href="http://brackets.io">Adobe Brackets</a> (code editor)</li>
                <li><a href="http://amber-lang.net/">Amber</a> (JavaScript-based Smalltalk system)</li>
                <li><a href="http://apachegui.ca/">Apache GUI</a></li>
                <li><a href="http://apeye.org/">APEye</a> (tool for testing &amp; documenting APIs)</li>
                <li><a href="https://chrome.google.com/webstore/detail/better-text-viewer/lcaidopdffhfemoefoaadecppnjdknkc">Better Text Viewer</a> (plain text reader app for Chrome)</li>
                <li><a href="http://blog.bitbucket.org/2013/05/14/edit-your-code-in-the-cloud-with-bitbucket/">Bitbucket</a> (code hosting)</li>
                <li><a href="http://buzz.blogger.com/2013/04/improvements-to-blogger-template-html.html">Blogger's template editor</a></li>
                <li><a href="http://bluegriffon.org/">BlueGriffon</a> (HTML editor)</li>
                <li><a href="http://cargocollective.com/">Cargo Collective</a> (creative publishing platform)</li>
                <li><a href="https://developers.google.com/chrome-developer-tools/">Chrome DevTools</a></li>
                <li><a href="http://clickhelp.co/">ClickHelp</a> (technical writing tool)</li>
                <li><a href="http://codeworld.info/">CodeWorld</a> (Haskell playground)</li>
                <li><a href="http://complete-ly.appspot.com/playground/code.playground.html">Complete.ly playground</a></li>
                <li><a href="https://codeanywhere.com/">Codeanywhere</a> (multi-platform cloud editor)</li>
                <li><a href="http://drupal.org/project/cpn">Code per Node</a> (Drupal module)</li>
                <li><a href="http://www.codebugapp.com/">Codebug</a> (PHP Xdebug front-end)</li>
                <li><a href="https://github.com/angelozerr/CodeMirror-Eclipse">CodeMirror Eclipse</a> (embed CM in Eclipse)</li>
                <li><a href="http://emmet.io/blog/codemirror-movie/">CodeMirror movie</a> (scripted editing demos)</li>
                <li><a href="http://code.google.com/p/codemirror2-gwt/">CodeMirror2-GWT</a> (Google Web Toolkit wrapper)</li>
                <li><a href="http://www.crunchzilla.com/code-monster">Code Monster</a> & <a href="http://www.crunchzilla.com/code-maven">Code Maven</a> (learning environment)</li>
                <li><a href="http://codepen.io">Codepen</a> (gallery of animations)</li>
                <li><a href="https://coderpad.io/">Coderpad</a> (interviewing tool)</li>
                <li><a href="http://sasstwo.codeschool.com/levels/1/challenges/1">Code School</a> (online tech learning environment)</li>
                <li><a href="http://code-snippets.bungeshea.com/">Code Snippets</a> (WordPress snippet management plugin)</li>
                <li><a href="http://antonmi.github.io/code_together/">Code together</a> (collaborative editing)</li>
                <li><a href="http://codev.it/">Codev</a> (collaborative IDE)</li>
                <li><a href="http://www.codezample.com">CodeZample</a> (code snippet sharing)</li>
                <li><a href="http://codio.com">Codio</a> (Web IDE)</li>
                <li><a href="http://ot.substance.io/demo/">Collaborative CodeMirror demo</a> (CodeMirror + operational transforms)</li>
                <li><a href="http://www.communitycodecamp.com/">Community Code Camp</a> (code snippet sharing)</li>
                <li><a href="http://www.compilejava.net/">compilejava.net</a> (online Java sandbox)</li>
                <li><a href="http://www.ckwnc.com/">CKWNC</a> (UML editor)</li>
                <li><a href="http://www.crossui.com/">CrossUI</a> (cross-platform UI builder)</li>
                <li><a href="http://rsnous.com/cruncher/">Cruncher</a> (notepad with calculation features)</li>
                <li><a href="http://www.crudzilla.com/">Crudzilla</a> (self-hosted web IDE)</li>
                <li><a href="http://cssdeck.com/">CSSDeck</a> (CSS showcase)</li>
                <li><a href="http://ireneros.com/deck/deck.js-codemirror/introduction/#textarea-code">Deck.js integration</a> (slides with editors)</li>
                <li><a href="http://www.dbninja.com">DbNinja</a> (MySQL access interface)</li>
                <li><a href="https://chat.echoplex.us/">Echoplexus</a> (chat and collaborative coding)</li>
                <li><a href="http://www.ecsspert.com/">eCSSpert</a> (CSS demos and experiments)</li>
                <li><a href="http://elm-lang.org/Examples.elm">Elm language examples</a></li>
                <li><a href="http://eloquentjavascript.net/chapter1.html">Eloquent JavaScript</a> (book)</li>
                <li><a href="http://emmet.io">Emmet</a> (fast XML editing)</li>
                <li><a href="https://github.com/espruino/EspruinoWebIDE">Espruino Web IDE</a> (Chrome App for writing code on Espruino devices)</li>
                <li><a href="http://www.fastfig.com/">Fastfig</a> (online computation/math tool)</li>
                <li><a href="https://metacpan.org/module/Farabi">Farabi</a> (modern Perl IDE)</li>
                <li><a href="http://blog.pamelafox.org/2012/02/interactive-html5-slides-with-fathomjs.html">FathomJS integration</a> (slides with editors, again)</li>
                <li><a href="https://phantomus.com/">Phantomus</a> (blogging platform)</li>
                <li><a href="http://fiddlesalad.com/">Fiddle Salad</a> (web development environment)</li>
                <li><a href="https://github.com/simogeo/Filemanager">Filemanager</a></li>
                <li><a href="https://hacks.mozilla.org/2013/11/firefox-developer-tools-episode-27-edit-as-html-codemirror-more/">Firefox Developer Tools</a></li>
                <li><a href="http://www.firepad.io">Firepad</a> (collaborative text editor)</li>
                <li><a href="https://code.google.com/p/gerrit/">Gerrit</a>'s diff view</li>
                <li><a href="https://github.com/maks/git-crx">Git Crx</a> (Chrome App for browsing local git repos)</li>
                <li><a href="http://tour.golang.org">Go language tour</a></li>
                <li><a href="https://github.com/github/android">GitHub's Android app</a></li>
                <li><a href="https://script.google.com/">Google Apps Script</a></li>
                <li><a href="http://web.uvic.ca/~siefkenj/graphit/graphit.html">Graphit</a> (function graphing)</li>
                <li><a href="http://www.handcraft.com/">Handcraft</a> (HTML prototyping)</li>
                <li><a href="http://hawkee.com/">Hawkee</a></li>
                <li><a href="http://try.haxe.org">Haxe</a> (Haxe Playground) </li>
                <li><a href="http://haxpad.com/">HaxPad</a> (editor for Win RT)</li>
                <li><a href="http://megafonweblab.github.com/histone-javascript/">Histone template engine playground</a></li>
                <li><a href="http://www.homegenie.it/docs/automation_getstarted.php">Homegenie</a> (home automation server)</li>
                <li><a href="http://icecoder.net">ICEcoder</a> (web IDE)</li>
                <li><a href="http://ipython.org/">IPython</a> (interactive computing shell)</li>
                <li><a href="http://i-mos.org/imos/">i-MOS</a> (modeling and simulation platform)</li>
                <li><a href="http://www.janvas.com/">Janvas</a> (vector graphics editor)</li>
                <li><a href="http://extensions.joomla.org/extensions/edition/editors/8723">Joomla plugin</a></li>
                <li><a href="http://jqfundamentals.com/">jQuery fundamentals</a> (interactive tutorial)</li>
                <li><a href="http://jsbin.com">jsbin.com</a> (JS playground)</li>
                <li><a href="http://tool.jser.com/preprocessor">JSER preprocessor</a></li>
                <li><a href="https://github.com/kucherenko/jscpd">jscpd</a> (code duplication detector)</li>
                <li><a href="http://jsfiddle.com">jsfiddle.com</a> (another JS playground)</li>
                <li><a href="http://www.jshint.com/">JSHint</a> (JS linter)</li>
                <li><a href="http://jumpseller.com/">Jumpseller</a> (online store builder)</li>
                <li><a href="http://kl1p.com/cmtest/1">kl1p</a> (paste service)</li>
                <li><a href="http://kodtest.com/">Kodtest</a> (HTML/JS/CSS playground)</li>
                <li><a href="http://try.kotlinlang.org">Kotlin</a> (web-based mini-IDE for Kotlin)</li>
                <li><a href="https://laborate.io/">Laborate</a> (collaborative coding)</li>
                <li><a href="http://lighttable.com/">Light Table</a> (experimental IDE)</li>
                <li><a href="http://liveweave.com/">Liveweave</a> (HTML/CSS/JS scratchpad)</li>
                <li><a href="http://marklighteditor.com/">Marklight editor</a> (lightweight markup editor)</li>
                <li><a href="http://www.mergely.com/">Mergely</a> (interactive diffing)</li>
                <li><a href="http://www.iunbug.com/mihtool">MIHTool</a> (iOS web-app debugging tool)</li>
                <li><a href="http://mongo-mapreduce-webbrowser.opensagres.cloudbees.net/">Mongo MapReduce WebBrowser</a></li>
                <li><a href="http://montagestudio.com/">Montage Studio</a> (web app creator suite)</li>
                <li><a href="http://mvcplayground.apphb.com/">MVC Playground</a></li>
                <li><a href="https://www.my2ndgeneration.com/">My2ndGeneration</a> (social coding)</li>
                <li><a href="http://www.navigatecms.com">Navigate CMS</a></li>
                <li><a href="https://github.com/soliton4/nodeMirror">nodeMirror</a> (IDE project)</li>
                <li><a href="https://notex.ch">NoTex</a> (rST authoring)</li>
                <li><a href="http://oakoutliner.com">Oak</a> (online outliner)</li>
                <li><a href="http://clrhome.org/asm/">ORG</a> (z80 assembly IDE)</li>
                <li><a href="https://github.com/mamacdon/orion-codemirror">Orion-CodeMirror integration</a> (running CodeMirror modes in Orion)</li>
                <li><a href="http://paperjs.org/">Paper.js</a> (graphics scripting)</li>
                <li><a href="http://prinbit.com/">PrinBit</a> (collaborative coding tool)</li>
                <li><a href="http://prose.io/">Prose.io</a> (github content editor)</li>
                <li><a href="https://pypi.python.org/pypi/PubliForge/">PubliForge</a> (online publishing system)</li>
                <li><a href="http://www.puzzlescript.net/">Puzzlescript</a> (puzzle game engine)</li>
                <li><a href="http://ql.io/">ql.io</a> (http API query helper)</li>
                <li><a href="http://qyapp.com">QiYun web app platform</a></li>
                <li><a href="http://ariya.ofilabs.com/2011/09/hybrid-webnative-desktop-codemirror.html">Qt+Webkit integration</a> (building a desktop CodeMirror app)</li>
                <li><a href="http://www.quivive-file-manager.com">Quivive File Manager</a></li>
                <li><a href="http://rascalmicro.com/docs/basic-tutorial-getting-started.html">Rascal</a> (tiny computer)</li>
                <li><a href="https://www.realtime.io/">RealTime.io</a> (Internet-of-Things infrastructure)</li>
                <li><a href="https://cloud.sagemath.com/">SageMathCloud</a> (interactive mathematical software environment)</li>
                <li><a href="https://chrome.google.com/webstore/detail/servephp/mnpikomdchjhkhbhmbboehfdjkobbfpo">ServePHP</a> (PHP code testing in Chrome dev tools)</li>
                <li><a href="https://www.shadertoy.com/">Shadertoy</a> (shader sharing)</li>
                <li><a href="http://www.sketchpatch.net/labs/livecodelabIntro.html">sketchPatch Livecodelab</a></li>
                <li><a href="http://www.skulpt.org/">Skulpt</a> (in-browser Python environment)</li>
                <li><a href="http://snaptomato.appspot.com/editor.html">Snap Tomato</a> (HTML editing/testing page)</li>
                <li><a href="http://snippets.pro/">Snippets.pro</a> (code snippet sharing)</li>
                <li><a href="http://www.solidshops.com/">SolidShops</a> (hosted e-commerce platform)</li>
                <li><a href="http://www.cemetech.net/sc/">SourceCoder 3</a> (online calculator IDE and editor)</li>
                <li><a href="http://sqlfiddle.com">SQLFiddle</a> (SQL playground)</li>
                <li><a href="http://www.subte.org/page/programar-ta-te-ti-online/">SubTe</a> (AI bot programming environment)</li>
                <li><a href="http://xuanji.appspot.com/isicp/">Structure and Interpretation of Computer Programs</a>, Interactive Version</li>
                <li><a href="http://syframework.alwaysdata.net">SyBox</a> (PHP playground)</li>
                <li><a href="http://www.tagspaces.org/">TagSpaces</a> (personal data manager)</li>
                <li><a href="https://thefiletree.com">The File Tree</a> (collab editor)</li>
                <li><a href="http://www.mapbox.com/tilemill/">TileMill</a> (map design tool)</li>
                <li><a href="http://doc.tiki.org/Syntax+Highlighter">Tiki</a> (wiki CMS groupware)</li>
                <li><a href="http://www.toolsverse.com/products/data-explorer/">Toolsverse Data Explorer</a> (database management)</li>
                <li><a href="http://enjalot.com/tributary/2636296/sinwaves.js">Tributary</a> (augmented editing)</li>
                <li><a href="http://blog.englard.net/post/39608000629/codeintumblr">Tumblr code highlighting shim</a></li>
                <li><a href="http://turbopy.com/">TurboPY</a> (web publishing framework)</li>
                <li><a href="http://uicod.com/">uiCod</a> (animation demo gallery and sharing)</li>
                <li><a href="http://cruise.eecs.uottawa.ca/umpleonline/">UmpleOnline</a> (model-oriented programming tool)</li>
                <li><a href="https://upsource.jetbrains.com/#idea/view/923f30395f2603cd9f42a32bcafd13b6c28de0ff/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ReplaceAbstractClassInstanceByMapIntention.java">Upsource</a> (code viewer)</li>
                <li><a href="https://github.com/mgaitan/waliki">Waliki</a> (wiki engine)</li>
                <li><a href="http://wamer.net/">Wamer</a> (web application builder)</li>
                <li><a href="https://github.com/brettz9/webappfind">webappfind</a> (windows file bindings for webapps)</li>
                <li><a href="http://www.webglacademy.com/">WebGL academy</a> (learning WebGL)</li>
                <li><a href="http://webglplayground.net/">WebGL playground</a></li>
                <li><a href="https://www.webkit.org/blog/2518/state-of-web-inspector/#source-code">WebKit Web inspector</a></li>
                <li><a href="http://www.wescheme.org/">WeScheme</a> (learning tool)</li>
                <li><a href="https://github.com/b3log/wide">Wide</a> (golang web IDE)</li>
                <li><a href="http://wordpress.org/extend/plugins/codemirror-for-codeeditor/">WordPress plugin</a></li>
                <li><a href="https://www.writelatex.com">writeLaTeX</a> (Collaborative LaTeX Editor)</li>
                <li><a href="http://www.xosystem.org/home/applications_websites/xosystem_website/xoside_EN.php">XOSide</a> (online editor)</li>
                <li><a href="http://videlibri.sourceforge.net/cgi-bin/xidelcgi">XQuery tester</a></li>
                <li><a href="http://q42jaap.github.io/xsd2codemirror/">xsd2codemirror</a> (convert XSD to CM XML completion info)</li>
              </ul>
          
          </article>
          
          
        • releases.html
          <!doctype html>
          
          <title>CodeMirror: Release History</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          <script src="activebookmark.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active data-default="true" href="#v5">Version 5.x</a>
              <li><a href="#v4">Version 4.x</a>
              <li><a href="#v3">Version 3.x</a>
              <li><a href="#v2">Version 2.x</a>
              <li><a href="#v1">Version 0.x</a>
            </ul>
          </div>
          
          <article>
          
          <h2>Release notes and version history</h2>
          
          <section id=v5 class=first>
          
            <h2>Version 5.x</h2>
          
            <p class="rel">20-04-2015: <a href="http://codemirror.net/codemirror-5.2.zip">Version 5.2</a>:</p>
          
            <ul class="rel-note">
              <li>Fix several race conditions
              in <a href="manual.html#addon_show-hint"><code>show-hint</code></a>'s
              asynchronous mode</li>
              <li>Fix backspace binding in <a href="../demo/sublime.html">Sublime bindings</a></li>
              <li>Change the way IME is handled in the <code>"textarea"</code> <a href="manual.html#option_inputStyle">input style</a></li>
              
              <li>New modes: <a href="../mode/mumps/index.html">MUMPS</a>, <a href="../mode/handlebars/index.html">Handlebars</a></li>
              <li>Rewritten modes: <a href="../mode/django/index.html">Django</a>, <a href="../mode/z80/index.html">Z80</a></li>
              <li>New theme: <a href="../demo/theme.html?liquibyte">Liquibyte</a></li>
              <li>New option: <a href="manual.html#option_lineWiseCopyCut"><code>lineWiseCopyCut</code></a></li>
              <li>The <a href="../demo/vim.html">Vim mode</a> now supports buffer-local options and the <code>filetype</code> setting</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/5.1.0...5.2.0">list of patches</a></li>
            </ul>
          
            <p class="rel">23-03-2015: <a href="http://codemirror.net/codemirror-5.1.zip">Version 5.1</a>:</p>
          
            <ul class="rel-note">
              <li>New modes: <a href="../mode/asciiarmor/index.html">ASCII armor</a> (PGP data), <a href="../mode/troff/index.html">Troff</a>, and <a href="../mode/cmake/index.html">CMake</a>.</li>
              <li>Remove SmartyMixed mode, rewrite <a href="../mode/smarty/index.html">Smarty</a> mode to supersede it.</li>
              <li>New commands in the <a href="manual.html#addon_merge">merge
              addon</a>: <code>goNextDiff</code> and <code>goPrevDiff</code>.</li>
              <li>The <a href="manual.html#addon_closebrackets">closebrackets addon</a> can now be configured per mode.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/5.0.0...5.1.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-02-2015: <a href="http://codemirror.net/codemirror-5.0.zip">Version 5.0</a>:</p>
          
            <ul class="rel-note">
              <li>Experimental mobile support (tested on iOS, Android Chrome, stock Android browser)</li>
              <li>New option <a href="manual.html#option_inputStyle"><code>inputStyle</code></a> to switch between hidden textarea and contenteditable input.</li>
              <li>The <a href="manual.html#getInputField"><code>getInputField</code></a>
              method is no longer guaranteed to return a textarea.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.13.0...5.0.0">list of patches</a>.</li>
            </ul>
          
          </section>
          
          <section id=v4 class=first>
          
            <h2>Version 4.x</h2>
          
            <p class="rel">20-02-2015: <a href="http://codemirror.net/codemirror-4.13.zip">Version 4.13</a>:</p>
          
            <ul class="rel-note">
              <li>Fix the way the <a href="../demo/closetag.html"><code>closetag</code></a> demo handles the slash character.</li>
              <li>New modes: <a href="../mode/forth/index.html">Forth</a>, <a href="../mode/stylus/index.html">Stylus</a>.</li>
              <li>Make the <a href="../mode/css/index.html">CSS mode</a> understand some modern CSS extensions.</li>
              <li>Have the <a href="../mode/clike/index.html">Scala mode</a> handle symbols and triple-quoted strings.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.12.0...4.13.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">22-01-2015: <a href="http://codemirror.net/codemirror-4.12.zip">Version 4.12</a>:</p>
          
            <ul class="rel-note">
              <li>The <a href="manual.html#addon_closetag"><code>closetag</code></a>
              addon now defines a <code>"closeTag"</code> command.</li>
              <li>Adds a <code>findModeByFileName</code> to the <a href="manual.html#addon_meta">mode metadata</a>
              addon.</li>
              <li><a href="../demo/simplemode.html">Simple mode</a> rules can
              now contain a <code>sol</code> property to only match at the start
              of a line.</li>
              <li>New
              addon: <a href="manual.html#addon_selection-pointer"><code>selection-pointer</code></a>
              to style the mouse cursor over the selection.</li>
              <li>Improvements to the <a href="../mode/sass/index.html">Sass mode</a>'s indentation.</li>
              <li>The <a href="../demo/vim.html">Vim keymap</a>'s search functionality now
              supports <a href="manual.html#addon_matchesonscrollbar">scrollbar
              annotation</a>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.11.0...4.12.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">9-01-2015: <a href="http://codemirror.net/codemirror-4.11.zip">Version 4.11</a>:</p>
          
            <p class="rel-note">Unfortunately, 4.10 did not take care of the
            Firefox scrolling issue entirely. This release adds two more patches
            to address that.</p>
          
            <p class="rel">29-12-2014: <a href="http://codemirror.net/codemirror-4.10.zip">Version 4.10</a>:</p>
          
            <p class="rel-note">Emergency single-patch update to 4.9. Fixes
            Firefox-specific problem where the cursor could end up behind the
            horizontal scrollbar.</p>
          
            <p class="rel">23-12-2014: <a href="http://codemirror.net/codemirror-4.9.zip">Version 4.9</a>:</p>
          
            <ul class="rel-note">
              <li>Overhauled scroll bar handling.
              Add pluggable <a href="../demo/simplescrollbars.html">scrollbar
              implementations</a>.</li>
              <li>Tweaked behavior for
              the <a href="manual.html#addon_show-hint">completion addons</a> to
              not take text after cursor into account.</li>
              <li>Two new optional features in
              the <a href="manual.html#addon_merge">merge addon</a>: aligning
              editors, and folding unchanged text.</li>
              <li>New
              modes: <a href="../mode/dart/index.html">Dart</a>, <a href="../mode/ebnf/index.html">EBNF</a>, <a href="../mode/spreadsheet/index.html">spreadsheet</a>,
              and <a href="../mode/soy/index.html">Soy</a>.</li>
              <li>New <a href="../demo/panel.html">addon</a> to show persistent panels below/above an editor.</li>
              <li>New themes: <a href="../demo/theme.html?zenburn">zenburn</a>
              and <a href="../demo/theme.html?tomorrow-night-bright">tomorrow night
              bright</a>.</li>
              <li>Allow ctrl-click to clear existing cursors.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.8.0...4.9.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">22-11-2014: <a href="http://codemirror.net/codemirror-4.8.zip">Version 4.8</a>:</p>
          
            <ul class="rel-note">
              <li>Built-in support for <a href="manual.html#normalizeKeyMap">multi-stroke key bindings</a>.</li>
              <li>New method: <a href="manual.html#getLineTokens"><code>getLineTokens</code></a>.</li>
              <li>New modes: <a href="../mode/dockerfile/index.html">dockerfile</a>, <a href="../mode/idl/index.html">IDL</a>, <a href="../mode/clike/index.html">Objective C</a> (crude).</li>
              <li>Support styling of gutter backgrounds, allow <code>"gutter"</code> styles in <a href="manual.html#addLineClass"><code>addLineClass</code></a>.</li>
              <li>Many improvements to the <a href="../demo/vim.html">Vim mode</a>, rewritten visual mode.</li>
              <li>Improvements to modes: <a href="../mode/gfm/index.html">gfm</a> (strikethrough), <a href="../mode/sparql/index.html">SPARQL</a> (version 1.1 support), and <a href="../mode/stex/index.html">sTeX</a> (no more runaway math mode).
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.7.0...4.8.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-10-2014: <a href="http://codemirror.net/codemirror-4.7.zip">Version 4.7</a>:</p>
          
            <ul class="rel-note">
              <li><strong>Incompatible</strong>:
              The <a href="../demo/lint.html">lint addon</a> now passes the
              editor's value as first argument to asynchronous lint functions,
              for consistency. The editor is still passed, as fourth
              argument.</li>
              <li>Improved handling of unicode identifiers in modes for
              languages that support them.</li>
              <li>More mode
              improvements: <a href="../mode/coffeescript/index.html">CoffeeScript</a>
              (indentation), <a href="../mode/verilog/index.html">Verilog</a>
              (indentation), <a href="../mode/clike/index.html">Scala</a>
              (indentation, triple-quoted strings),
              and <a href="../mode/php/index.html">PHP</a> (interpolated
              variables in heredoc strings).</li>
              <li>New modes: <a href="../mode/textile/index.html">Textile</a> and <a href="../mode/tornado/index.html">Tornado templates</a>.</li>
              <li>Experimental new <a href="../demo/simplemode.html">way to define modes</a>.</li>
              <li>Improvements to the <a href="../demo/vim.html">Vim
              bindings</a>: Arbitrary insert mode key mappings are now possible,
              and text objects are supported in visual mode.</li>
              <li>The mode <a href="../mode/meta.js">meta-information file</a>
              now includes information about file extensions,
              and <a href="manual.html#addon_meta">helper
              functions</a> <code>findModeByMIME</code>
              and <code>findModeByExtension</code>.</li>
              <li>New logo!</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.6.0...4.7.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">19-09-2014: <a href="http://codemirror.net/codemirror-4.6.zip">Version 4.6</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/modelica/index.html">Modelica</a></li>
              <li>New method: <a href="manual.html#findWordAt"><code>findWordAt</code></a></li>
              <li>Make it easier to <a href="../demo/markselection.html">use text background styling</a></li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.5.0...4.6.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">21-08-2014: <a href="http://codemirror.net/codemirror-4.5.zip">Version 4.5</a>:</p>
          
            <ul class="rel-note">
              <li>Fix several serious bugs with horizontal scrolling</li>
              <li>New mode: <a href="../mode/slim/index.html">Slim</a></li>
              <li>New command: <a href="manual.html#command_goLineLeftSmart"><code>goLineLeftSmart</code></a></li>
              <li>More fixes and extensions for the <a href="../demo/vim.html">Vim</a> visual block mode</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.4.0...4.5.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">21-07-2014: <a href="http://codemirror.net/codemirror-4.4.zip">Version 4.4</a>:</p>
          
            <ul class="rel-note">
              <li><strong>Note:</strong> Some events might now fire in slightly
              different order (<code>"change"</code> is still guaranteed to fire
              before <code>"cursorActivity"</code>)</li>
              <li>Nested operations in multiple editors are now synced (complete
              at same time, reducing DOM reflows)</li>
              <li>Visual block mode for <a href="../demo/vim.html">vim</a> (&lt;C-v>) is nearly complete</li>
              <li>New mode: <a href="../mode/kotlin/index.html">Kotlin</a></li>
              <li>Better multi-selection paste for text copied from multiple CodeMirror selections</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.3.0...4.4.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">23-06-2014: <a href="http://codemirror.net/codemirror-4.3.zip">Version 4.3</a>:</p>
          
            <ul class="rel-note">
              <li>Several <a href="../demo/vim.html">vim bindings</a>
              improvements: search and exCommand history, global flag
              for <code>:substitute</code>, <code>:global</code> command.
              <li>Allow hiding the cursor by
              setting <a href="manual.html#option_cursorBlinkRate"><code>cursorBlinkRate</code></a>
              to a negative value.</li>
              <li>Make gutter markers themeable, use this in foldgutter.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.2.0...4.3.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">19-05-2014: <a href="http://codemirror.net/codemirror-4.2.zip">Version 4.2</a>:</p>
          
            <ul class="rel-note">
              <li>Fix problem where some modes were broken by the fact that empty tokens were forbidden.</li>
              <li>Several fixes to context menu handling.</li>
              <li>On undo, scroll <em>change</em>, not cursor, into view.</li>
              <li>Rewritten <a href="../mode/jade/index.html">Jade</a> mode.</li>
              <li>Various improvements to <a href="../mode/shell/index.html">Shell</a> (support for more syntax) and <a href="../mode/python/index.html">Python</a> (better indentation) modes.</li>
              <li>New mode: <a href="../mode/cypher/index.html">Cypher</a>.</li>
              <li>New theme: <a href="../demo/theme.html?neo">Neo</a>.</li>
              <li>Support direct styling options (color, line style, width) in the <a href="manual.html#addon_rulers">rulers</a> addon.</li>
              <li>Recognize per-editor configuration for the <a href="manual.html#addon_show-hint">show-hint</a> and <a href="manual.html#addon_foldcode">foldcode</a> addons.</li>
              <li>More intelligent scanning for existing close tags in <a href="manual.html#addon_closetag">closetag</a> addon.</li>
              <li>In the <a href="../demo/vim.html">Vim bindings</a>: Fix bracket matching, support case conversion in visual mode, visual paste, append action.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.1.0...4.2.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">22-04-2014: <a href="http://codemirror.net/codemirror-4.1.zip">Version 4.1</a>:</p>
          
            <ul class="rel-note">
              <li><em>Slightly incompatible</em>:
              The <a href="manual.html#event_cursorActivity"><code>"cursorActivity"</code></a>
              event now fires after all other events for the operation (and only
              for handlers that were actually registered at the time the
              activity happened).</li>
              <li>New command: <a href="manual.html#command_insertSoftTab"><code>insertSoftTab</code></a>.</li>
              <li>New mode: <a href="../mode/django/index.html">Django</a>.</li>
              <li>Improved modes: <a href="../mode/verilog/index.html">Verilog</a> (rewritten), <a href="../mode/jinja2/index.html">Jinja2</a>, <a href="../mode/haxe/index.html">Haxe</a>, <a href="../mode/php/index.html">PHP</a> (string interpolation highlighted), <a href="../mode/javascript/index.html">JavaScript</a> (indentation of trailing else, template strings), <a href="../mode/livescript/index.html">LiveScript</a> (multi-line strings).</li>
              <li>Many small issues from the 3.x→4.x transition were found and fixed.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.0.3...4.1.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-03-2014: <a href="http://codemirror.net/codemirror-4.0.zip">Version 4.0</a>:</p>
          
            <p class="rel-note">This is a new major version of CodeMirror. There
            are a few <strong>incompatible</strong> changes in the API. Upgrade
            with care, and read the <a href="upgrade_v4.html">upgrading
            guide</a>.</p>
          
            <ul class="rel-note">
              <li>Multiple selections (ctrl-click, alt-drag, <a href="manual.html#setSelections">API</a>).</li>
              <li>Sublime Text <a href="../demo/sublime.html">bindings</a>.</li>
              <li><a href="manual.html#modloader">Module loader shims</a> wrapped around all modules.</li>
              <li>Selection <a href="manual.html#command_undoSelection">undo</a>/<a href="manual.html#command_redoSelection">redo</a>.</li>
              <li>Improved character measuring (faster, handles wrapped lines more robustly).</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.23.0...4.0.3">list of patches</a>.</li>
            </ul>
          
          </section>
          
          <section id=v3>
          
            <h2>Version 3.x</h2>
          
            <p class="rel">22-04-2014: <a href="http://codemirror.net/codemirror-3.24.zip">Version 3.24</a>:</p>
          
            <p class="rel-note">Merges the improvements from 4.1 that could
            easily be applied to the 3.x code. Also improves the way the editor
            size is updated when line widgets change.</p>
          
            <p class="rel">20-03-2014: <a href="http://codemirror.net/codemirror-3.23.zip">Version 3.23</a>:</p>
          
            <ul class="rel-note">
              <li>In the <a href="../mode/xml/index.html">XML mode</a>,
              add <code>brackets</code> style to angle brackets, fix
              case-sensitivity of tags for HTML.</li>
              <li>New mode: <a href="../mode/dylan/index.html">Dylan</a>.</li>
              <li>Many improvements to the <a href="../demo/vim.html">Vim bindings</a>.</li>
            </ul>
          
            <p class="rel">21-02-2014: <a href="http://codemirror.net/codemirror-3.22.zip">Version 3.22</a>:</p>
          
            <ul class="rel-note">
              <li>Adds the <a href="manual.html#findMarks"><code>findMarks</code></a> method.</li>
              <li>New addons: <a href="manual.html#addon_rulers">rulers</a>, markdown-fold, yaml-lint.</li>
              <li>New theme: <a href="../demo/theme.html?mdn-like">mdn-like</a>.</li>
              <li>New mode: <a href="../mode/solr/index.html">Solr</a>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.21.0...3.22.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">16-01-2014: <a href="http://codemirror.net/codemirror-3.21.zip">Version 3.21</a>:</p>
          
            <ul class="rel-note">
              <li>Auto-indenting a block will no longer add trailing whitespace to blank lines.</a>
              <li>Marking text has a new option <a href="manual.html#markText"><code>clearWhenEmpty</code></a> to control auto-removal.</li>
              <li>Several bugfixes in the handling of bidirectional text.</li>
              <li>The <a href="../mode/xml/index.html">XML</a> and <a href="../mode/css/index.html">CSS</a> modes were largely rewritten. <a href="../mode/css/less.html">LESS</a> support was added to the CSS mode.</li>
              <li>The OCaml mode was moved to an <a href="../mode/mllike/index.html">mllike</a> mode, F# support added.</li>
              <li>Make it possible to fetch multiple applicable helper values with <a href="manual.html#getHelpers"><code>getHelpers</code></a>, and to register helpers matched on predicates with <a href="manual.html#registerGlobalHelper"><code>registerGlobalHelper</code></a>.</li>
              <li>New theme <a href="../demo/theme.html?pastel-on-dark">pastel-on-dark</a>.</li>
              <li>Better ECMAScript 6 support in <a href="../mode/javascript/index.html">JavaScript</a> mode.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.20.0...3.21.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">21-11-2013: <a href="http://codemirror.net/codemirror-3.20.zip">Version 3.20</a>:</p>
          
            <ul class="rel-note">
              <li>New modes: <a href="../mode/julia/index.html">Julia</a> and <a href="../mode/pegjs/index.html">PEG.js</a>.</li>
              <li>Support ECMAScript 6 in the <a href="../mode/javascript/index.html">JavaScript mode</a>.</li>
              <li>Improved indentation for the <a href="../mode/coffeescript/index.html">CoffeeScript mode</a>.</li>
              <li>Make non-printable-character representation <a href="manual.html#option_specialChars">configurable</a>.</li>
              <li>Add ‘notification’ functionality to <a href="manual.html#addon_dialog">dialog</a> addon.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.19.0...3.20.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">21-10-2013: <a href="http://codemirror.net/codemirror-3.19.zip">Version 3.19</a>:</p>
          
            <ul class="rel-note">
              <li>New modes: <a href="../mode/eiffel/index.html">Eiffel</a>, <a href="../mode/gherkin/index.html">Gherkin</a>, <a href="../mode/sql/?mime=text/x-mssql">MSSQL dialect</a>.</li>
              <li>New addons: <a href="manual.html#addon_hardwrap">hardwrap</a>, <a href="manual.html#addon_sql-hint">sql-hint</a>.</li>
              <li>New theme: <a href="../demo/theme.html?mbo">MBO</a>.</li>
              <li>Add <a href="manual.html#token_style_line">support</a> for line-level styling from mode tokenizers.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.18.0...3.19.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">23-09-2013: <a href="http://codemirror.net/codemirror-3.18.zip">Version 3.18</a>:</p>
          
            <p class="rel-note">Emergency release to fix a problem in 3.17
            where <code>.setOption("lineNumbers", false)</code> would raise an
            error.</p>
          
            <p class="rel">23-09-2013: <a href="http://codemirror.net/codemirror-3.17.zip">Version 3.17</a>:</p>
          
            <ul class="rel-note">
              <li>New modes: <a href="../mode/fortran/index.html">Fortran</a>, <a href="../mode/octave/index.html">Octave</a> (Matlab), <a href="../mode/toml/index.html">TOML</a>, and <a href="../mode/dtd/index.html">DTD</a>.</li>
              <li>New addons: <a href="../addon/lint/css-lint.js"><code>css-lint</code></a>, <a href="manual.html#addon_css-hint"><code>css-hint</code></a>.</li>
              <li>Improve resilience to CSS 'frameworks' that globally mess up <code>box-sizing</code>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.16.0...3.17.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">21-08-2013: <a href="http://codemirror.net/codemirror-3.16.zip">Version 3.16</a>:</p>
          
            <ul class="rel-note">
              <li>The whole codebase is now under a single <a href="../LICENSE">license</a> file.</li>
              <li>The project page was overhauled and redesigned.</li>
              <li>New themes: <a href="../demo/theme.html?paraiso-dark">Paraiso</a> (<a href="../demo/theme.html?paraiso-light">light</a>), <a href="../demo/theme.html?the-matrix">The Matrix</a>.</li>
              <li>Improved interaction between themes and <a href="manual.html#addon_active-line">active-line</a>/<a href="manual.html#addon_matchbrackets">matchbrackets</a> addons.</li>
              <li>New <a href="manual.html#addon_foldcode">folding</a> function <code>CodeMirror.fold.comment</code>.</li>
              <li>Added <a href="manual.html#addon_fullscreen">fullscreen</a> addon.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.15.0...3.16.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">29-07-2013: <a href="http://codemirror.net/codemirror-3.15.zip">Version 3.15</a>:</p>
          
            <ul class="rel-note">
              <li>New modes: <a href="../mode/jade/index.html">Jade</a>, <a href="../mode/nginx/index.html">Nginx</a>.</li>
              <li>New addons: <a href="../demo/tern.html">Tern</a>, <a href="manual.html#addon_matchtags">matchtags</a>, and <a href="manual.html#addon_foldgutter">foldgutter</a>.</li>
              <li>Introduced <a href="manual.html#getHelper"><em>helper</em></a> concept (<a href="https://groups.google.com/forum/#!msg/codemirror/cOc0xvUUEUU/nLrX1-qnidgJ">context</a>).</li>
              <li>New method: <a href="manual.html#getModeAt"><code>getModeAt</code></a>.</li>
              <li>New themes: base16 <a href="../demo/theme.html?base16-dark">dark</a>/<a href="../demo/theme.html?base16-light">light</a>, 3024 <a href="../demo/theme.html?3024-night">dark</a>/<a href="../demo/theme.html?3024-day">light</a>, <a href="../demo/theme.html?tomorrow-night-eighties">tomorrow-night</a>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.14.0...3.15.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-06-2013: <a href="http://codemirror.net/codemirror-3.14.zip">Version 3.14</a>:</p>
          
            <ul class="rel-note">
              <li>New
              addons: <a href="manual.html#addon_trailingspace">trailing
              space highlight</a>, <a href="manual.html#addon_xml-hint">XML
              completion</a> (rewritten),
              and <a href="manual.html#addon_merge">diff merging</a>.</li>
              <li><a href="manual.html#markText"><code>markText</code></a>
              and <a href="manual.html#addLineWidget"><code>addLineWidget</code></a>
              now take a <code>handleMouseEvents</code> option.</li>
              <li>New methods: <a href="manual.html#lineAtHeight"><code>lineAtHeight</code></a>,
              <a href="manual.html#getTokenTypeAt"><code>getTokenTypeAt</code></a>.</li>
              <li>More precise cleanness-tracking
              using <a href="manual.html#changeGeneration"><code>changeGeneration</code></a>
              and <a href="manual.html#isClean"><code>isClean</code></a>.</li>
              <li>Many extensions to <a href="../demo/emacs.html">Emacs</a> mode
              (prefixes, more navigation units, and more).</li>
              <li>New
              events <a href="manual.html#event_keyHandled"><code>"keyHandled"</code></a>
              and <a href="manual.html#event_inputRead"><code>"inputRead"</code></a>.</li>
              <li>Various improvements to <a href="../mode/ruby/index.html">Ruby</a>,
              <a href="../mode/smarty/index.html">Smarty</a>, <a href="../mode/sql/index.html">SQL</a>,
              and <a href="../demo/vim.html">Vim</a> modes.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.13.0...3.14.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-05-2013: <a href="http://codemirror.net/codemirror-3.13.zip">Version 3.13</a>:</p>
          
            <ul class="rel-note">
              <li>New modes: <a href="../mode/cobol/index.html">COBOL</a> and <a href="../mode/haml/index.html">HAML</a>.</li>
              <li>New options: <a href="manual.html#option_cursorScrollMargin"><code>cursorScrollMargin</code></a> and <a href="manual.html#option_coverGutterNextToScrollbar"><code>coverGutterNextToScrollbar</code></a>.</li>
              <li>New addon: <a href="manual.html#addon_comment">commenting</a>.</li>
              <li>More features added to the <a href="../demo/vim.html">Vim keymap</a>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.12...3.13.0">list of patches</a>.</li>
            </ul>
          
            <p class="rel">19-04-2013: <a href="http://codemirror.net/codemirror-3.12.zip">Version 3.12</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/gas/index.html">GNU assembler</a>.</li>
              <li>New
              options: <a href="manual.html#option_maxHighlightLength"><code>maxHighlightLength</code></a>
              and <a href="manual.html#option_historyEventDelay"><code>historyEventDelay</code></a>.</li>
              <li>Added <a href="manual.html#mark_addToHistory"><code>addToHistory</code></a>
              option for <code>markText</code>.</li>
              <li>Various fixes to JavaScript tokenization and indentation corner cases.</li>
              <li>Further improvements to the vim mode.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.11...v3.12">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-03-2013: <a href="http://codemirror.net/codemirror-3.11.zip">Version 3.11</a>:</p>
          
            <ul class="rel-note">
              <li><strong>Removed code:</strong> <code>collapserange</code>,
              <code>formatting</code>, and <code>simple-hint</code>
              addons. <code>plsql</code> and <code>mysql</code> modes
              (use <a href="../mode/sql/index.html"><code>sql</code></a> mode).</li>
              <li><strong>Moved code:</strong> the range-finding functions for folding now have <a href="../addon/fold/">their own files</a>.</li>
              <li><strong>Changed interface:</strong>
              the <a href="manual.html#addon_continuecomment"><code>continuecomment</code></a>
              addon now exposes an option, rather than a command.</li>
              <li>New
              modes: <a href="../mode/css/scss.html">SCSS</a>, <a href="../mode/tcl/index.html">Tcl</a>, <a href="../mode/livescript/index.html">LiveScript</a>,
              and <a href="../mode/mirc/index.html">mIRC</a>.</li>
              <li>New addons: <a href="../demo/placeholder.html"><code>placeholder</code></a>, <a href="../demo/html5complete.html">HTML completion</a>.</li>
              <li>New
              methods: <a href="manual.html#hasFocus"><code>hasFocus</code></a>, <a href="manual.html#defaultCharWidth"><code>defaultCharWidth</code></a>.</li>
              <li>New events: <a href="manual.html#event_beforeCursorEnter"><code>beforeCursorEnter</code></a>, <a href="manual.html#event_renderLine"><code>renderLine</code></a>.</li>
              <li>Many improvements to the <a href="manual.html#addon_show-hint"><code>show-hint</code></a> completion
              dialog addon.</li>
              <li>Tweak behavior of by-word cursor motion.</li>
              <li>Further improvements to the <a href="../demo/vim.html">vim mode</a>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.1...v3.11">list of patches</a>.</li>
            </ul>
          
            <p class="rel">21-02-2013: <a href="http://codemirror.net/codemirror-3.1.zip">Version 3.1</a>:</p>
          
            <ul class="rel-note">
              <li><strong>Incompatible:</strong> key handlers may
              now <em>return</em>, rather
              than <em>throw</em> <code>CodeMirror.Pass</code> to signal they
              didn't handle the key.</li>
              <li>Make documents a <a href="manual.html#api_doc">first-class
              construct</a>, support split views and subviews.</li>
              <li>Add a <a href="manual.html#addon_show-hint">new module</a>
              for showing completion hints.
              Deprecate <code>simple-hint.js</code>.</li>
              <li>Extend <a href="../mode/htmlmixed/index.html">htmlmixed mode</a>
              to allow custom handling of script types.</li>
              <li>Support an <code>insertLeft</code> option
              to <a href="manual.html#setBookmark"><code>setBookmark</code></a>.</li>
              <li>Add an <a href="manual.html#eachLine"><code>eachLine</code></a>
              method to iterate over a document.</li>
              <li>New addon modules: <a href="../demo/markselection.html">selection
              marking</a>, <a href="../demo/lint.html">linting</a>,
              and <a href="../demo/closebrackets.html">automatic bracket
              closing</a>.</li>
              <li>Add <a href="manual.html#event_beforeChange"><code>"beforeChange"</code></a>
              and <a href="manual.html#event_beforeSelectionChange"><code>"beforeSelectionChange"</code></a>
              events.</li>
              <li>Add <a href="manual.html#event_hide"><code>"hide"</code></a>
              and <a href="manual.html#event_unhide"><code>"unhide"</code></a>
              events to marked ranges.</li>
              <li>Fix <a href="manual.html#coordsChar"><code>coordsChar</code></a>'s
              interpretation of its argument to match the documentation.</li>
              <li>New modes: <a href="../mode/turtle/index.html">Turtle</a>
              and <a href="../mode/q/index.html">Q</a>.</li>
              <li>Further improvements to the <a href="../demo/vim.html">vim mode</a>.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.01...v3.1">list of patches</a>.</li>
            </ul>
            
          
            <p class="rel">25-01-2013: <a href="http://codemirror.net/codemirror-3.02.zip">Version 3.02</a>:</p>
          
            <p class="rel-note">Single-bugfix release. Fixes a problem that
            prevents CodeMirror instances from being garbage-collected after
            they become unused.</p>
          
            <p class="rel">21-01-2013: <a href="http://codemirror.net/codemirror-3.01.zip">Version 3.01</a>:</p>
          
            <ul class="rel-note">
              <li>Move all add-ons into an organized directory structure
              under <a href="../addon/"><code>/addon</code></a>. <strong>You might have to adjust your
              paths.</strong></li>
              <li>New
              modes: <a href="../mode/d/index.html">D</a>, <a href="../mode/sass/index.html">Sass</a>, <a href="../mode/apl/index.html">APL</a>, <a href="../mode/sql/index.html">SQL</a>
              (configurable), and <a href="../mode/asterisk/index.html">Asterisk</a>.</li>
              <li>Several bugfixes in right-to-left text support.</li>
              <li>Add <a href="manual.html#option_rtlMoveVisually"><code>rtlMoveVisually</code></a> option.</li>
              <li>Improvements to vim keymap.</li>
              <li>Add built-in (lightweight) <a href="manual.html#addOverlay">overlay mode</a> support.</li>
              <li>Support <code>showIfHidden</code> option for <a href="manual.html#addLineWidget">line widgets</a>.</li>
              <li>Add simple <a href="manual.html#addon_python-hint">Python hinter</a>.</li>
              <li>Bring back the <a href="manual.html#option_fixedGutter"><code>fixedGutter</code></a> option.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0...v3.01">list of patches</a>.</li>
            </ul>
          
            <p class="rel">10-12-2012: <a href="http://codemirror.net/codemirror-3.0.zip">Version 3.0</a>:</p>
          
            <p class="rel-note"><strong>New major version</strong>. Only
            partially backwards-compatible. See
            the <a href="upgrade_v3.html">upgrading guide</a> for more
            information. Changes since release candidate 2:</p>
          
            <ul class="rel-note">
              <li>Rewritten VIM mode.</li>
              <li>Fix a few minor scrolling and sizing issues.</li>
              <li>Work around Safari segfault when dragging.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0rc2...v3.0">list of patches</a>.</li>
            </ul>
            
            <p class="rel">20-11-2012: <a href="http://codemirror.net/codemirror-3.0rc2.zip">Version 3.0, release candidate 2</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/http/index.html">HTTP</a>.</li>
              <li>Improved handling of selection anchor position.</li>
              <li>Improve IE performance on longer lines.</li>
              <li>Reduce gutter glitches during horiz. scrolling.</li>
              <li>Add <a href="manual.html#addKeyMap"><code>addKeyMap</code></a> and <a href="manual.html#removeKeyMap"><code>removeKeyMap</code></a> methods.</li>
              <li>Rewrite <code>formatting</code> and <code>closetag</code> add-ons.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0rc1...v3.0rc2">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-11-2012: <a href="http://codemirror.net/codemirror-3.0rc1.zip">Version 3.0, release candidate 1</a>:</p>
          
            <ul class="rel-note">
              <li>New theme: <a href="../demo/theme.html?solarized%20light">Solarized</a>.</li>
              <li>Introduce <a href="manual.html#addLineClass"><code>addLineClass</code></a>
              and <a href="manual.html#removeLineClass"><code>removeLineClass</code></a>,
              drop <code>setLineClass</code>.</li>
              <li>Add a <em>lot</em> of
              new <a href="manual.html#markText">options for marked text</a>
              (read-only, atomic, collapsed, widget replacement).</li>
              <li>Remove the old code folding interface in favour of these new ranges.</li>
              <li>Add <a href="manual.html#isClean"><code>isClean</code></a>/<a href="manual.html#markClean"><code>markClean</code></a> methods.</li>
              <li>Remove <code>compoundChange</code> method, use better undo-event-combining heuristic.</li>
              <li>Improve scrolling performance smoothness.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0beta2...v3.0rc1">list of patches</a>.</li>
            </ul>
          
            <p class="rel">22-10-2012: <a href="http://codemirror.net/codemirror-3.0beta2.zip">Version 3.0, beta 2</a>:</p>
          
            <ul class="rel-note">
              <li>Fix page-based coordinate computation.</li>
              <li>Fix firing of <a href="manual.html#event_gutterClick"><code>gutterClick</code></a> event.</li>
              <li>Add <a href="manual.html#option_cursorHeight"><code>cursorHeight</code></a> option.</li>
              <li>Fix bi-directional text regression.</li>
              <li>Add <a href="manual.html#option_viewportMargin"><code>viewportMargin</code></a> option.</li>
              <li>Directly handle mousewheel events (again, hopefully better).</li>
              <li>Make vertical cursor movement more robust (through widgets, big line gaps).</li>
              <li>Add <a href="manual.html#option_flattenSpans"><code>flattenSpans</code></a> option.</li>
              <li>Many optimizations. Poor responsiveness should be fixed.</li>
              <li>Initialization in hidden state works again.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0beta1...v3.0beta2">list of patches</a>.</li>
            </ul>
          
            <p class="rel">19-09-2012: <a href="http://codemirror.net/codemirror-3.0beta1.zip">Version 3.0, beta 1</a>:</p>
          
            <ul class="rel-note">
              <li>Bi-directional text support.</li>
              <li>More powerful gutter model.</li>
              <li>Support for arbitrary text/widget height.</li>
              <li>In-line widgets.</li>
              <li>Generalized event handling.</li>
            </ul>
          
          </section>
          
          <section id=v2>
          
            <h2>Version 2.x</h2>
          
            <p class="rel">21-01-2013: <a href="http://codemirror.net/codemirror-2.38.zip">Version 2.38</a>:</p>
          
            <p class="rel-note">Integrate some bugfixes, enhancements to the vim keymap, and new
            modes
            (<a href="../mode/d/index.html">D</a>, <a href="../mode/sass/index.html">Sass</a>, <a href="../mode/apl/index.html">APL</a>)
            from the v3 branch.</p>
          
            <p class="rel">20-12-2012: <a href="http://codemirror.net/codemirror-2.37.zip">Version 2.37</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/sql/index.html">SQL</a> (will replace <a href="../mode/plsql/index.html">plsql</a> and <a href="../mode/mysql/index.html">mysql</a> modes).</li>
              <li>Further work on the new VIM mode.</li>
              <li>Fix Cmd/Ctrl keys on recent Operas on OS X.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v2.36...v2.37">list of patches</a>.</li>
            </ul>
          
            <p class="rel">20-11-2012: <a href="http://codemirror.net/codemirror-2.36.zip">Version 2.36</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/z80/index.html">Z80 assembly</a>.</li>
              <li>New theme: <a href="../demo/theme.html?twilight">Twilight</a>.</li>
              <li>Add command-line compression helper.</li>
              <li>Make <a href="manual.html#scrollIntoView"><code>scrollIntoView</code></a> public.</li>
              <li>Add <a href="manual.html#defaultTextHeight"><code>defaultTextHeight</code></a> method.</li>
              <li>Various extensions to the vim keymap.</li>
              <li>Make <a href="../mode/php/index.html">PHP mode</a> build on <a href="../mode/htmlmixed/index.html">mixed HTML mode</a>.</li>
              <li>Add <a href="manual.html#addon_continuecomment">comment-continuing</a> add-on.</li>
              <li>Full <a href="../https://github.com/codemirror/CodeMirror/compare/v2.35...v2.36">list of patches</a>.</li>
            </ul>
          
            <p class="rel">22-10-2012: <a href="http://codemirror.net/codemirror-2.35.zip">Version 2.35</a>:</p>
          
            <ul class="rel-note">
              <li>New (sub) mode: <a href="../mode/javascript/typescript.html">TypeScript</a>.</li>
              <li>Don't overwrite (insert key) when pasting.</li>
              <li>Fix several bugs in <a href="manual.html#markText"><code>markText</code></a>/undo interaction.</li>
              <li>Better indentation of JavaScript code without semicolons.</li>
              <li>Add <a href="manual.html#defineInitHook"><code>defineInitHook</code></a> function.</li>
              <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v2.34...v2.35">list of patches</a>.</li>
            </ul>
          
            <p class="rel">19-09-2012: <a href="http://codemirror.net/codemirror-2.34.zip">Version 2.34</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/commonlisp/index.html">Common Lisp</a>.</li>
              <li>Fix right-click select-all on most browsers.</li>
              <li>Change the way highlighting happens:<br>&nbsp; Saves memory and CPU cycles.<br>&nbsp; <code>compareStates</code> is no longer needed.<br>&nbsp; <code>onHighlightComplete</code> no longer works.</li>
              <li>Integrate mode (Markdown, XQuery, CSS, sTex) tests in central testsuite.</li>
              <li>Add a <a href="manual.html#version"><code>CodeMirror.version</code></a> property.</li>
              <li>More robust handling of nested modes in <a href="../demo/formatting.html">formatting</a> and <a href="../demo/closetag.html">closetag</a> plug-ins.</li>
              <li>Un/redo now preserves <a href="manual.html#markText">marked text</a> and bookmarks.</li>
              <li><a href="https://github.com/codemirror/CodeMirror/compare/v2.33...v2.34">Full list</a> of patches.</li>
            </ul>
          
            <p class="rel">23-08-2012: <a href="http://codemirror.net/codemirror-2.33.zip">Version 2.33</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/sieve/index.html">Sieve</a>.</li>
              <li>New <a href="manual.html#getViewport"><code>getViewPort</code></a> and <a href="manual.html#option_onViewportChange"><code>onViewportChange</code></a> API.</li>
              <li><a href="manual.html#option_cursorBlinkRate">Configurable</a> cursor blink rate.</li>
              <li>Make binding a key to <code>false</code> disabling handling (again).</li>
              <li>Show non-printing characters as red dots.</li>
              <li>More tweaks to the scrolling model.</li>
              <li>Expanded testsuite. Basic linter added.</li>
              <li>Remove most uses of <code>innerHTML</code>. Remove <code>CodeMirror.htmlEscape</code>.</li>
              <li><a href="https://github.com/codemirror/CodeMirror/compare/v2.32...v2.33">Full list</a> of patches.</li>
            </ul>
          
            <p class="rel">23-07-2012: <a href="http://codemirror.net/codemirror-2.32.zip">Version 2.32</a>:</p>
          
            <p class="rel-note">Emergency fix for a bug where an editor with
            line wrapping on IE will break when there is <em>no</em>
            scrollbar.</p>
          
            <p class="rel">20-07-2012: <a href="http://codemirror.net/codemirror-2.31.zip">Version 2.31</a>:</p>
          
            <ul class="rel-note">
              <li>New modes: <a href="../mode/ocaml/index.html">OCaml</a>, <a href="../mode/haxe/index.html">Haxe</a>, and <a href="../mode/vb/index.html">VB.NET</a>.</li>
              <li>Several fixes to the new scrolling model.</li>
              <li>Add a <a href="manual.html#setSize"><code>setSize</code></a> method for programmatic resizing.</li>
              <li>Add <a href="manual.html#getHistory"><code>getHistory</code></a> and <a href="manual.html#setHistory"><code>setHistory</code></a> methods.</li>
              <li>Allow custom line separator string in <a href="manual.html#getValue"><code>getValue</code></a> and <a href="manual.html#getRange"><code>getRange</code></a>.</li>
              <li>Support double- and triple-click drag, double-clicking whitespace.</li>
              <li>And more... <a href="https://github.com/codemirror/CodeMirror/compare/v2.3...v2.31">(all patches)</a></li>
            </ul>
          
            <p class="rel">22-06-2012: <a href="http://codemirror.net/codemirror-2.3.zip">Version 2.3</a>:</p>
          
            <ul class="rel-note">
              <li><strong>New scrollbar implementation</strong>. Should flicker less. Changes DOM structure of the editor.</li>
              <li>New theme: <a href="../demo/theme.html?vibrant-ink">vibrant-ink</a>.</li>
              <li>Many extensions to the VIM keymap (including text objects).</li>
              <li>Add <a href="../demo/multiplex.html">mode-multiplexing</a> utility script.</li>
              <li>Fix bug where right-click paste works in read-only mode.</li>
              <li>Add a <a href="manual.html#getScrollInfo"><code>getScrollInfo</code></a> method.</li>
              <li>Lots of other <a href="https://github.com/codemirror/CodeMirror/compare/v2.25...v2.3">fixes</a>.</li>
            </ul>
          
            <p class="rel">23-05-2012: <a href="http://codemirror.net/codemirror-2.25.zip">Version 2.25</a>:</p>
          
            <ul class="rel-note">
              <li>New mode: <a href="../mode/erlang/index.html">Erlang</a>.</li>
              <li><strong>Remove xmlpure mode</strong> (use <a href="../mode/xml/index.html">xml.js</a>).</li>
              <li>Fix line-wrapping in Opera.</li>
              <li>Fix X Windows middle-click paste in Chrome.</li>
              <li>Fix bug that broke pasting of huge documents.</li>
              <li>Fix backspace and tab key repeat in Opera.</li>
            </ul>
          
            <p class="rel">23-04-2012: <a href="http://codemirror.net/codemirror-2.24.zip">Version 2.24</a>:</p>
          
            <ul class="rel-note">
              <li><strong>Drop support for Internet Explorer 6</strong>.</li>
              <li>New
              modes: <a href="../mode/shell/index.html">Shell</a>, <a href="../mode/tiki/index.html">Tiki
              wiki</a>, <a href="../mode/pig/index.html">Pig Latin</a>.</li>
              <li>New themes: <a href="../demo/theme.html?ambiance">Ambiance</a>, <a href="../demo/theme.html?blackboard">Blackboard</a>.</li>
              <li>More control over drag/drop
              with <a href="manual.html#option_dragDrop"><code>dragDrop</code></a>
              and <a href="manual.html#option_onDragEvent"><code>onDragEvent</code></a>
              options.</li>
              <li>Make HTML mode a bit less pedantic.</li>
              <li>Add <a href="manual.html#compoundChange"><code>compoundChange</code></a> API method.</li>
              <li>Several fixes in undo history and line hiding.</li>
              <li>Remove (broken) support for <code>catchall</code> in key maps,
              add <code>nofallthrough</code> boolean field instead.</li>
            </ul>
          
            <p class="rel">26-03-2012: <a href="http://codemirror.net/codemirror-2.23.zip">Version 2.23</a>:</p>
          
            <ul class="rel-note">
              <li>Change <strong>default binding for tab</strong> <a href="javascript:void(document.getElementById('tabbinding').style.display='')">[more]</a>
                <div style="display: none" id=tabbinding>
                  Starting in 2.23, these bindings are default:
                  <ul><li>Tab: Insert tab character</li>
                    <li>Shift-tab: Reset line indentation to default</li>
                    <li>Ctrl/Cmd-[: Reduce line indentation (old tab behaviour)</li>
                    <li>Ctrl/Cmd-]: Increase line indentation (old shift-tab behaviour)</li>
                  </ul>
                </div>
              </li>
              <li>New modes: <a href="../mode/xquery/index.html">XQuery</a> and <a href="../mode/vbscript/index.html">VBScript</a>.</li>
              <li>Two new themes: <a href="../mode/less/index.html">lesser-dark</a> and <a href="../mode/xquery/index.html">xq-dark</a>.</li>
              <li>Differentiate between background and text styles in <a href="manual.html#setLineClass"><code>setLineClass</code></a>.</li>
              <li>Fix drag-and-drop in IE9+.</li>
              <li>Extend <a href="manual.html#charCoords"><code>charCoords</code></a>
              and <a href="manual.html#cursorCoords"><code>cursorCoords</code></a> with a <code>mode</code> argument.</li>
              <li>Add <a href="manual.html#option_autofocus"><code>autofocus</code></a> option.</li>
              <li>Add <a href="manual.html#findMarksAt"><code>findMarksAt</code></a> method.</li>
            </ul>
          
            <p class="rel">27-02-2012: <a href="http://codemirror.net/codemirror-2.22.zip">Version 2.22</a>:</p>
          
            <ul class="rel-note">
              <li>Allow <a href="manual.html#keymaps">key handlers</a> to pass up events, allow binding characters.</li>
              <li>Add <a href="manual.html#option_autoClearEmptyLines"><code>autoClearEmptyLines</code></a> option.</li>
              <li>Properly use tab stops when rendering tabs.</li>
              <li>Make PHP mode more robust.</li>
              <li>Support indentation blocks in <a href="manual.html#addon_foldcode">code folder</a>.</li>
              <li>Add a script for <a href="manual.html#addon_match-highlighter">highlighting instances of the selection</a>.</li>
              <li>New <a href="../mode/properties/index.html">.properties</a> mode.</li>
              <li>Fix many bugs.</li>
            </ul>
          
            <p class="rel">27-01-2012: <a href="http://codemirror.net/codemirror-2.21.zip">Version 2.21</a>:</p>
          
            <ul class="rel-note">
              <li>Added <a href="../mode/less/index.html">LESS</a>, <a href="../mode/mysql/index.html">MySQL</a>,
              <a href="../mode/go/index.html">Go</a>, and <a href="../mode/verilog/index.html">Verilog</a> modes.</li>
              <li>Add <a href="manual.html#option_smartIndent"><code>smartIndent</code></a>
              option.</li>
              <li>Support a cursor in <a href="manual.html#option_readOnly"><code>readOnly</code></a>-mode.</li>
              <li>Support assigning multiple styles to a token.</li>
              <li>Use a new approach to drawing the selection.</li>
              <li>Add <a href="manual.html#scrollTo"><code>scrollTo</code></a> method.</li>
              <li>Allow undo/redo events to span non-adjacent lines.</li>
              <li>Lots and lots of bugfixes.</li>
            </ul>
          
            <p class="rel">20-12-2011: <a href="http://codemirror.net/codemirror-2.2.zip">Version 2.2</a>:</p>
          
            <ul class="rel-note">
              <li>Slightly incompatible API changes. Read <a href="upgrade_v2.2.html">this</a>.</li>
              <li>New approach
              to <a href="manual.html#option_extraKeys">binding</a> keys,
              support for <a href="manual.html#option_keyMap">custom
              bindings</a>.</li>
              <li>Support for overwrite (insert).</li>
              <li><a href="manual.html#option_tabSize">Custom-width</a>
              and <a href="../demo/visibletabs.html">stylable</a> tabs.</li>
              <li>Moved more code into <a href="manual.html#addons">add-on scripts</a>.</li>
              <li>Support for sane vertical cursor movement in wrapped lines.</li>
              <li>More reliable handling of
              editing <a href="manual.html#markText">marked text</a>.</li>
              <li>Add minimal <a href="../demo/emacs.html">emacs</a>
              and <a href="../demo/vim.html">vim</a> bindings.</li>
              <li>Rename <code>coordsFromIndex</code>
              to <a href="manual.html#posFromIndex"><code>posFromIndex</code></a>,
              add <a href="manual.html#indexFromPos"><code>indexFromPos</code></a>
              method.</li>
            </ul>
          
            <p class="rel">21-11-2011: <a href="http://codemirror.net/codemirror-2.18.zip">Version 2.18</a>:</p>
            <p class="rel-note">Fixes <code>TextMarker.clear</code>, which is broken in 2.17.</p>
          
            <p class="rel">21-11-2011: <a href="http://codemirror.net/codemirror-2.17.zip">Version 2.17</a>:</p>
            <ul class="rel-note">
              <li>Add support for <a href="manual.html#option_lineWrapping">line
              wrapping</a> and <a href="manual.html#hideLine">code
              folding</a>.</li>
              <li>Add <a href="../mode/gfm/index.html">Github-style Markdown</a> mode.</li>
              <li>Add <a href="../theme/monokai.css">Monokai</a>
              and <a href="../theme/rubyblue.css">Rubyblue</a> themes.</li>
              <li>Add <a href="manual.html#setBookmark"><code>setBookmark</code></a> method.</li>
              <li>Move some of the demo code into reusable components
              under <a href="../addon/"><code>lib/util</code></a>.</li>
              <li>Make screen-coord-finding code faster and more reliable.</li>
              <li>Fix drag-and-drop in Firefox.</li>
              <li>Improve support for IME.</li>
              <li>Speed up content rendering.</li>
              <li>Fix browser's built-in search in Webkit.</li>
              <li>Make double- and triple-click work in IE.</li>
              <li>Various fixes to modes.</li>
            </ul>
          
            <p class="rel">27-10-2011: <a href="http://codemirror.net/codemirror-2.16.zip">Version 2.16</a>:</p>
            <ul class="rel-note">
              <li>Add <a href="../mode/perl/index.html">Perl</a>, <a href="../mode/rust/index.html">Rust</a>, <a href="../mode/tiddlywiki/index.html">TiddlyWiki</a>, and <a href="../mode/groovy/index.html">Groovy</a> modes.</li>
              <li>Dragging text inside the editor now moves, rather than copies.</li>
              <li>Add a <a href="manual.html#coordsFromIndex"><code>coordsFromIndex</code></a> method.</li>
              <li><strong>API change</strong>: <code>setValue</code> now no longer clears history. Use <a href="manual.html#clearHistory"><code>clearHistory</code></a> for that.</li>
              <li><strong>API change</strong>: <a href="manual.html#markText"><code>markText</code></a> now
              returns an object with <code>clear</code> and <code>find</code>
              methods. Marked text is now more robust when edited.</li>
              <li>Fix editing code with tabs in Internet Explorer.</li>
            </ul>
          
            <p class="rel">26-09-2011: <a href="http://codemirror.net/codemirror-2.15.zip">Version 2.15</a>:</p>
            <p class="rel-note">Fix bug that snuck into 2.14: Clicking the
            character that currently has the cursor didn't re-focus the
            editor.</p>
          
            <p class="rel">26-09-2011: <a href="http://codemirror.net/codemirror-2.14.zip">Version 2.14</a>:</p>
            <ul class="rel-note">
              <li>Add <a href="../mode/clojure/index.html">Clojure</a>, <a href="../mode/pascal/index.html">Pascal</a>, <a href="../mode/ntriples/index.html">NTriples</a>, <a href="../mode/jinja2/index.html">Jinja2</a>, and <a href="../mode/markdown/index.html">Markdown</a> modes.</li>
              <li>Add <a href="../theme/cobalt.css">Cobalt</a> and <a href="../theme/eclipse.css">Eclipse</a> themes.</li>
              <li>Add a <a href="manual.html#option_fixedGutter"><code>fixedGutter</code></a> option.</li>
              <li>Fix bug with <code>setValue</code> breaking cursor movement.</li>
              <li>Make gutter updates much more efficient.</li>
              <li>Allow dragging of text out of the editor (on modern browsers).</li>
            </ul>
          
          
            <p class="rel">23-08-2011: <a href="http://codemirror.net/codemirror-2.13.zip">Version 2.13</a>:</p>
            <ul class="rel-note">
              <li>Add <a href="../mode/ruby/index.html">Ruby</a>, <a href="../mode/r/index.html">R</a>, <a href="../mode/coffeescript/index.html">CoffeeScript</a>, and <a href="../mode/velocity/index.html">Velocity</a> modes.</li>
              <li>Add <a href="manual.html#getGutterElement"><code>getGutterElement</code></a> to API.</li>
              <li>Several fixes to scrolling and positioning.</li>
              <li>Add <a href="manual.html#option_smartHome"><code>smartHome</code></a> option.</li>
              <li>Add an experimental <a href="../mode/xmlpure/index.html">pure XML</a> mode.</li>
            </ul>
          
            <p class="rel">25-07-2011: <a href="http://codemirror.net/codemirror-2.12.zip">Version 2.12</a>:</p>
            <ul class="rel-note">
              <li>Add a <a href="../mode/sparql/index.html">SPARQL</a> mode.</li>
              <li>Fix bug with cursor jumping around in an unfocused editor in IE.</li>
              <li>Allow key and mouse events to bubble out of the editor. Ignore widget clicks.</li>
              <li>Solve cursor flakiness after undo/redo.</li>
              <li>Fix block-reindent ignoring the last few lines.</li>
              <li>Fix parsing of multi-line attrs in XML mode.</li>
              <li>Use <code>innerHTML</code> for HTML-escaping.</li>
              <li>Some fixes to indentation in C-like mode.</li>
              <li>Shrink horiz scrollbars when long lines removed.</li>
              <li>Fix width feedback loop bug that caused the width of an inner DIV to shrink.</li>
            </ul>
          
            <p class="rel">04-07-2011: <a href="http://codemirror.net/codemirror-2.11.zip">Version 2.11</a>:</p>
            <ul class="rel-note">
              <li>Add a <a href="../mode/scheme/index.html">Scheme mode</a>.</li>
              <li>Add a <code>replace</code> method to search cursors, for cursor-preserving replacements.</li>
              <li>Make the <a href="../mode/clike/index.html">C-like mode</a> mode more customizable.</li>
              <li>Update XML mode to spot mismatched tags.</li>
              <li>Add <code>getStateAfter</code> API and <code>compareState</code> mode API methods for finer-grained mode magic.</li>
              <li>Add a <code>getScrollerElement</code> API method to manipulate the scrolling DIV.</li>
              <li>Fix drag-and-drop for Firefox.</li>
              <li>Add a C# configuration for the <a href="../mode/clike/index.html">C-like mode</a>.</li>
              <li>Add <a href="../demo/fullscreen.html">full-screen editing</a> and <a href="../demo/changemode.html">mode-changing</a> demos.</li>
            </ul>
          
            <p class="rel">07-06-2011: <a href="http://codemirror.net/codemirror-2.1.zip">Version 2.1</a>:</p>
            <p class="rel-note">Add
            a <a href="manual.html#option_theme">theme</a> system
            (<a href="../demo/theme.html">demo</a>). Note that this is not
            backwards-compatible—you'll have to update your styles and
            modes!</p>
          
            <p class="rel">07-06-2011: <a href="http://codemirror.net/codemirror-2.02.zip">Version 2.02</a>:</p>
            <ul class="rel-note">
              <li>Add a <a href="../mode/lua/index.html">Lua mode</a>.</li>
              <li>Fix reverse-searching for a regexp.</li>
              <li>Empty lines can no longer break highlighting.</li>
              <li>Rework scrolling model (the outer wrapper no longer does the scrolling).</li>
              <li>Solve horizontal jittering on long lines.</li>
              <li>Add <a href="../demo/runmode.html">runmode.js</a>.</li>
              <li>Immediately re-highlight text when typing.</li>
              <li>Fix problem with 'sticking' horizontal scrollbar.</li>
            </ul>
          
            <p class="rel">26-05-2011: <a href="http://codemirror.net/codemirror-2.01.zip">Version 2.01</a>:</p>
            <ul class="rel-note">
              <li>Add a <a href="../mode/smalltalk/index.html">Smalltalk mode</a>.</li>
              <li>Add a <a href="../mode/rst/index.html">reStructuredText mode</a>.</li>
              <li>Add a <a href="../mode/python/index.html">Python mode</a>.</li>
              <li>Add a <a href="../mode/plsql/index.html">PL/SQL mode</a>.</li>
              <li><code>coordsChar</code> now works</li>
              <li>Fix a problem where <code>onCursorActivity</code> interfered with <code>onChange</code>.</li>
              <li>Fix a number of scrolling and mouse-click-position glitches.</li>
              <li>Pass information about the changed lines to <code>onChange</code>.</li>
              <li>Support cmd-up/down on OS X.</li>
              <li>Add triple-click line selection.</li>
              <li>Don't handle shift when changing the selection through the API.</li>
              <li>Support <code>"nocursor"</code> mode for <code>readOnly</code> option.</li>
              <li>Add an <code>onHighlightComplete</code> option.</li>
              <li>Fix the context menu for Firefox.</li>
            </ul>
          
            <p class="rel">28-03-2011: <a href="http://codemirror.net/codemirror-2.0.zip">Version 2.0</a>:</p>
            <p class="rel-note">CodeMirror 2 is a complete rewrite that's
            faster, smaller, simpler to use, and less dependent on browser
            quirks. See <a href="internals.html">this</a>
            and <a href="http://groups.google.com/group/codemirror/browse_thread/thread/5a8e894024a9f580">this</a>
            for more information.</p>
          
            <p class="rel">22-02-2011: <a href="https://github.com/codemirror/codemirror/tree/beta2">Version 2.0 beta 2</a>:</p>
            <p class="rel-note">Somewhat more mature API, lots of bugs shaken out.</p>
          
            <p class="rel">17-02-2011: <a href="http://codemirror.net/codemirror-0.94.zip">Version 0.94</a>:</p>
            <ul class="rel-note">
              <li><code>tabMode: "spaces"</code> was modified slightly (now indents when something is selected).</li>
              <li>Fixes a bug that would cause the selection code to break on some IE versions.</li>
              <li>Disabling spell-check on WebKit browsers now works.</li>
            </ul>
          
            <p class="rel">08-02-2011: <a href="http://codemirror.net/">Version 2.0 beta 1</a>:</p>
            <p class="rel-note">CodeMirror 2 is a complete rewrite of
            CodeMirror, no longer depending on an editable frame.</p>
          
            <p class="rel">19-01-2011: <a href="http://codemirror.net/codemirror-0.93.zip">Version 0.93</a>:</p>
            <ul class="rel-note">
              <li>Added a <a href="contrib/regex/index.html">Regular Expression</a> parser.</li>
              <li>Fixes to the PHP parser.</li>
              <li>Support for regular expression in search/replace.</li>
              <li>Add <code>save</code> method to instances created with <code>fromTextArea</code>.</li>
              <li>Add support for MS T-SQL in the SQL parser.</li>
              <li>Support use of CSS classes for highlighting brackets.</li>
              <li>Fix yet another hang with line-numbering in hidden editors.</li>
            </ul>
          </section>
          
          <section id=v1>
          
            <h2>Version 0.x</h2>
          
            <p class="rel">28-03-2011: <a href="http://codemirror.net/codemirror-1.0.zip">Version 1.0</a>:</p>
            <ul class="rel-note">
              <li>Fix error when debug history overflows.</li>
              <li>Refine handling of C# verbatim strings.</li>
              <li>Fix some issues with JavaScript indentation.</li>
            </ul>
          
            <p class="rel">17-12-2010: <a href="http://codemirror.net/codemirror-0.92.zip">Version 0.92</a>:</p>
            <ul class="rel-note">
              <li>Make CodeMirror work in XHTML documents.</li>
              <li>Fix bug in handling of backslashes in Python strings.</li>
              <li>The <code>styleNumbers</code> option is now officially
              supported and documented.</li>
              <li><code>onLineNumberClick</code> option added.</li>
              <li>More consistent names <code>onLoad</code> and
              <code>onCursorActivity</code> callbacks. Old names still work, but
              are deprecated.</li>
              <li>Add a <a href="contrib/freemarker/index.html">Freemarker</a> mode.</li>
            </ul>
          
            <p class="rel">11-11-2010: <a
            href="http://codemirror.net/codemirror-0.91.zip">Version 0.91</a>:</p>
            <ul class="rel-note">
              <li>Adds support for <a href="contrib/java">Java</a>.</li>
              <li>Small additions to the <a href="contrib/php">PHP</a> and <a href="contrib/sql">SQL</a> parsers.</li>
              <li>Work around various <a href="https://bugs.webkit.org/show_bug.cgi?id=47806">Webkit</a> <a href="https://bugs.webkit.org/show_bug.cgi?id=23474">issues</a>.</li>
              <li>Fix <code>toTextArea</code> to update the code in the textarea.</li>
              <li>Add a <code>noScriptCaching</code> option (hack to ease development).</li>
              <li>Make sub-modes of <a href="mixedtest.html">HTML mixed</a> mode configurable.</li>
            </ul>
          
            <p class="rel">02-10-2010: <a
            href="http://codemirror.net/codemirror-0.9.zip">Version 0.9</a>:</p>
            <ul class="rel-note">
              <li>Add support for searching backwards.</li>
              <li>There are now parsers for <a href="contrib/scheme/index.html">Scheme</a>, <a href="contrib/xquery/index.html">XQuery</a>, and <a href="contrib/ometa/index.html">OmetaJS</a>.</li>
              <li>Makes <code>height: "dynamic"</code> more robust.</li>
              <li>Fixes bug where paste did not work on OS X.</li>
              <li>Add a <code>enterMode</code> and <code>electricChars</code> options to make indentation even more customizable.</li>
              <li>Add <code>firstLineNumber</code> option.</li>
              <li>Fix bad handling of <code>@media</code> rules by the CSS parser.</li>
              <li>Take a new, more robust approach to working around the invisible-last-line bug in WebKit.</li>
            </ul>
          
            <p class="rel">22-07-2010: <a
            href="http://codemirror.net/codemirror-0.8.zip">Version 0.8</a>:</p>
            <ul class="rel-note">
              <li>Add a <code>cursorCoords</code> method to find the screen
              coordinates of the cursor.</li>
              <li>A number of fixes and support for more syntax in the PHP parser.</li>
              <li>Fix indentation problem with JSON-mode JS parser in Webkit.</li>
              <li>Add a <a href="compress.html">minification</a> UI.</li>
              <li>Support a <code>height: dynamic</code> mode, where the editor's
              height will adjust to the size of its content.</li>
              <li>Better support for IME input mode.</li>
              <li>Fix JavaScript parser getting confused when seeing a no-argument
              function call.</li>
              <li>Have CSS parser see the difference between selectors and other
              identifiers.</li>
              <li>Fix scrolling bug when pasting in a horizontally-scrolled
              editor.</li>
              <li>Support <code>toTextArea</code> method in instances created with
              <code>fromTextArea</code>.</li>
              <li>Work around new Opera cursor bug that causes the cursor to jump
              when pressing backspace at the end of a line.</li>
            </ul>
          
            <p class="rel">27-04-2010: <a
            href="http://codemirror.net/codemirror-0.67.zip">Version
            0.67</a>:</p>
            <p class="rel-note">More consistent page-up/page-down behaviour
            across browsers. Fix some issues with hidden editors looping forever
            when line-numbers were enabled. Make PHP parser parse
            <code>"\\"</code> correctly. Have <code>jumpToLine</code> work on
            line handles, and add <code>cursorLine</code> function to fetch the
            line handle where the cursor currently is. Add new
            <code>setStylesheet</code> function to switch style-sheets in a
            running editor.</p>
          
            <p class="rel">01-03-2010: <a
            href="http://codemirror.net/codemirror-0.66.zip">Version
            0.66</a>:</p>
            <p class="rel-note">Adds <code>removeLine</code> method to API.
            Introduces the <a href="contrib/plsql/index.html">PLSQL parser</a>.
            Marks XML errors by adding (rather than replacing) a CSS class, so
            that they can be disabled by modifying their style. Fixes several
            selection bugs, and a number of small glitches.</p>
          
            <p class="rel">12-11-2009: <a
            href="http://codemirror.net/codemirror-0.65.zip">Version
            0.65</a>:</p>
            <p class="rel-note">Add support for having both line-wrapping and
            line-numbers turned on, make paren-highlighting style customisable
            (<code>markParen</code> and <code>unmarkParen</code> config
            options), work around a selection bug that Opera
            <em>re</em>introduced in version 10.</p>
          
            <p class="rel">23-10-2009: <a
            href="http://codemirror.net/codemirror-0.64.zip">Version
            0.64</a>:</p>
            <p class="rel-note">Solves some issues introduced by the
            paste-handling changes from the previous release. Adds
            <code>setSpellcheck</code>, <code>setTextWrapping</code>,
            <code>setIndentUnit</code>, <code>setUndoDepth</code>,
            <code>setTabMode</code>, and <code>setLineNumbers</code> to
            customise a running editor. Introduces an <a
            href="contrib/sql/index.html">SQL</a> parser. Fixes a few small
            problems in the <a href="contrib/python/index.html">Python</a>
            parser. And, as usual, add workarounds for various newly discovered
            browser incompatibilities.</p>
          
            <p class="rel">31-08-2009: <a href="http://codemirror.net/codemirror-0.63.zip">Version 0.63</a>:</p>
            <p class="rel-note"> Overhaul of paste-handling (less fragile), fixes for several
            serious IE8 issues (cursor jumping, end-of-document bugs) and a number
            of small problems.</p>
          
            <p class="rel">30-05-2009: <a href="http://codemirror.net/codemirror-0.62.zip">Version 0.62</a>:</p>
            <p class="rel-note">Introduces <a href="contrib/python/index.html">Python</a>
            and <a href="contrib/lua/index.html">Lua</a> parsers. Add
            <code>setParser</code> (on-the-fly mode changing) and
            <code>clearHistory</code> methods. Make parsing passes time-based
            instead of lines-based (see the <code>passTime</code> option).</p>
          
          </section>
          </article>
          
        • reporting.html
          <!doctype html>
          
          <title>CodeMirror: Reporting Bugs</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Reporting bugs</a>
            </ul>
          </div>
          
          <article>
          
          <h2>Reporting bugs effectively</h2>
          
          <div class="left">
          
          <p>So you found a problem in CodeMirror. By all means, report it! Bug
          reports from users are the main drive behind improvements to
          CodeMirror. But first, please read over these points:</p>
          
          <ol>
            <li>CodeMirror is maintained by volunteers. They don't owe you
            anything, so be polite. Reports with an indignant or belligerent
            tone tend to be moved to the bottom of the pile.</li>
          
            <li>Include information about <strong>the browser in which the
            problem occurred</strong>. Even if you tested several browsers, and
            the problem occurred in all of them, mention this fact in the bug
            report. Also include browser version numbers and the operating
            system that you're on.</li>
          
            <li>Mention which release of CodeMirror you're using. Preferably,
            try also with the current development snapshot, to ensure the
            problem has not already been fixed.</li>
          
            <li>Mention very precisely what went wrong. "X is broken" is not a
            good bug report. What did you expect to happen? What happened
            instead? Describe the exact steps a maintainer has to take to make
            the problem occur. We can not fix something that we can not
            observe.</li>
          
            <li>If the problem can not be reproduced in any of the demos
            included in the CodeMirror distribution, please provide an HTML
            document that demonstrates the problem. The best way to do this is
            to go to <a href="http://jsbin.com/ihunin/1/edit">jsbin.com</a>, enter
            it there, press save, and include the resulting link in your bug
            report.</li>
          </ol>
          
          </div>
          
          </article>
          
        • upgrade_v2.2.html
          <!doctype html>
          
          <title>CodeMirror: Version 2.2 upgrade guide</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">2.2 upgrade guide</a>
            </ul>
          </div>
          
          <article>
          
          <h2>Upgrading to v2.2</h2>
          
          <p>There are a few things in the 2.2 release that require some care
          when upgrading.</p>
          
          <h3>No more default.css</h3>
          
          <p>The default theme is now included
          in <a href="../lib/codemirror.css"><code>codemirror.css</code></a>, so
          you do not have to included it separately anymore. (It was tiny, so
          even if you're not using it, the extra data overhead is negligible.)
          
          <h3>Different key customization</h3>
          
          <p>CodeMirror has moved to a system
          where <a href="manual.html#option_keyMap">keymaps</a> are used to
          bind behavior to keys. This means <a href="../demo/emacs.html">custom
          bindings</a> are now possible.</p>
          
          <p>Three options that influenced key
          behavior, <code>tabMode</code>, <code>enterMode</code>,
          and <code>smartHome</code>, are no longer supported. Instead, you can
          provide custom bindings to influence the way these keys act. This is
          done through the
          new <a href="manual.html#option_extraKeys"><code>extraKeys</code></a>
          option, which can hold an object mapping key names to functionality. A
          simple example would be:</p>
          
          <pre>  extraKeys: {
              "Ctrl-S": function(instance) { saveText(instance.getValue()); },
              "Ctrl-/": "undo"
            }</pre>
          
          <p>Keys can be mapped either to functions, which will be given the
          editor instance as argument, or to strings, which are mapped through
          functions through the <code>CodeMirror.commands</code> table, which
          contains all the built-in editing commands, and can be inspected and
          extended by external code.</p>
          
          <p>By default, the <code>Home</code> key is bound to
          the <code>"goLineStartSmart"</code> command, which moves the cursor to
          the first non-whitespace character on the line. You can set do this to
          make it always go to the very start instead:</p>
          
          <pre>  extraKeys: {"Home": "goLineStart"}</pre>
          
          <p>Similarly, <code>Enter</code> is bound
          to <code>"newlineAndIndent"</code> by default. You can bind it to
          something else to get different behavior. To disable special handling
          completely and only get a newline character inserted, you can bind it
          to <code>false</code>:</p>
          
          <pre>  extraKeys: {"Enter": false}</pre>
          
          <p>The same works for <code>Tab</code>. If you don't want CodeMirror
          to handle it, bind it to <code>false</code>. The default behaviour is
          to indent the current line more (<code>"indentMore"</code> command),
          and indent it less when shift is held (<code>"indentLess"</code>).
          There are also <code>"indentAuto"</code> (smart indent)
          and <code>"insertTab"</code> commands provided for alternate
          behaviors. Or you can write your own handler function to do something
          different altogether.</p>
          
          <h3>Tabs</h3>
          
          <p>Handling of tabs changed completely. The display width of tabs can
          now be set with the <code>tabSize</code> option, and tabs can
          be <a href="../demo/visibletabs.html">styled</a> by setting CSS rules
          for the <code>cm-tab</code> class.</p>
          
          <p>The default width for tabs is now 4, as opposed to the 8 that is
          hard-wired into browsers. If you are relying on 8-space tabs, make
          sure you explicitly set <code>tabSize: 8</code> in your options.</p>
          
          </article>
          
        • upgrade_v3.html
          <!doctype html>
          
          <title>CodeMirror: Version 3 upgrade guide</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          <script src="../lib/codemirror.js"></script>
          <link rel="stylesheet" href="../lib/codemirror.css">
          <script src="../addon/runmode/runmode.js"></script>
          <script src="../addon/runmode/colorize.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../mode/css/css.js"></script>
          <script src="../mode/htmlmixed/htmlmixed.js"></script>
          <script src="activebookmark.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#upgrade">Upgrade guide</a>
              <li><a href="#dom">DOM structure</a></li>
              <li><a href="#gutters">Gutter model</a></li>
              <li><a href="#events">Event handling</a></li>
              <li><a href="#marktext">markText method arguments</a></li>
              <li><a href="#folding">Line folding</a></li>
              <li><a href="#lineclass">Line CSS classes</a></li>
              <li><a href="#positions">Position properties</a></li>
              <li><a href="#matchbrackets">Bracket matching</a></li>
              <li><a href="#modes">Mode management</a></li>
              <li><a href="#new">New features</a></li>
            </ul>
          </div>
          
          <article>
          
          <h2 id=upgrade>Upgrading to version 3</h2>
          
          <p>Version 3 does not depart too much from 2.x API, and sites that use
          CodeMirror in a very simple way might be able to upgrade without
          trouble. But it does introduce a number of incompatibilities. Please
          at least skim this text before upgrading.</p>
          
          <p>Note that <strong>version 3 drops full support for Internet
          Explorer 7</strong>. The editor will mostly work on that browser, but
          it'll be significantly glitchy.</p>
          
          <section id=dom>
            <h2>DOM structure</h2>
          
          <p>This one is the most likely to cause problems. The internal
          structure of the editor has changed quite a lot, mostly to implement a
          new scrolling model.</p>
          
          <p>Editor height is now set on the outer wrapper element (CSS
          class <code>CodeMirror</code>), not on the scroller element
          (<code>CodeMirror-scroll</code>).</p>
          
          <p>Other nodes were moved, dropped, and added. If you have any code
          that makes assumptions about the internal DOM structure of the editor,
          you'll have to re-test it and probably update it to work with v3.</p>
          
          <p>See the <a href="manual.html#styling">styling section</a> of the
          manual for more information.</p>
          </section>
          <section id=gutters>
            <h2>Gutter model</h2>
          
          <p>In CodeMirror 2.x, there was a single gutter, and line markers
          created with <code>setMarker</code> would have to somehow coexist with
          the line numbers (if present). Version 3 allows you to specify an
          array of gutters, <a href="manual.html#option_gutters">by class
          name</a>,
          use <a href="manual.html#setGutterMarker"><code>setGutterMarker</code></a>
          to add or remove markers in individual gutters, and clear whole
          gutters
          with <a href="manual.html#clearGutter"><code>clearGutter</code></a>.
          Gutter markers are now specified as DOM nodes, rather than HTML
          snippets.</p>
          
          <p>The gutters no longer horizontally scrolls along with the content.
          The <code>fixedGutter</code> option was removed (since it is now the
          only behavior).</p>
          
          <pre data-lang="text/html">
          &lt;style>
            /* Define a gutter style */
            .note-gutter { width: 3em; background: cyan; }
          &lt;/style>
          &lt;script>
            // Create an instance with two gutters -- line numbers and notes
            var cm = new CodeMirror(document.body, {
              gutters: ["note-gutter", "CodeMirror-linenumbers"],
              lineNumbers: true
            });
            // Add a note to line 0
            cm.setGutterMarker(0, "note-gutter", document.createTextNode("hi"));
          &lt;/script>
          </pre>
          </section>
          <section id=events>
            <h2>Event handling</h2>
          
          <p>Most of the <code>onXYZ</code> options have been removed. The same
          effect is now obtained by calling
          the <a href="manual.html#on"><code>on</code></a> method with a string
          identifying the event type. Multiple handlers can now be registered
          (and individually unregistered) for an event, and objects such as line
          handlers now also expose events. See <a href="manual.html#events">the
          full list here</a>.</p>
          
          <p>(The <code>onKeyEvent</code> and <code>onDragEvent</code> options,
          which act more as hooks than as event handlers, are still there in
          their old form.)</p>
          
          <pre data-lang="javascript">
          cm.on("change", function(cm, change) {
            console.log("something changed! (" + change.origin + ")");
          });
          </pre>
          </section>
          <section id=marktext>
            <h2>markText method arguments</h2>
          
          <p>The <a href="manual.html#markText"><code>markText</code></a> method
          (which has gained some interesting new features, such as creating
          atomic and read-only spans, or replacing spans with widgets) no longer
          takes the CSS class name as a separate argument, but makes it an
          optional field in the options object instead.</p>
          
          <pre data-lang="javascript">
          // Style first ten lines, and forbid the cursor from entering them
          cm.markText({line: 0, ch: 0}, {line: 10, ch: 0}, {
            className: "magic-text",
            inclusiveLeft: true,
            atomic: true
          });
          </pre>
          </section>
          <section id=folding>
            <h2>Line folding</h2>
          
          <p>The interface for hiding lines has been
          removed. <a href="manual.html#markText"><code>markText</code></a> can
          now be used to do the same in a more flexible and powerful way.</p>
          
          <p>The <a href="../demo/folding.html">folding script</a> has been
          updated to use the new interface, and should now be more robust.</p>
          
          <pre data-lang="javascript">
          // Fold a range, replacing it with the text "??"
          var range = cm.markText({line: 4, ch: 2}, {line: 8, ch: 1}, {
            replacedWith: document.createTextNode("??"),
            // Auto-unfold when cursor moves into the range
            clearOnEnter: true
          });
          // Get notified when auto-unfolding
          CodeMirror.on(range, "clear", function() {
            console.log("boom");
          });
          </pre>
          </section>
          <section id=lineclass>
            <h2>Line CSS classes</h2>
          
          <p>The <code>setLineClass</code> method has been replaced
          by <a href="manual.html#addLineClass"><code>addLineClass</code></a>
          and <a href="manual.html#removeLineClass"><code>removeLineClass</code></a>,
          which allow more modular control over the classes attached to a line.</p>
          
          <pre data-lang="javascript">
          var marked = cm.addLineClass(10, "background", "highlighted-line");
          setTimeout(function() {
            cm.removeLineClass(marked, "background", "highlighted-line");
          });
          </pre>
          </section>
          <section id=positions>
            <h2>Position properties</h2>
          
          <p>All methods that take or return objects that represent screen
          positions now use <code>{left, top, bottom, right}</code> properties
          (not always all of them) instead of the <code>{x, y, yBot}</code> used
          by some methods in v2.x.</p>
          
          <p>Affected methods
          are <a href="manual.html#cursorCoords"><code>cursorCoords</code></a>, <a href="manual.html#charCoords"><code>charCoords</code></a>, <a href="manual.html#coordsChar"><code>coordsChar</code></a>,
          and <a href="manual.html#getScrollInfo"><code>getScrollInfo</code></a>.</p>
          </section>
          <section id=matchbrackets>
            <h2>Bracket matching no longer in core</h2>
          
          <p>The <a href="manual.html#addon_matchbrackets"><code>matchBrackets</code></a>
          option is no longer defined in the core editor.
          Load <code>addon/edit/matchbrackets.js</code> to enable it.</p>
          </section>
          <section id=modes>
            <h2>Mode management</h2>
          
          <p>The <code>CodeMirror.listModes</code>
          and <code>CodeMirror.listMIMEs</code> functions, used for listing
          defined modes, are gone. You are now encouraged to simply
          inspect <code>CodeMirror.modes</code> (mapping mode names to mode
          constructors) and <code>CodeMirror.mimeModes</code> (mapping MIME
          strings to mode specs).</p>
          </section>
          <section id=new>
            <h2>New features</h2>
          
          <p>Some more reasons to upgrade to version 3.</p>
          
          <ul>
            <li>Bi-directional text support. CodeMirror will now mostly do the
            right thing when editing Arabic or Hebrew text.</li>
            <li>Arbitrary line heights. Using fonts with different heights
            inside the editor (whether off by one pixel or fifty) is now
            supported and handled gracefully.</li>
            <li>In-line widgets. See <a href="../demo/widget.html">the demo</a>
            and <a href="manual.html#addLineWidget">the docs</a>.</li>
            <li>Defining custom options
            with <a href="manual.html#defineOption"><code>CodeMirror.defineOption</code></a>.</li>
          </ul>
          </section>
          </article>
          
          <script>setTimeout(function(){CodeMirror.colorize();}, 20);</script>
          
        • upgrade_v4.html
          <!doctype html>
          
          <title>CodeMirror: Version 4 upgrade guide</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="docs.css">
          <script src="activebookmark.js"></script>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#upgrade">Upgrade guide</a>
              <li><a href="#multisel">Multiple selections</a>
              <li><a href="#beforeSelectionChange">The beforeSelectionChange event</a>
              <li><a href="#replaceSelection">replaceSelection and collapsing</a>
              <li><a href="#changeEvent">change event data</a>
              <li><a href="#showIfHidden">showIfHidden option to line widgets</a>
              <li><a href="#module">Module loaders</a>
              <li><a href="#shareddata">Mutating shared data structures</a></li>
              <li><a href="#deprecated">Deprecated interfaces dropped</a>
            </ul>
          </div>
          
          <article>
          
          <h2 id=upgrade>Upgrading to version 4</h2>
          
          <p>CodeMirror 4's interface is <em>very</em> close version 3, but it
          does fix a few awkward details in a backwards-incompatible ways. At
          least skim the text below before upgrading.</p>
          
          <section id=multisel><h2>Multiple selections</h2>
          
          <p>The main new feature in version 4 is multiple selections. The
          single-selection variants of methods are still there, but now
          typically act only on the <em>primary</em> selection (usually the last
          one added).</p>
          
          <p>The exception to this
          is <a href="manual.html#getSelection"><strong><code>getSelection</code></strong></a>,
          which will now return the content of <em>all</em> selections
          (separated by newlines, or whatever <code>lineSep</code> parameter you passed
          it).</p>
          
          </section>
          
          <section id=beforeSelectionChange><h2>The beforeSelectionChange event</h2>
          
          <p>This event still exists, but the object it is passed has
          a <a href="manual.html#event_beforeSelectionChange">completely new
          interface</a>, because such changes now concern multiple
          selections.</p>
          
          </section>
          
          <section id=replaceSelection><h2>replaceSelection's collapsing behavior</h2>
          
          <p>By
          default, <a href="manual.html#replaceSelection"><code>replaceSelection</code></a>
          would leave the newly inserted text selected. This is only rarely what
          you want, and also (slightly) more expensive in the new model, so the
          default was changed to <code>"end"</code>, meaning the old behavior
          must be explicitly specified by passing a second argument
          of <code>"around"</code>.</p>
          
          </section>
          
          <section id=changeEvent><h2>change event data</h2>
          
          <p>Rather than forcing client code to follow <code>next</code>
          pointers from one change object to the next, the library will now
          simply fire
          multiple <a href="manual.html#event_change"><code>"change"</code></a>
          events. Existing code will probably continue to work unmodified.</p>
          
          </section>
          
          <section id=showIfHidden><h2>showIfHidden option to line widgets</h2>
          
          <p>This option, which conceptually caused line widgets to be visible
          even if their line was hidden, was never really well-defined, and was
          buggy from the start. It would be a rather expensive feature, both in
          code complexity and run-time performance, to implement properly. It
          has been dropped entirely in 4.0.</p>
          
          </section>
          
          <section id=module><h2>Module loaders</h2>
          
          <p>All modules in the CodeMirror distribution are now wrapped in a
          shim function to make them compatible with both AMD
          (<a href="http://requirejs.org">requirejs</a>) and CommonJS (as used
          by <a href="http://nodejs.org/">node</a>
          and <a href="http://browserify.org/">browserify</a>) module loaders.
          When neither of these is present, they fall back to simply using the
          global <code>CodeMirror</code> variable.</p>
          
          <p>If you have a module loader present in your environment, CodeMirror
          will attempt to use it, and you might need to change the way you load
          CodeMirror modules.</p>
          
          </section>
          
          <section id=shareddata><h2>Mutating shared data structures</h2>
          
          <p>Data structures produced by the library should not be mutated
          unless explicitly allowed, in general. This is slightly more strict in
          4.0 than it was in earlier versions, which copied the position objects
          returned by <a href="manual.html#getCursor"><code>getCursor</code></a>
          for nebulous, historic reasons. In 4.0, mutating these
          objects <em>will</em> corrupt your editor's selection.</p>
          
          </section>
          
          <section id=deprecated><h2>Deprecated interfaces dropped</h2>
          
          <p>A few properties and methods that have been deprecated for a while
          are now gone. Most notably, the <code>onKeyEvent</code>
          and <code>onDragEvent</code> options (use the
          corresponding <a href="manual.html#event_dom">events</a> instead).</p>
          
          <p>Two silly methods, which were mostly there to stay close to the 0.x
          API, <code>setLine</code> and <code>removeLine</code> are now gone.
          Use the more
          flexible <a href="manual.html#replaceRange"><code>replaceRange</code></a>
          method instead.</p>
          
          <p>The long names for folding and completing functions
          (<code>CodeMirror.braceRangeFinder</code>, <code>CodeMirror.javascriptHint</code>,
          etc) are also gone
          (use <code>CodeMirror.fold.brace</code>, <code>CodeMirror.hint.javascript</code>).</p>
          
          <p>The <code>className</code> property in the return value
          of <a href="manual.html#getTokenAt"><code>getTokenAt</code></a>, which
          has been superseded by the <code>type</code> property, is also no
          longer present.</p>
          
          </section>
          </article>
          
        • yinyang.png
          �PNG
          
          
      • lib
        • codemirror.css
          /* BASICS */
          
          .CodeMirror {
            /* Set height, width, borders, and global font properties here */
            font-family: monospace;
            height: 300px;
            color: black;
          }
          
          /* PADDING */
          
          .CodeMirror-lines {
            padding: 4px 0; /* Vertical padding around content */
          }
          .CodeMirror pre {
            padding: 0 4px; /* Horizontal padding of content */
          }
          
          .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
            background-color: white; /* The little square between H and V scrollbars */
          }
          
          /* GUTTER */
          
          .CodeMirror-gutters {
            border-right: 1px solid #ddd;
            background-color: #f7f7f7;
            white-space: nowrap;
          }
          .CodeMirror-linenumbers {}
          .CodeMirror-linenumber {
            padding: 0 3px 0 5px;
            min-width: 20px;
            text-align: right;
            color: #999;
            white-space: nowrap;
          }
          
          .CodeMirror-guttermarker { color: black; }
          .CodeMirror-guttermarker-subtle { color: #999; }
          
          /* CURSOR */
          
          .CodeMirror div.CodeMirror-cursor {
            border-left: 1px solid black;
          }
          /* Shown when moving in bi-directional text */
          .CodeMirror div.CodeMirror-secondarycursor {
            border-left: 1px solid silver;
          }
          .CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
            width: auto;
            border: 0;
            background: #7e7;
          }
          .CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
            z-index: 1;
          }
          
          .cm-animate-fat-cursor {
            width: auto;
            border: 0;
            -webkit-animation: blink 1.06s steps(1) infinite;
            -moz-animation: blink 1.06s steps(1) infinite;
            animation: blink 1.06s steps(1) infinite;
          }
          @-moz-keyframes blink {
            0% { background: #7e7; }
            50% { background: none; }
            100% { background: #7e7; }
          }
          @-webkit-keyframes blink {
            0% { background: #7e7; }
            50% { background: none; }
            100% { background: #7e7; }
          }
          @keyframes blink {
            0% { background: #7e7; }
            50% { background: none; }
            100% { background: #7e7; }
          }
          
          /* Can style cursor different in overwrite (non-insert) mode */
          div.CodeMirror-overwrite div.CodeMirror-cursor {}
          
          .cm-tab { display: inline-block; text-decoration: inherit; }
          
          .CodeMirror-ruler {
            border-left: 1px solid #ccc;
            position: absolute;
          }
          
          /* DEFAULT THEME */
          
          .cm-s-default .cm-keyword {color: #708;}
          .cm-s-default .cm-atom {color: #219;}
          .cm-s-default .cm-number {color: #164;}
          .cm-s-default .cm-def {color: #00f;}
          .cm-s-default .cm-variable,
          .cm-s-default .cm-punctuation,
          .cm-s-default .cm-property,
          .cm-s-default .cm-operator {}
          .cm-s-default .cm-variable-2 {color: #05a;}
          .cm-s-default .cm-variable-3 {color: #085;}
          .cm-s-default .cm-comment {color: #a50;}
          .cm-s-default .cm-string {color: #a11;}
          .cm-s-default .cm-string-2 {color: #f50;}
          .cm-s-default .cm-meta {color: #555;}
          .cm-s-default .cm-qualifier {color: #555;}
          .cm-s-default .cm-builtin {color: #30a;}
          .cm-s-default .cm-bracket {color: #997;}
          .cm-s-default .cm-tag {color: #170;}
          .cm-s-default .cm-attribute {color: #00c;}
          .cm-s-default .cm-header {color: blue;}
          .cm-s-default .cm-quote {color: #090;}
          .cm-s-default .cm-hr {color: #999;}
          .cm-s-default .cm-link {color: #00c;}
          
          .cm-negative {color: #d44;}
          .cm-positive {color: #292;}
          .cm-header, .cm-strong {font-weight: bold;}
          .cm-em {font-style: italic;}
          .cm-link {text-decoration: underline;}
          .cm-strikethrough {text-decoration: line-through;}
          
          .cm-s-default .cm-error {color: #f00;}
          .cm-invalidchar {color: #f00;}
          
          .CodeMirror-composing { border-bottom: 2px solid; }
          
          /* Default styles for common addons */
          
          div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
          div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
          .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
          .CodeMirror-activeline-background {background: #e8f2ff;}
          
          /* STOP */
          
          /* The rest of this file contains styles related to the mechanics of
             the editor. You probably shouldn't touch them. */
          
          .CodeMirror {
            position: relative;
            overflow: hidden;
            background: white;
          }
          
          .CodeMirror-scroll {
            overflow: scroll !important; /* Things will break if this is overridden */
            /* 30px is the magic margin used to hide the element's real scrollbars */
            /* See overflow: hidden in .CodeMirror */
            margin-bottom: -30px; margin-right: -30px;
            padding-bottom: 30px;
            height: 100%;
            outline: none; /* Prevent dragging from highlighting the element */
            position: relative;
          }
          .CodeMirror-sizer {
            position: relative;
            border-right: 30px solid transparent;
          }
          
          /* The fake, visible scrollbars. Used to force redraw during scrolling
             before actuall scrolling happens, thus preventing shaking and
             flickering artifacts. */
          .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
            position: absolute;
            z-index: 6;
            display: none;
          }
          .CodeMirror-vscrollbar {
            right: 0; top: 0;
            overflow-x: hidden;
            overflow-y: scroll;
          }
          .CodeMirror-hscrollbar {
            bottom: 0; left: 0;
            overflow-y: hidden;
            overflow-x: scroll;
          }
          .CodeMirror-scrollbar-filler {
            right: 0; bottom: 0;
          }
          .CodeMirror-gutter-filler {
            left: 0; bottom: 0;
          }
          
          .CodeMirror-gutters {
            position: absolute; left: 0; top: 0;
            z-index: 3;
          }
          .CodeMirror-gutter {
            white-space: normal;
            height: 100%;
            display: inline-block;
            margin-bottom: -30px;
            /* Hack to make IE7 behave */
            *zoom:1;
            *display:inline;
          }
          .CodeMirror-gutter-wrapper {
            position: absolute;
            z-index: 4;
            height: 100%;
          }
          .CodeMirror-gutter-elt {
            position: absolute;
            cursor: default;
            z-index: 4;
          }
          .CodeMirror-gutter-wrapper {
            -webkit-user-select: none;
            -moz-user-select: none;
            user-select: none;
          }
          
          .CodeMirror-lines {
            cursor: text;
            min-height: 1px; /* prevents collapsing before first draw */
          }
          .CodeMirror pre {
            /* Reset some styles that the rest of the page might have set */
            -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
            border-width: 0;
            background: transparent;
            font-family: inherit;
            font-size: inherit;
            margin: 0;
            white-space: pre;
            word-wrap: normal;
            line-height: inherit;
            color: inherit;
            z-index: 2;
            position: relative;
            overflow: visible;
            -webkit-tap-highlight-color: transparent;
          }
          .CodeMirror-wrap pre {
            word-wrap: break-word;
            white-space: pre-wrap;
            word-break: normal;
          }
          
          .CodeMirror-linebackground {
            position: absolute;
            left: 0; right: 0; top: 0; bottom: 0;
            z-index: 0;
          }
          
          .CodeMirror-linewidget {
            position: relative;
            z-index: 2;
            overflow: auto;
          }
          
          .CodeMirror-widget {}
          
          .CodeMirror-code {
            outline: none;
          }
          
          /* Force content-box sizing for the elements where we expect it */
          .CodeMirror-scroll,
          .CodeMirror-sizer,
          .CodeMirror-gutter,
          .CodeMirror-gutters,
          .CodeMirror-linenumber {
            -moz-box-sizing: content-box;
            box-sizing: content-box;
          }
          
          .CodeMirror-measure {
            position: absolute;
            width: 100%;
            height: 0;
            overflow: hidden;
            visibility: hidden;
          }
          .CodeMirror-measure pre { position: static; }
          
          .CodeMirror div.CodeMirror-cursor {
            position: absolute;
            border-right: none;
            width: 0;
          }
          
          div.CodeMirror-cursors {
            visibility: hidden;
            position: relative;
            z-index: 3;
          }
          .CodeMirror-focused div.CodeMirror-cursors {
            visibility: visible;
          }
          
          .CodeMirror-selected { background: #d9d9d9; }
          .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
          .CodeMirror-crosshair { cursor: crosshair; }
          .CodeMirror ::selection { background: #d7d4f0; }
          .CodeMirror ::-moz-selection { background: #d7d4f0; }
          
          .cm-searching {
            background: #ffa;
            background: rgba(255, 255, 0, .4);
          }
          
          /* IE7 hack to prevent it from returning funny offsetTops on the spans */
          .CodeMirror span { *vertical-align: text-bottom; }
          
          /* Used to force a border model for a node */
          .cm-force-border { padding-right: .1px; }
          
          @media print {
            /* Hide the cursor when printing */
            .CodeMirror div.CodeMirror-cursors {
              visibility: hidden;
            }
          }
          
          /* See issue #2901 */
          .cm-tab-wrap-hack:after { content: ''; }
          
          /* Help users use markselection to safely style text background */
          span.CodeMirror-selectedtext { background: none; }
          
        • codemirror.js
          // CodeMirror, copyright (c) by Marijn Haverbeke and others
          // Distributed under an MIT license: http://codemirror.net/LICENSE
          
          // This is CodeMirror (http://codemirror.net), a code editor
          // implemented in JavaScript on top of the browser's DOM.
          //
          // You can find some technical background for some of the code below
          // at http://marijnhaverbeke.nl/blog/#cm-internals .
          
          (function(mod) {
            if (typeof exports == "object" && typeof module == "object") // CommonJS
              module.exports = mod();
            else if (typeof define == "function" && define.amd) // AMD
              return define([], mod);
            else // Plain browser env
              this.CodeMirror = mod();
          })(function() {
            "use strict";
          
            // BROWSER SNIFFING
          
            // Kludges for bugs and behavior differences that can't be feature
            // detected are enabled based on userAgent etc sniffing.
          
            var gecko = /gecko\/\d/i.test(navigator.userAgent);
            var ie_upto10 = /MSIE \d/.test(navigator.userAgent);
            var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent);
            var ie = ie_upto10 || ie_11up;
            var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]);
            var webkit = /WebKit\//.test(navigator.userAgent);
            var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
            var chrome = /Chrome\//.test(navigator.userAgent);
            var presto = /Opera\//.test(navigator.userAgent);
            var safari = /Apple Computer/.test(navigator.vendor);
            var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
            var phantom = /PhantomJS/.test(navigator.userAgent);
          
            var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
            // This is woefully incomplete. Suggestions for alternative methods welcome.
            var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
            var mac = ios || /Mac/.test(navigator.platform);
            var windows = /win/i.test(navigator.platform);
          
            var presto_version = presto && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
            if (presto_version) presto_version = Number(presto_version[1]);
            if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
            // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
            var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));
            var captureRightClick = gecko || (ie && ie_version >= 9);
          
            // Optimize some code when these features are not used.
            var sawReadOnlySpans = false, sawCollapsedSpans = false;
          
            // EDITOR CONSTRUCTOR
          
            // A CodeMirror instance represents an editor. This is the object
            // that user code is usually dealing with.
          
            function CodeMirror(place, options) {
              if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
          
              this.options = options = options ? copyObj(options) : {};
              // Determine effective options based on given values and defaults.
              copyObj(defaults, options, false);
              setGuttersForLineNumbers(options);
          
              var doc = options.value;
              if (typeof doc == "string") doc = new Doc(doc, options.mode);
              this.doc = doc;
          
              var input = new CodeMirror.inputStyles[options.inputStyle](this);
              var display = this.display = new Display(place, doc, input);
              display.wrapper.CodeMirror = this;
              updateGutters(this);
              themeChanged(this);
              if (options.lineWrapping)
                this.display.wrapper.className += " CodeMirror-wrap";
              if (options.autofocus && !mobile) display.input.focus();
              initScrollbars(this);
          
              this.state = {
                keyMaps: [],  // stores maps added by addKeyMap
                overlays: [], // highlighting overlays, as added by addOverlay
                modeGen: 0,   // bumped when mode/overlay changes, used to invalidate highlighting info
                overwrite: false,
                delayingBlurEvent: false,
                focused: false,
                suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
                pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
                draggingText: false,
                highlight: new Delayed(), // stores highlight worker timeout
                keySeq: null,  // Unfinished key sequence
                specialChars: null
              };
          
              var cm = this;
          
              // Override magic textarea content restore that IE sometimes does
              // on our hidden textarea on reload
              if (ie && ie_version < 11) setTimeout(function() { cm.display.input.reset(true); }, 20);
          
              registerEventHandlers(this);
              ensureGlobalHandlers();
          
              startOperation(this);
              this.curOp.forceUpdate = true;
              attachDoc(this, doc);
          
              if ((options.autofocus && !mobile) || cm.hasFocus())
                setTimeout(bind(onFocus, this), 20);
              else
                onBlur(this);
          
              for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))
                optionHandlers[opt](this, options[opt], Init);
              maybeUpdateLineNumberWidth(this);
              if (options.finishInit) options.finishInit(this);
              for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
              endOperation(this);
              // Suppress optimizelegibility in Webkit, since it breaks text
              // measuring on line wrapping boundaries.
              if (webkit && options.lineWrapping &&
                  getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
                display.lineDiv.style.textRendering = "auto";
            }
          
            // DISPLAY CONSTRUCTOR
          
            // The display handles the DOM integration, both for input reading
            // and content drawing. It holds references to DOM nodes and
            // display-related state.
          
            function Display(place, doc, input) {
              var d = this;
              this.input = input;
          
              // Covers bottom-right square when both scrollbars are present.
              d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
              d.scrollbarFiller.setAttribute("cm-not-content", "true");
              // Covers bottom of gutter when coverGutterNextToScrollbar is on
              // and h scrollbar is present.
              d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
              d.gutterFiller.setAttribute("cm-not-content", "true");
              // Will contain the actual code, positioned to cover the viewport.
              d.lineDiv = elt("div", null, "CodeMirror-code");
              // Elements are added to these to represent selection and cursors.
              d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
              d.cursorDiv = elt("div", null, "CodeMirror-cursors");
              // A visibility: hidden element used to find the size of things.
              d.measure = elt("div", null, "CodeMirror-measure");
              // When lines outside of the viewport are measured, they are drawn in this.
              d.lineMeasure = elt("div", null, "CodeMirror-measure");
              // Wraps everything that needs to exist inside the vertically-padded coordinate system
              d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
                                null, "position: relative; outline: none");
              // Moved around its parent to cover visible view.
              d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
              // Set to the height of the document, allowing scrolling.
              d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
              d.sizerWidth = null;
              // Behavior of elts with overflow: auto and padding is
              // inconsistent across browsers. This is used to ensure the
              // scrollable area is big enough.
              d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;");
              // Will contain the gutters, if any.
              d.gutters = elt("div", null, "CodeMirror-gutters");
              d.lineGutter = null;
              // Actual scrollable element.
              d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
              d.scroller.setAttribute("tabIndex", "-1");
              // The element in which the editor lives.
              d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
          
              // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
              if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
              if (!webkit && !(gecko && mobile)) d.scroller.draggable = true;
          
              if (place) {
                if (place.appendChild) place.appendChild(d.wrapper);
                else place(d.wrapper);
              }
          
              // Current rendered range (may be bigger than the view window).
              d.viewFrom = d.viewTo = doc.first;
              d.reportedViewFrom = d.reportedViewTo = doc.first;
              // Information about the rendered lines.
              d.view = [];
              d.renderedView = null;
              // Holds info about a single rendered line when it was rendered
              // for measurement, while not in view.
              d.externalMeasured = null;
              // Empty space (in pixels) above the view
              d.viewOffset = 0;
              d.lastWrapHeight = d.lastWrapWidth = 0;
              d.updateLineNumbers = null;
          
              d.nativeBarWidth = d.barHeight = d.barWidth = 0;
              d.scrollbarsClipped = false;
          
              // Used to only resize the line number gutter when necessary (when
              // the amount of lines crosses a boundary that makes its width change)
              d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
              // Set to true when a non-horizontal-scrolling line widget is
              // added. As an optimization, line widget aligning is skipped when
              // this is false.
              d.alignWidgets = false;
          
              d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
          
              // Tracks the maximum line length so that the horizontal scrollbar
              // can be kept static when scrolling.
              d.maxLine = null;
              d.maxLineLength = 0;
              d.maxLineChanged = false;
          
              // Used for measuring wheel scrolling granularity
              d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
          
              // True when shift is held down.
              d.shift = false;
          
              // Used to track whether anything happened since the context menu
              // was opened.
              d.selForContextMenu = null;
          
              d.activeTouch = null;
          
              input.init(d);
            }
          
            // STATE UPDATES
          
            // Used to get the editor into a consistent state again when options change.
          
            function loadMode(cm) {
              cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
              resetModeState(cm);
            }
          
            function resetModeState(cm) {
              cm.doc.iter(function(line) {
                if (line.stateAfter) line.stateAfter = null;
                if (line.styles) line.styles = null;
              });
              cm.doc.frontier = cm.doc.first;
              startWorker(cm, 100);
              cm.state.modeGen++;
              if (cm.curOp) regChange(cm);
            }
          
            function wrappingChanged(cm) {
              if (cm.options.lineWrapping) {
                addClass(cm.display.wrapper, "CodeMirror-wrap");
                cm.display.sizer.style.minWidth = "";
                cm.display.sizerWidth = null;
              } else {
                rmClass(cm.display.wrapper, "CodeMirror-wrap");
                findMaxLine(cm);
              }
              estimateLineHeights(cm);
              regChange(cm);
              clearCaches(cm);
              setTimeout(function(){updateScrollbars(cm);}, 100);
            }
          
            // Returns a function that estimates the height of a line, to use as
            // first approximation until the line becomes visible (and is thus
            // properly measurable).
            function estimateHeight(cm) {
              var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
              var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
              return function(line) {
                if (lineIsHidden(cm.doc, line)) return 0;
          
                var widgetsHeight = 0;
                if (line.widgets) for (var i = 0; i < line.widgets.length; i++) {
                  if (line.widgets[i].height) widgetsHeight += line.widgets[i].height;
                }
          
                if (wrapping)
                  return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th;
                else
                  return widgetsHeight + th;
              };
            }
          
            function estimateLineHeights(cm) {
              var doc = cm.doc, est = estimateHeight(cm);
              doc.iter(function(line) {
                var estHeight = est(line);
                if (estHeight != line.height) updateLineHeight(line, estHeight);
              });
            }
          
            function themeChanged(cm) {
              cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
                cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
              clearCaches(cm);
            }
          
            function guttersChanged(cm) {
              updateGutters(cm);
              regChange(cm);
              setTimeout(function(){alignHorizontally(cm);}, 20);
            }
          
            // Rebuild the gutter elements, ensure the margin to the left of the
            // code matches their width.
            function updateGutters(cm) {
              var gutters = cm.display.gutters, specs = cm.options.gutters;
              removeChildren(gutters);
              for (var i = 0; i < specs.length; ++i) {
                var gutterClass = specs[i];
                var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
                if (gutterClass == "CodeMirror-linenumbers") {
                  cm.display.lineGutter = gElt;
                  gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
                }
              }
              gutters.style.display = i ? "" : "none";
              updateGutterSpace(cm);
            }
          
            function updateGutterSpace(cm) {
              var width = cm.display.gutters.offsetWidth;
              cm.display.sizer.style.marginLeft = width + "px";
            }
          
            // Compute the character length of a line, taking into account
            // collapsed ranges (see markText) that might hide parts, and join
            // other lines onto it.
            function lineLength(line) {
              if (line.height == 0) return 0;
              var len = line.text.length, merged, cur = line;
              while (merged = collapsedSpanAtStart(cur)) {
                var found = merged.find(0, true);
                cur = found.from.line;
                len += found.from.ch - found.to.ch;
              }
              cur = line;
              while (merged = collapsedSpanAtEnd(cur)) {
                var found = merged.find(0, true);
                len -= cur.text.length - found.from.ch;
                cur = found.to.line;
                len += cur.text.length - found.to.ch;
              }
              return len;
            }
          
            // Find the longest line in the document.
            function findMaxLine(cm) {
              var d = cm.display, doc = cm.doc;
              d.maxLine = getLine(doc, doc.first);
              d.maxLineLength = lineLength(d.maxLine);
              d.maxLineChanged = true;
              doc.iter(function(line) {
                var len = lineLength(line);
                if (len > d.maxLineLength) {
                  d.maxLineLength = len;
                  d.maxLine = line;
                }
              });
            }
          
            // Make sure the gutters options contains the element
            // "CodeMirror-linenumbers" when the lineNumbers option is true.
            function setGuttersForLineNumbers(options) {
              var found = indexOf(options.gutters, "CodeMirror-linenumbers");
              if (found == -1 && options.lineNumbers) {
                options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]);
              } else if (found > -1 && !options.lineNumbers) {
                options.gutters = options.gutters.slice(0);
                options.gutters.splice(found, 1);
              }
            }
          
            // SCROLLBARS
          
            // Prepare DOM reads needed to update the scrollbars. Done in one
            // shot to minimize update/measure roundtrips.
            function measureForScrollbars(cm) {
              var d = cm.display, gutterW = d.gutters.offsetWidth;
              var docH = Math.round(cm.doc.height + paddingVert(cm.display));
              return {
                clientHeight: d.scroller.clientHeight,
                viewHeight: d.wrapper.clientHeight,
                scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
                viewWidth: d.wrapper.clientWidth,
                barLeft: cm.options.fixedGutter ? gutterW : 0,
                docHeight: docH,
                scrollHeight: docH + scrollGap(cm) + d.barHeight,
                nativeBarWidth: d.nativeBarWidth,
                gutterWidth: gutterW
              };
            }
          
            function NativeScrollbars(place, scroll, cm) {
              this.cm = cm;
              var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");
              var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
              place(vert); place(horiz);
          
              on(vert, "scroll", function() {
                if (vert.clientHeight) scroll(vert.scrollTop, "vertical");
              });
              on(horiz, "scroll", function() {
                if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal");
              });
          
              this.checkedOverlay = false;
              // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
              if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px";
            }
          
            NativeScrollbars.prototype = copyObj({
              update: function(measure) {
                var needsH = measure.scrollWidth > measure.clientWidth + 1;
                var needsV = measure.scrollHeight > measure.clientHeight + 1;
                var sWidth = measure.nativeBarWidth;
          
                if (needsV) {
                  this.vert.style.display = "block";
                  this.vert.style.bottom = needsH ? sWidth + "px" : "0";
                  var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);
                  // A bug in IE8 can cause this value to be negative, so guard it.
                  this.vert.firstChild.style.height =
                    Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
                } else {
                  this.vert.style.display = "";
                  this.vert.firstChild.style.height = "0";
                }
          
                if (needsH) {
                  this.horiz.style.display = "block";
                  this.horiz.style.right = needsV ? sWidth + "px" : "0";
                  this.horiz.style.left = measure.barLeft + "px";
                  var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);
                  this.horiz.firstChild.style.width =
                    (measure.scrollWidth - measure.clientWidth + totalWidth) + "px";
                } else {
                  this.horiz.style.display = "";
                  this.horiz.firstChild.style.width = "0";
                }
          
                if (!this.checkedOverlay && measure.clientHeight > 0) {
                  if (sWidth == 0) this.overlayHack();
                  this.checkedOverlay = true;
                }
          
                return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0};
              },
              setScrollLeft: function(pos) {
                if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos;
              },
              setScrollTop: function(pos) {
                if (this.vert.scrollTop != pos) this.vert.scrollTop = pos;
              },
              overlayHack: function() {
                var w = mac && !mac_geMountainLion ? "12px" : "18px";
                this.horiz.style.minHeight = this.vert.style.minWidth = w;
                var self = this;
                var barMouseDown = function(e) {
                  if (e_target(e) != self.vert && e_target(e) != self.horiz)
                    operation(self.cm, onMouseDown)(e);
                };
                on(this.vert, "mousedown", barMouseDown);
                on(this.horiz, "mousedown", barMouseDown);
              },
              clear: function() {
                var parent = this.horiz.parentNode;
                parent.removeChild(this.horiz);
                parent.removeChild(this.vert);
              }
            }, NativeScrollbars.prototype);
          
            function NullScrollbars() {}
          
            NullScrollbars.prototype = copyObj({
              update: function() { return {bottom: 0, right: 0}; },
              setScrollLeft: function() {},
              setScrollTop: function() {},
              clear: function() {}
            }, NullScrollbars.prototype);
          
            CodeMirror.scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars};
          
            function initScrollbars(cm) {
              if (cm.display.scrollbars) {
                cm.display.scrollbars.clear();
                if (cm.display.scrollbars.addClass)
                  rmClass(cm.display.wrapper, cm.display.scrollbars.addClass);
              }
          
              cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) {
                cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);
                // Prevent clicks in the scrollbars from killing focus
                on(node, "mousedown", function() {
                  if (cm.state.focused) setTimeout(function() { cm.display.input.focus(); }, 0);
                });
                node.setAttribute("cm-not-content", "true");
              }, function(pos, axis) {
                if (axis == "horizontal") setScrollLeft(cm, pos);
                else setScrollTop(cm, pos);
              }, cm);
              if (cm.display.scrollbars.addClass)
                addClass(cm.display.wrapper, cm.display.scrollbars.addClass);
            }
          
            function updateScrollbars(cm, measure) {
              if (!measure) measure = measureForScrollbars(cm);
              var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;
              updateScrollbarsInner(cm, measure);
              for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
                if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
                  updateHeightsInViewport(cm);
                updateScrollbarsInner(cm, measureForScrollbars(cm));
                startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;
              }
            }
          
            // Re-synchronize the fake scrollbars with the actual size of the
            // content.
            function updateScrollbarsInner(cm, measure) {
              var d = cm.display;
              var sizes = d.scrollbars.update(measure);
          
              d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px";
              d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px";
          
              if (sizes.right && sizes.bottom) {
                d.scrollbarFiller.style.display = "block";
                d.scrollbarFiller.style.height = sizes.bottom + "px";
                d.scrollbarFiller.style.width = sizes.right + "px";
              } else d.scrollbarFiller.style.display = "";
              if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
                d.gutterFiller.style.display = "block";
                d.gutterFiller.style.height = sizes.bottom + "px";
                d.gutterFiller.style.width = measure.gutterWidth + "px";
              } else d.gutterFiller.style.display = "";
            }
          
            // Compute the lines that are visible in a given viewport (defaults
            // the the current scroll position). viewport may contain top,
            // height, and ensure (see op.scrollToPos) properties.
            function visibleLines(display, doc, viewport) {
              var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;
              top = Math.floor(top - paddingTop(display));
              var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;
          
              var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
              // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
              // forces those lines into the viewport (if possible).
              if (viewport && viewport.ensure) {
                var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;
                if (ensureFrom < from) {
                  from = ensureFrom;
                  to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);
                } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
                  from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);
                  to = ensureTo;
                }
              }
              return {from: from, to: Math.max(to, from + 1)};
            }
          
            // LINE NUMBERS
          
            // Re-align line numbers and gutter marks to compensate for
            // horizontal scrolling.
            function alignHorizontally(cm) {
              var display = cm.display, view = display.view;
              if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
              var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
              var gutterW = display.gutters.offsetWidth, left = comp + "px";
              for (var i = 0; i < view.length; i++) if (!view[i].hidden) {
                if (cm.options.fixedGutter && view[i].gutter)
                  view[i].gutter.style.left = left;
                var align = view[i].alignable;
                if (align) for (var j = 0; j < align.length; j++)
                  align[j].style.left = left;
              }
              if (cm.options.fixedGutter)
                display.gutters.style.left = (comp + gutterW) + "px";
            }
          
            // Used to ensure that the line number gutter is still the right
            // size for the current document size. Returns true when an update
            // is needed.
            function maybeUpdateLineNumberWidth(cm) {
              if (!cm.options.lineNumbers) return false;
              var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
              if (last.length != display.lineNumChars) {
                var test = display.measure.appendChild(elt("div", [elt("div", last)],
                                                           "CodeMirror-linenumber CodeMirror-gutter-elt"));
                var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
                display.lineGutter.style.width = "";
                display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
                display.lineNumWidth = display.lineNumInnerWidth + padding;
                display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
                display.lineGutter.style.width = display.lineNumWidth + "px";
                updateGutterSpace(cm);
                return true;
              }
              return false;
            }
          
            function lineNumberFor(options, i) {
              return String(options.lineNumberFormatter(i + options.firstLineNumber));
            }
          
            // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
            // but using getBoundingClientRect to get a sub-pixel-accurate
            // result.
            function compensateForHScroll(display) {
              return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left;
            }
          
            // DISPLAY DRAWING
          
            function DisplayUpdate(cm, viewport, force) {
              var display = cm.display;
          
              this.viewport = viewport;
              // Store some values that we'll need later (but don't want to force a relayout for)
              this.visible = visibleLines(display, cm.doc, viewport);
              this.editorIsHidden = !display.wrapper.offsetWidth;
              this.wrapperHeight = display.wrapper.clientHeight;
              this.wrapperWidth = display.wrapper.clientWidth;
              this.oldDisplayWidth = displayWidth(cm);
              this.force = force;
              this.dims = getDimensions(cm);
              this.events = [];
            }
          
            DisplayUpdate.prototype.signal = function(emitter, type) {
              if (hasHandler(emitter, type))
                this.events.push(arguments);
            };
            DisplayUpdate.prototype.finish = function() {
              for (var i = 0; i < this.events.length; i++)
                signal.apply(null, this.events[i]);
            };
          
            function maybeClipScrollbars(cm) {
              var display = cm.display;
              if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
                display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;
                display.heightForcer.style.height = scrollGap(cm) + "px";
                display.sizer.style.marginBottom = -display.nativeBarWidth + "px";
                display.sizer.style.borderRightWidth = scrollGap(cm) + "px";
                display.scrollbarsClipped = true;
              }
            }
          
            // Does the actual updating of the line display. Bails out
            // (returning false) when there is nothing to be done and forced is
            // false.
            function updateDisplayIfNeeded(cm, update) {
              var display = cm.display, doc = cm.doc;
          
              if (update.editorIsHidden) {
                resetView(cm);
                return false;
              }
          
              // Bail out if the visible area is already rendered and nothing changed.
              if (!update.force &&
                  update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&
                  (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&
                  display.renderedView == display.view && countDirtyView(cm) == 0)
                return false;
          
              if (maybeUpdateLineNumberWidth(cm)) {
                resetView(cm);
                update.dims = getDimensions(cm);
              }
          
              // Compute a suitable new viewport (from & to)
              var end = doc.first + doc.size;
              var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);
              var to = Math.min(end, update.visible.to + cm.options.viewportMargin);
              if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom);
              if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo);
              if (sawCollapsedSpans) {
                from = visualLineNo(cm.doc, from);
                to = visualLineEndNo(cm.doc, to);
              }
          
              var different = from != display.viewFrom || to != display.viewTo ||
                display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;
              adjustView(cm, from, to);
          
              display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
              // Position the mover div to align with the current scroll position
              cm.display.mover.style.top = display.viewOffset + "px";
          
              var toUpdate = countDirtyView(cm);
              if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
                  (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
                return false;
          
              // For big changes, we hide the enclosing element during the
              // update, since that speeds up the operations on most browsers.
              var focused = activeElt();
              if (toUpdate > 4) display.lineDiv.style.display = "none";
              patchDisplay(cm, display.updateLineNumbers, update.dims);
              if (toUpdate > 4) display.lineDiv.style.display = "";
              display.renderedView = display.view;
              // There might have been a widget with a focused element that got
              // hidden or updated, if so re-focus it.
              if (focused && activeElt() != focused && focused.offsetHeight) focused.focus();
          
              // Prevent selection and cursors from interfering with the scroll
              // width and height.
              removeChildren(display.cursorDiv);
              removeChildren(display.selectionDiv);
              display.gutters.style.height = 0;
          
              if (different) {
                display.lastWrapHeight = update.wrapperHeight;
                display.lastWrapWidth = update.wrapperWidth;
                startWorker(cm, 400);
              }
          
              display.updateLineNumbers = null;
          
              return true;
            }
          
            function postUpdateDisplay(cm, update) {
              var viewport = update.viewport;
              for (var first = true;; first = false) {
                if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
                  // Clip forced viewport to actual scrollable area.
                  if (viewport && viewport.top != null)
                    viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)};
                  // Updated line heights might result in the drawn area not
                  // actually covering the viewport. Keep looping until it does.
                  update.visible = visibleLines(cm.display, cm.doc, viewport);
                  if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
                    break;
                }
                if (!updateDisplayIfNeeded(cm, update)) break;
                updateHeightsInViewport(cm);
                var barMeasure = measureForScrollbars(cm);
                updateSelection(cm);
                setDocumentHeight(cm, barMeasure);
                updateScrollbars(cm, barMeasure);
              }
          
              update.signal(cm, "update", cm);
              if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
                update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
                cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;
              }
            }
          
            function updateDisplaySimple(cm, viewport) {
              var update = new DisplayUpdate(cm, viewport);
              if (updateDisplayIfNeeded(cm, update)) {
                updateHeightsInViewport(cm);
                postUpdateDisplay(cm, update);
                var barMeasure = measureForScrollbars(cm);
                updateSelection(cm);
                setDocumentHeight(cm, barMeasure);
                updateScrollbars(cm, barMeasure);
                update.finish();
              }
            }
          
            function setDocumentHeight(cm, measure) {
              cm.display.sizer.style.minHeight = measure.docHeight + "px";
              var total = measure.docHeight + cm.display.barHeight;
              cm.display.heightForcer.style.top = total + "px";
              cm.display.gutters.style.height = Math.max(total + scrollGap(cm), measure.clientHeight) + "px";
            }
          
            // Read the actual heights of the rendered lines, and update their
            // stored heights to match.
            function updateHeightsInViewport(cm) {
              var display = cm.display;
              var prevBottom = display.lineDiv.offsetTop;
              for (var i = 0; i < display.view.length; i++) {
                var cur = display.view[i], height;
                if (cur.hidden) continue;
                if (ie && ie_version < 8) {
                  var bot = cur.node.offsetTop + cur.node.offsetHeight;
                  height = bot - prevBottom;
                  prevBottom = bot;
                } else {
                  var box = cur.node.getBoundingClientRect();
                  height = box.bottom - box.top;
                }
                var diff = cur.line.height - height;
                if (height < 2) height = textHeight(display);
                if (diff > .001 || diff < -.001) {
                  updateLineHeight(cur.line, height);
                  updateWidgetHeight(cur.line);
                  if (cur.rest) for (var j = 0; j < cur.rest.length; j++)
                    updateWidgetHeight(cur.rest[j]);
                }
              }
            }
          
            // Read and store the height of line widgets associated with the
            // given line.
            function updateWidgetHeight(line) {
              if (line.widgets) for (var i = 0; i < line.widgets.length; ++i)
                line.widgets[i].height = line.widgets[i].node.offsetHeight;
            }
          
            // Do a bulk-read of the DOM positions and sizes needed to draw the
            // view, so that we don't interleave reading and writing to the DOM.
            function getDimensions(cm) {
              var d = cm.display, left = {}, width = {};
              var gutterLeft = d.gutters.clientLeft;
              for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
                left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft;
                width[cm.options.gutters[i]] = n.clientWidth;
              }
              return {fixedPos: compensateForHScroll(d),
                      gutterTotalWidth: d.gutters.offsetWidth,
                      gutterLeft: left,
                      gutterWidth: width,
                      wrapperWidth: d.wrapper.clientWidth};
            }
          
            // Sync the actual display DOM structure with display.view, removing
            // nodes for lines that are no longer in view, and creating the ones
            // that are not there yet, and updating the ones that are out of
            // date.
            function patchDisplay(cm, updateNumbersFrom, dims) {
              var display = cm.display, lineNumbers = cm.options.lineNumbers;
              var container = display.lineDiv, cur = container.firstChild;
          
              function rm(node) {
                var next = node.nextSibling;
                // Works around a throw-scroll bug in OS X Webkit
                if (webkit && mac && cm.display.currentWheelTarget == node)
                  node.style.display = "none";
                else
                  node.parentNode.removeChild(node);
                return next;
              }
          
              var view = display.view, lineN = display.viewFrom;
              // Loop over the elements in the view, syncing cur (the DOM nodes
              // in display.lineDiv) with the view as we go.
              for (var i = 0; i < view.length; i++) {
                var lineView = view[i];
                if (lineView.hidden) {
                } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
                  var node = buildLineElement(cm, lineView, lineN, dims);
                  container.insertBefore(node, cur);
                } else { // Already drawn
                  while (cur != lineView.node) cur = rm(cur);
                  var updateNumber = lineNumbers && updateNumbersFrom != null &&
                    updateNumbersFrom <= lineN && lineView.lineNumber;
                  if (lineView.changes) {
                    if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false;
                    updateLineForChanges(cm, lineView, lineN, dims);
                  }
                  if (updateNumber) {
                    removeChildren(lineView.lineNumber);
                    lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));
                  }
                  cur = lineView.node.nextSibling;
                }
                lineN += lineView.size;
              }
              while (cur) cur = rm(cur);
            }
          
            // When an aspect of a line changes, a string is added to
            // lineView.changes. This updates the relevant part of the line's
            // DOM structure.
            function updateLineForChanges(cm, lineView, lineN, dims) {
              for (var j = 0; j < lineView.changes.length; j++) {
                var type = lineView.changes[j];
                if (type == "text") updateLineText(cm, lineView);
                else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims);
                else if (type == "class") updateLineClasses(lineView);
                else if (type == "widget") updateLineWidgets(cm, lineView, dims);
              }
              lineView.changes = null;
            }
          
            // Lines with gutter elements, widgets or a background class need to
            // be wrapped, and have the extra elements added to the wrapper div
            function ensureLineWrapped(lineView) {
              if (lineView.node == lineView.text) {
                lineView.node = elt("div", null, null, "position: relative");
                if (lineView.text.parentNode)
                  lineView.text.parentNode.replaceChild(lineView.node, lineView.text);
                lineView.node.appendChild(lineView.text);
                if (ie && ie_version < 8) lineView.node.style.zIndex = 2;
              }
              return lineView.node;
            }
          
            function updateLineBackground(lineView) {
              var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass;
              if (cls) cls += " CodeMirror-linebackground";
              if (lineView.background) {
                if (cls) lineView.background.className = cls;
                else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }
              } else if (cls) {
                var wrap = ensureLineWrapped(lineView);
                lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild);
              }
            }
          
            // Wrapper around buildLineContent which will reuse the structure
            // in display.externalMeasured when possible.
            function getLineContent(cm, lineView) {
              var ext = cm.display.externalMeasured;
              if (ext && ext.line == lineView.line) {
                cm.display.externalMeasured = null;
                lineView.measure = ext.measure;
                return ext.built;
              }
              return buildLineContent(cm, lineView);
            }
          
            // Redraw the line's text. Interacts with the background and text
            // classes because the mode may output tokens that influence these
            // classes.
            function updateLineText(cm, lineView) {
              var cls = lineView.text.className;
              var built = getLineContent(cm, lineView);
              if (lineView.text == lineView.node) lineView.node = built.pre;
              lineView.text.parentNode.replaceChild(built.pre, lineView.text);
              lineView.text = built.pre;
              if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
                lineView.bgClass = built.bgClass;
                lineView.textClass = built.textClass;
                updateLineClasses(lineView);
              } else if (cls) {
                lineView.text.className = cls;
              }
            }
          
            function updateLineClasses(lineView) {
              updateLineBackground(lineView);
              if (lineView.line.wrapClass)
                ensureLineWrapped(lineView).className = lineView.line.wrapClass;
              else if (lineView.node != lineView.text)
                lineView.node.className = "";
              var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass;
              lineView.text.className = textClass || "";
            }
          
            function updateLineGutter(cm, lineView, lineN, dims) {
              if (lineView.gutter) {
                lineView.node.removeChild(lineView.gutter);
                lineView.gutter = null;
              }
              var markers = lineView.line.gutterMarkers;
              if (cm.options.lineNumbers || markers) {
                var wrap = ensureLineWrapped(lineView);
                var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", "left: " +
                                                       (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +
                                                       "px; width: " + dims.gutterTotalWidth + "px");
                cm.display.input.setUneditable(gutterWrap);
                wrap.insertBefore(gutterWrap, lineView.text);
                if (lineView.line.gutterClass)
                  gutterWrap.className += " " + lineView.line.gutterClass;
                if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
                  lineView.lineNumber = gutterWrap.appendChild(
                    elt("div", lineNumberFor(cm.options, lineN),
                        "CodeMirror-linenumber CodeMirror-gutter-elt",
                        "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
                        + cm.display.lineNumInnerWidth + "px"));
                if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) {
                  var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
                  if (found)
                    gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
                                               dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
                }
              }
            }
          
            function updateLineWidgets(cm, lineView, dims) {
              if (lineView.alignable) lineView.alignable = null;
              for (var node = lineView.node.firstChild, next; node; node = next) {
                var next = node.nextSibling;
                if (node.className == "CodeMirror-linewidget")
                  lineView.node.removeChild(node);
              }
              insertLineWidgets(cm, lineView, dims);
            }
          
            // Build a line's DOM representation from scratch
            function buildLineElement(cm, lineView, lineN, dims) {
              var built = getLineContent(cm, lineView);
              lineView.text = lineView.node = built.pre;
              if (built.bgClass) lineView.bgClass = built.bgClass;
              if (built.textClass) lineView.textClass = built.textClass;
          
              updateLineClasses(lineView);
              updateLineGutter(cm, lineView, lineN, dims);
              insertLineWidgets(cm, lineView, dims);
              return lineView.node;
            }
          
            // A lineView may contain multiple logical lines (when merged by
            // collapsed spans). The widgets for all of them need to be drawn.
            function insertLineWidgets(cm, lineView, dims) {
              insertLineWidgetsFor(cm, lineView.line, lineView, dims, true);
              if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
                insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false);
            }
          
            function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
              if (!line.widgets) return;
              var wrap = ensureLineWrapped(lineView);
              for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
                var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
                if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true");
                positionLineWidget(widget, node, lineView, dims);
                cm.display.input.setUneditable(node);
                if (allowAbove && widget.above)
                  wrap.insertBefore(node, lineView.gutter || lineView.text);
                else
                  wrap.appendChild(node);
                signalLater(widget, "redraw");
              }
            }
          
            function positionLineWidget(widget, node, lineView, dims) {
              if (widget.noHScroll) {
                (lineView.alignable || (lineView.alignable = [])).push(node);
                var width = dims.wrapperWidth;
                node.style.left = dims.fixedPos + "px";
                if (!widget.coverGutter) {
                  width -= dims.gutterTotalWidth;
                  node.style.paddingLeft = dims.gutterTotalWidth + "px";
                }
                node.style.width = width + "px";
              }
              if (widget.coverGutter) {
                node.style.zIndex = 5;
                node.style.position = "relative";
                if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
              }
            }
          
            // POSITION OBJECT
          
            // A Pos instance represents a position within the text.
            var Pos = CodeMirror.Pos = function(line, ch) {
              if (!(this instanceof Pos)) return new Pos(line, ch);
              this.line = line; this.ch = ch;
            };
          
            // Compare two positions, return 0 if they are the same, a negative
            // number when a is less, and a positive number otherwise.
            var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; };
          
            function copyPos(x) {return Pos(x.line, x.ch);}
            function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; }
            function minPos(a, b) { return cmp(a, b) < 0 ? a : b; }
          
            // INPUT HANDLING
          
            function ensureFocus(cm) {
              if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }
            }
          
            function isReadOnly(cm) {
              return cm.options.readOnly || cm.doc.cantEdit;
            }
          
            // This will be set to an array of strings when copying, so that,
            // when pasting, we know what kind of selections the copied text
            // was made out of.
            var lastCopied = null;
          
            function applyTextInput(cm, inserted, deleted, sel, origin) {
              var doc = cm.doc;
              cm.display.shift = false;
              if (!sel) sel = doc.sel;
          
              var textLines = splitLines(inserted), multiPaste = null;
              // When pasing N lines into N selections, insert one line per selection
              if (cm.state.pasteIncoming && sel.ranges.length > 1) {
                if (lastCopied && lastCopied.join("\n") == inserted)
                  multiPaste = sel.ranges.length % lastCopied.length == 0 && map(lastCopied, splitLines);
                else if (textLines.length == sel.ranges.length)
                  multiPaste = map(textLines, function(l) { return [l]; });
              }
          
              // Normal behavior is to insert the new text into every selection
              for (var i = sel.ranges.length - 1; i >= 0; i--) {
                var range = sel.ranges[i];
                var from = range.from(), to = range.to();
                if (range.empty()) {
                  if (deleted && deleted > 0) // Handle deletion
                    from = Pos(from.line, from.ch - deleted);
                  else if (cm.state.overwrite && !cm.state.pasteIncoming) // Handle overwrite
                    to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));
                }
                var updateInput = cm.curOp.updateInput;
                var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,
                                   origin: origin || (cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input")};
                makeChange(cm.doc, changeEvent);
                signalLater(cm, "inputRead", cm, changeEvent);
              }
              if (inserted && !cm.state.pasteIncoming)
                triggerElectric(cm, inserted);
          
              ensureCursorVisible(cm);
              cm.curOp.updateInput = updateInput;
              cm.curOp.typing = true;
              cm.state.pasteIncoming = cm.state.cutIncoming = false;
            }
          
            function triggerElectric(cm, inserted) {
              // When an 'electric' character is inserted, immediately trigger a reindent
              if (!cm.options.electricChars || !cm.options.smartIndent) return;
              var sel = cm.doc.sel;
          
              for (var i = sel.ranges.length - 1; i >= 0; i--) {
                var range = sel.ranges[i];
                if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) continue;
                var mode = cm.getModeAt(range.head);
                var indented = false;
                if (mode.electricChars) {
                  for (var j = 0; j < mode.electricChars.length; j++)
                    if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
                      indented = indentLine(cm, range.head.line, "smart");
                      break;
                    }
                } else if (mode.electricInput) {
                  if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
                    indented = indentLine(cm, range.head.line, "smart");
                }
                if (indented) signalLater(cm, "electricInput", cm, range.head.line);
              }
            }
          
            function copyableRanges(cm) {
              var text = [], ranges = [];
              for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
                var line = cm.doc.sel.ranges[i].head.line;
                var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
                ranges.push(lineRange);
                text.push(cm.getRange(lineRange.anchor, lineRange.head));
              }
              return {text: text, ranges: ranges};
            }
          
            function disableBrowserMagic(field) {
              field.setAttribute("autocorrect", "off");
              field.setAttribute("autocapitalize", "off");
              field.setAttribute("spellcheck", "false");
            }
          
            // TEXTAREA INPUT STYLE
          
            function TextareaInput(cm) {
              this.cm = cm;
              // See input.poll and input.reset
              this.prevInput = "";
          
              // Flag that indicates whether we expect input to appear real soon
              // now (after some event like 'keypress' or 'input') and are
              // polling intensively.
              this.pollingFast = false;
              // Self-resetting timeout for the poller
              this.polling = new Delayed();
              // Tracks when input.reset has punted to just putting a short
              // string into the textarea instead of the full selection.
              this.inaccurateSelection = false;
              // Used to work around IE issue with selection being forgotten when focus moves away from textarea
              this.hasSelection = false;
              this.composing = null;
            };
          
            function hiddenTextarea() {
              var te = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none");
              var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
              // The textarea is kept positioned near the cursor to prevent the
              // fact that it'll be scrolled into view on input from scrolling
              // our fake cursor out of view. On webkit, when wrap=off, paste is
              // very slow. So make the area wide instead.
              if (webkit) te.style.width = "1000px";
              else te.setAttribute("wrap", "off");
              // If border: 0; -- iOS fails to open keyboard (issue #1287)
              if (ios) te.style.border = "1px solid black";
              disableBrowserMagic(te);
              return div;
            }
          
            TextareaInput.prototype = copyObj({
              init: function(display) {
                var input = this, cm = this.cm;
          
                // Wraps and hides input textarea
                var div = this.wrapper = hiddenTextarea();
                // The semihidden textarea that is focused when the editor is
                // focused, and receives input.
                var te = this.textarea = div.firstChild;
                display.wrapper.insertBefore(div, display.wrapper.firstChild);
          
                // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
                if (ios) te.style.width = "0px";
          
                on(te, "input", function() {
                  if (ie && ie_version >= 9 && input.hasSelection) input.hasSelection = null;
                  input.poll();
                });
          
                on(te, "paste", function() {
                  // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206
                  // Add a char to the end of textarea before paste occur so that
                  // selection doesn't span to the end of textarea.
                  if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {
                    var start = te.selectionStart, end = te.selectionEnd;
                    te.value += "$";
                    // The selection end needs to be set before the start, otherwise there
                    // can be an intermediate non-empty selection between the two, which
                    // can override the middle-click paste buffer on linux and cause the
                    // wrong thing to get pasted.
                    te.selectionEnd = end;
                    te.selectionStart = start;
                    cm.state.fakedLastChar = true;
                  }
                  cm.state.pasteIncoming = true;
                  input.fastPoll();
                });
          
                function prepareCopyCut(e) {
                  if (cm.somethingSelected()) {
                    lastCopied = cm.getSelections();
                    if (input.inaccurateSelection) {
                      input.prevInput = "";
                      input.inaccurateSelection = false;
                      te.value = lastCopied.join("\n");
                      selectInput(te);
                    }
                  } else if (!cm.options.lineWiseCopyCut) {
                    return;
                  } else {
                    var ranges = copyableRanges(cm);
                    lastCopied = ranges.text;
                    if (e.type == "cut") {
                      cm.setSelections(ranges.ranges, null, sel_dontScroll);
                    } else {
                      input.prevInput = "";
                      te.value = ranges.text.join("\n");
                      selectInput(te);
                    }
                  }
                  if (e.type == "cut") cm.state.cutIncoming = true;
                }
                on(te, "cut", prepareCopyCut);
                on(te, "copy", prepareCopyCut);
          
                on(display.scroller, "paste", function(e) {
                  if (eventInWidget(display, e)) return;
                  cm.state.pasteIncoming = true;
                  input.focus();
                });
          
                // Prevent normal selection in the editor (we handle our own)
                on(display.lineSpace, "selectstart", function(e) {
                  if (!eventInWidget(display, e)) e_preventDefault(e);
                });
          
                on(te, "compositionstart", function() {
                  var start = cm.getCursor("from");
                  input.composing = {
                    start: start,
                    range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
                  };
                });
                on(te, "compositionend", function() {
                  if (input.composing) {
                    input.poll();
                    input.composing.range.clear();
                    input.composing = null;
                  }
                });
              },
          
              prepareSelection: function() {
                // Redraw the selection and/or cursor
                var cm = this.cm, display = cm.display, doc = cm.doc;
                var result = prepareSelection(cm);
          
                // Move the hidden textarea near the cursor to prevent scrolling artifacts
                if (cm.options.moveInputWithCursor) {
                  var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
                  var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
                  result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
                                                      headPos.top + lineOff.top - wrapOff.top));
                  result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
                                                       headPos.left + lineOff.left - wrapOff.left));
                }
          
                return result;
              },
          
              showSelection: function(drawn) {
                var cm = this.cm, display = cm.display;
                removeChildrenAndAdd(display.cursorDiv, drawn.cursors);
                removeChildrenAndAdd(display.selectionDiv, drawn.selection);
                if (drawn.teTop != null) {
                  this.wrapper.style.top = drawn.teTop + "px";
                  this.wrapper.style.left = drawn.teLeft + "px";
                }
              },
          
              // Reset the input to correspond to the selection (or to be empty,
              // when not typing and nothing is selected)
              reset: function(typing) {
                if (this.contextMenuPending) return;
                var minimal, selected, cm = this.cm, doc = cm.doc;
                if (cm.somethingSelected()) {
                  this.prevInput = "";
                  var range = doc.sel.primary();
                  minimal = hasCopyEvent &&
                    (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000);
                  var content = minimal ? "-" : selected || cm.getSelection();
                  this.textarea.value = content;
                  if (cm.state.focused) selectInput(this.textarea);
                  if (ie && ie_version >= 9) this.hasSelection = content;
                } else if (!typing) {
                  this.prevInput = this.textarea.value = "";
                  if (ie && ie_version >= 9) this.hasSelection = null;
                }
                this.inaccurateSelection = minimal;
              },
          
              getField: function() { return this.textarea; },
          
              supportsTouch: function() { return false; },
          
              focus: function() {
                if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
                  try { this.textarea.focus(); }
                  catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
                }
              },
          
              blur: function() { this.textarea.blur(); },
          
              resetPosition: function() {
                this.wrapper.style.top = this.wrapper.style.left = 0;
              },
          
              receivedFocus: function() { this.slowPoll(); },
          
              // Poll for input changes, using the normal rate of polling. This
              // runs as long as the editor is focused.
              slowPoll: function() {
                var input = this;
                if (input.pollingFast) return;
                input.polling.set(this.cm.options.pollInterval, function() {
                  input.poll();
                  if (input.cm.state.focused) input.slowPoll();
                });
              },
          
              // When an event has just come in that is likely to add or change
              // something in the input textarea, we poll faster, to ensure that
              // the change appears on the screen quickly.
              fastPoll: function() {
                var missed = false, input = this;
                input.pollingFast = true;
                function p() {
                  var changed = input.poll();
                  if (!changed && !missed) {missed = true; input.polling.set(60, p);}
                  else {input.pollingFast = false; input.slowPoll();}
                }
                input.polling.set(20, p);
              },
          
              // Read input from the textarea, and update the document to match.
              // When something is selected, it is present in the textarea, and
              // selected (unless it is huge, in which case a placeholder is
              // used). When nothing is selected, the cursor sits after previously
              // seen text (can be empty), which is stored in prevInput (we must
              // not reset the textarea when typing, because that breaks IME).
              poll: function() {
                var cm = this.cm, input = this.textarea, prevInput = this.prevInput;
                // Since this is called a *lot*, try to bail out as cheaply as
                // possible when it is clear that nothing happened. hasSelection
                // will be the case when there is a lot of text in the textarea,
                // in which case reading its value would be expensive.
                if (!cm.state.focused || (hasSelection(input) && !prevInput) ||
                    isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq)
                  return false;
                // See paste handler for more on the fakedLastChar kludge
                if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
                  input.value = input.value.substring(0, input.value.length - 1);
                  cm.state.fakedLastChar = false;
                }
                var text = input.value;
                // If nothing changed, bail.
                if (text == prevInput && !cm.somethingSelected()) return false;
                // Work around nonsensical selection resetting in IE9/10, and
                // inexplicable appearance of private area unicode characters on
                // some key combos in Mac (#2689).
                if (ie && ie_version >= 9 && this.hasSelection === text ||
                    mac && /[\uf700-\uf7ff]/.test(text)) {
                  cm.display.input.reset();
                  return false;
                }
          
                if (cm.doc.sel == cm.display.selForContextMenu) {
                  var first = text.charCodeAt(0);
                  if (first == 0x200b && !prevInput) prevInput = "\u200b";
                  if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo"); }
                }
                // Find the part of the input that is actually new
                var same = 0, l = Math.min(prevInput.length, text.length);
                while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
          
                var self = this;
                runInOp(cm, function() {
                  applyTextInput(cm, text.slice(same), prevInput.length - same,
                                 null, self.composing ? "*compose" : null);
          
                  // Don't leave long text in the textarea, since it makes further polling slow
                  if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = "";
                  else self.prevInput = text;
          
                  if (self.composing) {
                    self.composing.range.clear();
                    self.composing.range = cm.markText(self.composing.start, cm.getCursor("to"),
                                                       {className: "CodeMirror-composing"});
                  }
                });
                return true;
              },
          
              ensurePolled: function() {
                if (this.pollingFast && this.poll()) this.pollingFast = false;
              },
          
              onKeyPress: function() {
                if (ie && ie_version >= 9) this.hasSelection = null;
                this.fastPoll();
              },
          
              onContextMenu: function(e) {
                var input = this, cm = input.cm, display = cm.display, te = input.textarea;
                var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
                if (!pos || presto) return; // Opera is difficult.
          
                // Reset the current text selection only if the click is done outside of the selection
                // and 'resetSelectionOnContextMenu' option is true.
                var reset = cm.options.resetSelectionOnContextMenu;
                if (reset && cm.doc.sel.contains(pos) == -1)
                  operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll);
          
                var oldCSS = te.style.cssText;
                input.wrapper.style.position = "absolute";
                te.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
                  "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " +
                  (ie ? "rgba(255, 255, 255, .05)" : "transparent") +
                  "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
                if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712)
                display.input.focus();
                if (webkit) window.scrollTo(null, oldScrollY);
                display.input.reset();
                // Adds "Select all" to context menu in FF
                if (!cm.somethingSelected()) te.value = input.prevInput = " ";
                input.contextMenuPending = true;
                display.selForContextMenu = cm.doc.sel;
                clearTimeout(display.detectingSelectAll);
          
                // Select-all will be greyed out if there's nothing to select, so
                // this adds a zero-width space so that we can later check whether
                // it got selected.
                function prepareSelectAllHack() {
                  if (te.selectionStart != null) {
                    var selected = cm.somethingSelected();
                    var extval = "\u200b" + (selected ? te.value : "");
                    te.value = "\u21da"; // Used to catch context-menu undo
                    te.value = extval;
                    input.prevInput = selected ? "" : "\u200b";
                    te.selectionStart = 1; te.selectionEnd = extval.length;
                    // Re-set this, in case some other handler touched the
                    // selection in the meantime.
                    display.selForContextMenu = cm.doc.sel;
                  }
                }
                function rehide() {
                  input.contextMenuPending = false;
                  input.wrapper.style.position = "relative";
                  te.style.cssText = oldCSS;
                  if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos);
          
                  // Try to detect the user choosing select-all
                  if (te.selectionStart != null) {
                    if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();
                    var i = 0, poll = function() {
                      if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
                          te.selectionEnd > 0 && input.prevInput == "\u200b")
                        operation(cm, commands.selectAll)(cm);
                      else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);
                      else display.input.reset();
                    };
                    display.detectingSelectAll = setTimeout(poll, 200);
                  }
                }
          
                if (ie && ie_version >= 9) prepareSelectAllHack();
                if (captureRightClick) {
                  e_stop(e);
                  var mouseup = function() {
                    off(window, "mouseup", mouseup);
                    setTimeout(rehide, 20);
                  };
                  on(window, "mouseup", mouseup);
                } else {
                  setTimeout(rehide, 50);
                }
              },
          
              setUneditable: nothing,
          
              needsContentAttribute: false
            }, TextareaInput.prototype);
          
            // CONTENTEDITABLE INPUT STYLE
          
            function ContentEditableInput(cm) {
              this.cm = cm;
              this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;
              this.polling = new Delayed();
              this.gracePeriod = false;
            }
          
            ContentEditableInput.prototype = copyObj({
              init: function(display) {
                var input = this, cm = input.cm;
                var div = input.div = display.lineDiv;
                div.contentEditable = "true";
                disableBrowserMagic(div);
          
                on(div, "paste", function(e) {
                  var pasted = e.clipboardData && e.clipboardData.getData("text/plain");
                  if (pasted) {
                    e.preventDefault();
                    cm.replaceSelection(pasted, null, "paste");
                  }
                });
          
                on(div, "compositionstart", function(e) {
                  var data = e.data;
                  input.composing = {sel: cm.doc.sel, data: data, startData: data};
                  if (!data) return;
                  var prim = cm.doc.sel.primary();
                  var line = cm.getLine(prim.head.line);
                  var found = line.indexOf(data, Math.max(0, prim.head.ch - data.length));
                  if (found > -1 && found <= prim.head.ch)
                    input.composing.sel = simpleSelection(Pos(prim.head.line, found),
                                                          Pos(prim.head.line, found + data.length));
                });
                on(div, "compositionupdate", function(e) {
                  input.composing.data = e.data;
                });
                on(div, "compositionend", function(e) {
                  var ours = input.composing;
                  if (!ours) return;
                  if (e.data != ours.startData && !/\u200b/.test(e.data))
                    ours.data = e.data;
                  // Need a small delay to prevent other code (input event,
                  // selection polling) from doing damage when fired right after
                  // compositionend.
                  setTimeout(function() {
                    if (!ours.handled)
                      input.applyComposition(ours);
                    if (input.composing == ours)
                      input.composing = null;
                  }, 50);
                });
          
                on(div, "touchstart", function() {
                  input.forceCompositionEnd();
                });
          
                on(div, "input", function() {
                  if (input.composing) return;
                  if (!input.pollContent())
                    runInOp(input.cm, function() {regChange(cm);});
                });
          
                function onCopyCut(e) {
                  if (cm.somethingSelected()) {
                    lastCopied = cm.getSelections();
                    if (e.type == "cut") cm.replaceSelection("", null, "cut");
                  } else if (!cm.options.lineWiseCopyCut) {
                    return;
                  } else {
                    var ranges = copyableRanges(cm);
                    lastCopied = ranges.text;
                    if (e.type == "cut") {
                      cm.operation(function() {
                        cm.setSelections(ranges.ranges, 0, sel_dontScroll);
                        cm.replaceSelection("", null, "cut");
                      });
                    }
                  }
                  // iOS exposes the clipboard API, but seems to discard content inserted into it
                  if (e.clipboardData && !ios) {
                    e.preventDefault();
                    e.clipboardData.clearData();
                    e.clipboardData.setData("text/plain", lastCopied.join("\n"));
                  } else {
                    // Old-fashioned briefly-focus-a-textarea hack
                    var kludge = hiddenTextarea(), te = kludge.firstChild;
                    cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
                    te.value = lastCopied.join("\n");
                    var hadFocus = document.activeElement;
                    selectInput(te);
                    setTimeout(function() {
                      cm.display.lineSpace.removeChild(kludge);
                      hadFocus.focus();
                    }, 50);
                  }
                }
                on(div, "copy", onCopyCut);
                on(div, "cut", onCopyCut);
              },
          
              prepareSelection: function() {
                var result = prepareSelection(this.cm, false);
                result.focus = this.cm.state.focused;
                return result;
              },
          
              showSelection: function(info) {
                if (!info || !this.cm.display.view.length) return;
                if (info.focus) this.showPrimarySelection();
                this.showMultipleSelections(info);
              },
          
              showPrimarySelection: function() {
                var sel = window.getSelection(), prim = this.cm.doc.sel.primary();
                var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset);
                var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset);
                if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
                    cmp(minPos(curAnchor, curFocus), prim.from()) == 0 &&
                    cmp(maxPos(curAnchor, curFocus), prim.to()) == 0)
                  return;
          
                var start = posToDOM(this.cm, prim.from());
                var end = posToDOM(this.cm, prim.to());
                if (!start && !end) return;
          
                var view = this.cm.display.view;
                var old = sel.rangeCount && sel.getRangeAt(0);
                if (!start) {
                  start = {node: view[0].measure.map[2], offset: 0};
                } else if (!end) { // FIXME dangerously hacky
                  var measure = view[view.length - 1].measure;
                  var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;
                  end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]};
                }
          
                try { var rng = range(start.node, start.offset, end.offset, end.node); }
                catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
                if (rng) {
                  sel.removeAllRanges();
                  sel.addRange(rng);
                  if (old && sel.anchorNode == null) sel.addRange(old);
                  else if (gecko) this.startGracePeriod();
                }
                this.rememberSelection();
              },
          
              startGracePeriod: function() {
                var input = this;
                clearTimeout(this.gracePeriod);
                this.gracePeriod = setTimeout(function() {
                  input.gracePeriod = false;
                  if (input.selectionChanged())
                    input.cm.operation(function() { input.cm.curOp.selectionChanged = true; });
                }, 20);
              },
          
              showMultipleSelections: function(info) {
                removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);
                removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);
              },
          
              rememberSelection: function() {
                var sel = window.getSelection();
                this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset;
                this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset;
              },
          
              selectionInEditor: function() {
                var sel = window.getSelection();
                if (!sel.rangeCount) return false;
                var node = sel.getRangeAt(0).commonAncestorContainer;
                return contains(this.div, node);
              },
          
              focus: function() {
                if (this.cm.options.readOnly != "nocursor") this.div.focus();
              },
              blur: function() { this.div.blur(); },
              getField: function() { return this.div; },
          
              supportsTouch: function() { return true; },
          
              receivedFocus: function() {
                var input = this;
                if (this.selectionInEditor())
                  this.pollSelection();
                else
                  runInOp(this.cm, function() { input.cm.curOp.selectionChanged = true; });
          
                function poll() {
                  if (input.cm.state.focused) {
                    input.pollSelection();
                    input.polling.set(input.cm.options.pollInterval, poll);
                  }
                }
                this.polling.set(this.cm.options.pollInterval, poll);
              },
          
              selectionChanged: function() {
                var sel = window.getSelection();
                return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
                  sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset;
              },
          
              pollSelection: function() {
                if (!this.composing && !this.gracePeriod && this.selectionChanged()) {
                  var sel = window.getSelection(), cm = this.cm;
                  this.rememberSelection();
                  var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
                  var head = domToPos(cm, sel.focusNode, sel.focusOffset);
                  if (anchor && head) runInOp(cm, function() {
                    setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll);
                    if (anchor.bad || head.bad) cm.curOp.selectionChanged = true;
                  });
                }
              },
          
              pollContent: function() {
                var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary();
                var from = sel.from(), to = sel.to();
                if (from.line < display.viewFrom || to.line > display.viewTo - 1) return false;
          
                var fromIndex;
                if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
                  var fromLine = lineNo(display.view[0].line);
                  var fromNode = display.view[0].node;
                } else {
                  var fromLine = lineNo(display.view[fromIndex].line);
                  var fromNode = display.view[fromIndex - 1].node.nextSibling;
                }
                var toIndex = findViewIndex(cm, to.line);
                if (toIndex == display.view.length - 1) {
                  var toLine = display.viewTo - 1;
                  var toNode = display.view[toIndex].node;
                } else {
                  var toLine = lineNo(display.view[toIndex + 1].line) - 1;
                  var toNode = display.view[toIndex + 1].node.previousSibling;
                }
          
                var newText = splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));
                var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));
                while (newText.length > 1 && oldText.length > 1) {
                  if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }
                  else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; }
                  else break;
                }
          
                var cutFront = 0, cutEnd = 0;
                var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length);
                while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
                  ++cutFront;
                var newBot = lst(newText), oldBot = lst(oldText);
                var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
                                         oldBot.length - (oldText.length == 1 ? cutFront : 0));
                while (cutEnd < maxCutEnd &&
                       newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
                  ++cutEnd;
          
                newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd);
                newText[0] = newText[0].slice(cutFront);
          
                var chFrom = Pos(fromLine, cutFront);
                var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0);
                if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
                  replaceRange(cm.doc, newText, chFrom, chTo, "+input");
                  return true;
                }
              },
          
              ensurePolled: function() {
                this.forceCompositionEnd();
              },
              reset: function() {
                this.forceCompositionEnd();
              },
              forceCompositionEnd: function() {
                if (!this.composing || this.composing.handled) return;
                this.applyComposition(this.composing);
                this.composing.handled = true;
                this.div.blur();
                this.div.focus();
              },
              applyComposition: function(composing) {
                if (composing.data && composing.data != composing.startData)
                  operation(this.cm, applyTextInput)(this.cm, composing.data, 0, composing.sel);
              },
          
              setUneditable: function(node) {
                node.setAttribute("contenteditable", "false");
              },
          
              onKeyPress: function(e) {
                e.preventDefault();
                operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0);
              },
          
              onContextMenu: nothing,
              resetPosition: nothing,
          
              needsContentAttribute: true
            }, ContentEditableInput.prototype);
          
            function posToDOM(cm, pos) {
              var view = findViewForLine(cm, pos.line);
              if (!view || view.hidden) return null;
              var line = getLine(cm.doc, pos.line);
              var info = mapFromLineView(view, line, pos.line);
          
              var order = getOrder(line), side = "left";
              if (order) {
                var partPos = getBidiPartAt(order, pos.ch);
                side = partPos % 2 ? "right" : "left";
              }
              var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);
              result.offset = result.collapse == "right" ? result.end : result.start;
              return result;
            }
          
            function badPos(pos, bad) { if (bad) pos.bad = true; return pos; }
          
            function domToPos(cm, node, offset) {
              var lineNode;
              if (node == cm.display.lineDiv) {
                lineNode = cm.display.lineDiv.childNodes[offset];
                if (!lineNode) return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true);
                node = null; offset = 0;
              } else {
                for (lineNode = node;; lineNode = lineNode.parentNode) {
                  if (!lineNode || lineNode == cm.display.lineDiv) return null;
                  if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) break;
                }
              }
              for (var i = 0; i < cm.display.view.length; i++) {
                var lineView = cm.display.view[i];
                if (lineView.node == lineNode)
                  return locateNodeInLineView(lineView, node, offset);
              }
            }
          
            function locateNodeInLineView(lineView, node, offset) {
              var wrapper = lineView.text.firstChild, bad = false;
              if (!node || !contains(wrapper, node)) return badPos(Pos(lineNo(lineView.line), 0), true);
              if (node == wrapper) {
                bad = true;
                node = wrapper.childNodes[offset];
                offset = 0;
                if (!node) {
                  var line = lineView.rest ? lst(lineView.rest) : lineView.line;
                  return badPos(Pos(lineNo(line), line.text.length), bad);
                }
              }
          
              var textNode = node.nodeType == 3 ? node : null, topNode = node;
              if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
                textNode = node.firstChild;
                if (offset) offset = textNode.nodeValue.length;
              }
              while (topNode.parentNode != wrapper) topNode = topNode.parentNode;
              var measure = lineView.measure, maps = measure.maps;
          
              function find(textNode, topNode, offset) {
                for (var i = -1; i < (maps ? maps.length : 0); i++) {
                  var map = i < 0 ? measure.map : maps[i];
                  for (var j = 0; j < map.length; j += 3) {
                    var curNode = map[j + 2];
                    if (curNode == textNode || curNode == topNode) {
                      var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);
                      var ch = map[j] + offset;
                      if (offset < 0 || curNode != textNode) ch = map[j + (offset ? 1 : 0)];
                      return Pos(line, ch);
                    }
                  }
                }
              }
              var found = find(textNode, topNode, offset);
              if (found) return badPos(found, bad);
          
              // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
              for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
                found = find(after, after.firstChild, 0);
                if (found)
                  return badPos(Pos(found.line, found.ch - dist), bad);
                else
                  dist += after.textContent.length;
              }
              for (var before = topNode.previousSibling, dist = offset; before; before = before.previousSibling) {
                found = find(before, before.firstChild, -1);
                if (found)
                  return badPos(Pos(found.line, found.ch + dist), bad);
                else
                  dist += after.textContent.length;
              }
            }
          
            function domTextBetween(cm, from, to, fromLine, toLine) {
              var text = "", closing = false;
              function recognizeMarker(id) { return function(marker) { return marker.id == id; }; }
              function walk(node) {
                if (node.nodeType == 1) {
                  var cmText = node.getAttribute("cm-text");
                  if (cmText != null) {
                    if (cmText == "") cmText = node.textContent.replace(/\u200b/g, "");
                    text += cmText;
                    return;
                  }
                  var markerID = node.getAttribute("cm-marker"), range;
                  if (markerID) {
                    var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));
                    if (found.length && (range = found[0].find()))
                      text += getBetween(cm.doc, range.from, range.to).join("\n");
                    return;
                  }
                  if (node.getAttribute("contenteditable") == "false") return;
                  for (var i = 0; i < node.childNodes.length; i++)
                    walk(node.childNodes[i]);
                  if (/^(pre|div|p)$/i.test(node.nodeName))
                    closing = true;
                } else if (node.nodeType == 3) {
                  var val = node.nodeValue;
                  if (!val) return;
                  if (closing) {
                    text += "\n";
                    closing = false;
                  }
                  text += val;
                }
              }
              for (;;) {
                walk(from);
                if (from == to) break;
                from = from.nextSibling;
              }
              return text;
            }
          
            CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput};
          
            // SELECTION / CURSOR
          
            // Selection objects are immutable. A new one is created every time
            // the selection changes. A selection is one or more non-overlapping
            // (and non-touching) ranges, sorted, and an integer that indicates
            // which one is the primary selection (the one that's scrolled into
            // view, that getCursor returns, etc).
            function Selection(ranges, primIndex) {
              this.ranges = ranges;
              this.primIndex = primIndex;
            }
          
            Selection.prototype = {
              primary: function() { return this.ranges[this.primIndex]; },
              equals: function(other) {
                if (other == this) return true;
                if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false;
                for (var i = 0; i < this.ranges.length; i++) {
                  var here = this.ranges[i], there = other.ranges[i];
                  if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false;
                }
                return true;
              },
              deepCopy: function() {
                for (var out = [], i = 0; i < this.ranges.length; i++)
                  out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head));
                return new Selection(out, this.primIndex);
              },
              somethingSelected: function() {
                for (var i = 0; i < this.ranges.length; i++)
                  if (!this.ranges[i].empty()) return true;
                return false;
              },
              contains: function(pos, end) {
                if (!end) end = pos;
                for (var i = 0; i < this.ranges.length; i++) {
                  var range = this.ranges[i];
                  if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
                    return i;
                }
                return -1;
              }
            };
          
            function Range(anchor, head) {
              this.anchor = anchor; this.head = head;
            }
          
            Range.prototype = {
              from: function() { return minPos(this.anchor, this.head); },
              to: function() { return maxPos(this.anchor, this.head); },
              empty: function() {
                return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch;
              }
            };
          
            // Take an unsorted, potentially overlapping set of ranges, and
            // build a selection out of it. 'Consumes' ranges array (modifying
            // it).
            function normalizeSelection(ranges, primIndex) {
              var prim = ranges[primIndex];
              ranges.sort(function(a, b) { return cmp(a.from(), b.from()); });
              primIndex = indexOf(ranges, prim);
              for (var i = 1; i < ranges.length; i++) {
                var cur = ranges[i], prev = ranges[i - 1];
                if (cmp(prev.to(), cur.from()) >= 0) {
                  var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());
                  var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;
                  if (i <= primIndex) --primIndex;
                  ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));
                }
              }
              return new Selection(ranges, primIndex);
            }
          
            function simpleSelection(anchor, head) {
              return new Selection([new Range(anchor, head || anchor)], 0);
            }
          
            // Most of the external API clips given positions to make sure they
            // actually exist within the document.
            function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
            function clipPos(doc, pos) {
              if (pos.line < doc.first) return Pos(doc.first, 0);
              var last = doc.first + doc.size - 1;
              if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
              return clipToLen(pos, getLine(doc, pos.line).text.length);
            }
            function clipToLen(pos, linelen) {
              var ch = pos.ch;
              if (ch == null || ch > linelen) return Pos(pos.line, linelen);
              else if (ch < 0) return Pos(pos.line, 0);
              else return pos;
            }
            function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
            function clipPosArray(doc, array) {
              for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]);
              return out;
            }
          
            // SELECTION UPDATES
          
            // The 'scroll' parameter given to many of these indicated whether
            // the new cursor position should be scrolled into view after
            // modifying the selection.
          
            // If shift is held or the extend flag is set, extends a range to
            // include a given position (and optionally a second position).
            // Otherwise, simply returns the range between the given positions.
            // Used for cursor motion and such.
            function extendRange(doc, range, head, other) {
              if (doc.cm && doc.cm.display.shift || doc.extend) {
                var anchor = range.anchor;
                if (other) {
                  var posBefore = cmp(head, anchor) < 0;
                  if (posBefore != (cmp(other, anchor) < 0)) {
                    anchor = head;
                    head = other;
                  } else if (posBefore != (cmp(head, other) < 0)) {
                    head = other;
                  }
                }
                return new Range(anchor, head);
              } else {
                return new Range(other || head, head);
              }
            }
          
            // Extend the primary selection range, discard the rest.
            function extendSelection(doc, head, other, options) {
              setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options);
            }
          
            // Extend all selections (pos is an array of selections with length
            // equal the number of selections)
            function extendSelections(doc, heads, options) {
              for (var out = [], i = 0; i < doc.sel.ranges.length; i++)
                out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null);
              var newSel = normalizeSelection(out, doc.sel.primIndex);
              setSelection(doc, newSel, options);
            }
          
            // Updates a single range in the selection.
            function replaceOneSelection(doc, i, range, options) {
              var ranges = doc.sel.ranges.slice(0);
              ranges[i] = range;
              setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options);
            }
          
            // Reset the selection to a single range.
            function setSimpleSelection(doc, anchor, head, options) {
              setSelection(doc, simpleSelection(anchor, head), options);
            }
          
            // Give beforeSelectionChange handlers a change to influence a
            // selection update.
            function filterSelectionChange(doc, sel) {
              var obj = {
                ranges: sel.ranges,
                update: function(ranges) {
                  this.ranges = [];
                  for (var i = 0; i < ranges.length; i++)
                    this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
                                               clipPos(doc, ranges[i].head));
                }
              };
              signal(doc, "beforeSelectionChange", doc, obj);
              if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
              if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1);
              else return sel;
            }
          
            function setSelectionReplaceHistory(doc, sel, options) {
              var done = doc.history.done, last = lst(done);
              if (last && last.ranges) {
                done[done.length - 1] = sel;
                setSelectionNoUndo(doc, sel, options);
              } else {
                setSelection(doc, sel, options);
              }
            }
          
            // Set a new selection.
            function setSelection(doc, sel, options) {
              setSelectionNoUndo(doc, sel, options);
              addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);
            }
          
            function setSelectionNoUndo(doc, sel, options) {
              if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
                sel = filterSelectionChange(doc, sel);
          
              var bias = options && options.bias ||
                (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
              setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
          
              if (!(options && options.scroll === false) && doc.cm)
                ensureCursorVisible(doc.cm);
            }
          
            function setSelectionInner(doc, sel) {
              if (sel.equals(doc.sel)) return;
          
              doc.sel = sel;
          
              if (doc.cm) {
                doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true;
                signalCursorActivity(doc.cm);
              }
              signalLater(doc, "cursorActivity", doc);
            }
          
            // Verify that the selection does not partially select any atomic
            // marked ranges.
            function reCheckSelection(doc) {
              setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll);
            }
          
            // Return a selection that does not partially select any atomic
            // ranges.
            function skipAtomicInSelection(doc, sel, bias, mayClear) {
              var out;
              for (var i = 0; i < sel.ranges.length; i++) {
                var range = sel.ranges[i];
                var newAnchor = skipAtomic(doc, range.anchor, bias, mayClear);
                var newHead = skipAtomic(doc, range.head, bias, mayClear);
                if (out || newAnchor != range.anchor || newHead != range.head) {
                  if (!out) out = sel.ranges.slice(0, i);
                  out[i] = new Range(newAnchor, newHead);
                }
              }
              return out ? normalizeSelection(out, sel.primIndex) : sel;
            }
          
            // Ensure a given position is not inside an atomic range.
            function skipAtomic(doc, pos, bias, mayClear) {
              var flipped = false, curPos = pos;
              var dir = bias || 1;
              doc.cantEdit = false;
              search: for (;;) {
                var line = getLine(doc, curPos.line);
                if (line.markedSpans) {
                  for (var i = 0; i < line.markedSpans.length; ++i) {
                    var sp = line.markedSpans[i], m = sp.marker;
                    if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
                        (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
                      if (mayClear) {
                        signal(m, "beforeCursorEnter");
                        if (m.explicitlyCleared) {
                          if (!line.markedSpans) break;
                          else {--i; continue;}
                        }
                      }
                      if (!m.atomic) continue;
                      var newPos = m.find(dir < 0 ? -1 : 1);
                      if (cmp(newPos, curPos) == 0) {
                        newPos.ch += dir;
                        if (newPos.ch < 0) {
                          if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
                          else newPos = null;
                        } else if (newPos.ch > line.text.length) {
                          if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
                          else newPos = null;
                        }
                        if (!newPos) {
                          if (flipped) {
                            // Driven in a corner -- no valid cursor position found at all
                            // -- try again *with* clearing, if we didn't already
                            if (!mayClear) return skipAtomic(doc, pos, bias, true);
                            // Otherwise, turn off editing until further notice, and return the start of the doc
                            doc.cantEdit = true;
                            return Pos(doc.first, 0);
                          }
                          flipped = true; newPos = pos; dir = -dir;
                        }
                      }
                      curPos = newPos;
                      continue search;
                    }
                  }
                }
                return curPos;
              }
            }
          
            // SELECTION DRAWING
          
            function updateSelection(cm) {
              cm.display.input.showSelection(cm.display.input.prepareSelection());
            }
          
            function prepareSelection(cm, primary) {
              var doc = cm.doc, result = {};
              var curFragment = result.cursors = document.createDocumentFragment();
              var selFragment = result.selection = document.createDocumentFragment();
          
              for (var i = 0; i < doc.sel.ranges.length; i++) {
                if (primary === false && i == doc.sel.primIndex) continue;
                var range = doc.sel.ranges[i];
                var collapsed = range.empty();
                if (collapsed || cm.options.showCursorWhenSelecting)
                  drawSelectionCursor(cm, range, curFragment);
                if (!collapsed)
                  drawSelectionRange(cm, range, selFragment);
              }
              return result;
            }
          
            // Draws a cursor for the given range
            function drawSelectionCursor(cm, range, output) {
              var pos = cursorCoords(cm, range.head, "div", null, null, !cm.options.singleCursorHeightPerLine);
          
              var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
              cursor.style.left = pos.left + "px";
              cursor.style.top = pos.top + "px";
              cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
          
              if (pos.other) {
                // Secondary cursor, shown when on a 'jump' in bi-directional text
                var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
                otherCursor.style.display = "";
                otherCursor.style.left = pos.other.left + "px";
                otherCursor.style.top = pos.other.top + "px";
                otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
              }
            }
          
            // Draws the given range as a highlighted selection
            function drawSelectionRange(cm, range, output) {
              var display = cm.display, doc = cm.doc;
              var fragment = document.createDocumentFragment();
              var padding = paddingH(cm.display), leftSide = padding.left;
              var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;
          
              function add(left, top, width, bottom) {
                if (top < 0) top = 0;
                top = Math.round(top);
                bottom = Math.round(bottom);
                fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
                                         "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) +
                                         "px; height: " + (bottom - top) + "px"));
              }
          
              function drawForLine(line, fromArg, toArg) {
                var lineObj = getLine(doc, line);
                var lineLen = lineObj.text.length;
                var start, end;
                function coords(ch, bias) {
                  return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
                }
          
                iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
                  var leftPos = coords(from, "left"), rightPos, left, right;
                  if (from == to) {
                    rightPos = leftPos;
                    left = right = leftPos.left;
                  } else {
                    rightPos = coords(to - 1, "right");
                    if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
                    left = leftPos.left;
                    right = rightPos.right;
                  }
                  if (fromArg == null && from == 0) left = leftSide;
                  if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
                    add(left, leftPos.top, null, leftPos.bottom);
                    left = leftSide;
                    if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
                  }
                  if (toArg == null && to == lineLen) right = rightSide;
                  if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
                    start = leftPos;
                  if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
                    end = rightPos;
                  if (left < leftSide + 1) left = leftSide;
                  add(left, rightPos.top, right - left, rightPos.bottom);
                });
                return {start: start, end: end};
              }
          
              var sFrom = range.from(), sTo = range.to();
              if (sFrom.line == sTo.line) {
                drawForLine(sFrom.line, sFrom.ch, sTo.ch);
              } else {
                var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);
                var singleVLine = visualLine(fromLine) == visualLine(toLine);
                var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;
                var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;
                if (singleVLine) {
                  if (leftEnd.top < rightStart.top - 2) {
                    add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
                    add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);
                  } else {
                    add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
                  }
                }
                if (leftEnd.bottom < rightStart.top)
                  add(leftSide, leftEnd.bottom, null, rightStart.top);
              }
          
              output.appendChild(fragment);
            }
          
            // Cursor-blinking
            function restartBlink(cm) {
              if (!cm.state.focused) return;
              var display = cm.display;
              clearInterval(display.blinker);
              var on = true;
              display.cursorDiv.style.visibility = "";
              if (cm.options.cursorBlinkRate > 0)
                display.blinker = setInterval(function() {
                  display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden";
                }, cm.options.cursorBlinkRate);
              else if (cm.options.cursorBlinkRate < 0)
                display.cursorDiv.style.visibility = "hidden";
            }
          
            // HIGHLIGHT WORKER
          
            function startWorker(cm, time) {
              if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)
                cm.state.highlight.set(time, bind(highlightWorker, cm));
            }
          
            function highlightWorker(cm) {
              var doc = cm.doc;
              if (doc.frontier < doc.first) doc.frontier = doc.first;
              if (doc.frontier >= cm.display.viewTo) return;
              var end = +new Date + cm.options.workTime;
              var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
              var changedLines = [];
          
              doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {
                if (doc.frontier >= cm.display.viewFrom) { // Visible
                  var oldStyles = line.styles;
                  var highlighted = highlightLine(cm, line, state, true);
                  line.styles = highlighted.styles;
                  var oldCls = line.styleClasses, newCls = highlighted.classes;
                  if (newCls) line.styleClasses = newCls;
                  else if (oldCls) line.styleClasses = null;
                  var ischange = !oldStyles || oldStyles.length != line.styles.length ||
                    oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
                  for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
                  if (ischange) changedLines.push(doc.frontier);
                  line.stateAfter = copyState(doc.mode, state);
                } else {
                  processLine(cm, line.text, state);
                  line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
                }
                ++doc.frontier;
                if (+new Date > end) {
                  startWorker(cm, cm.options.workDelay);
                  return true;
                }
              });
              if (changedLines.length) runInOp(cm, function() {
                for (var i = 0; i < changedLines.length; i++)
                  regLineChange(cm, changedLines[i], "text");
              });
            }
          
            // Finds the line to start with when starting a parse. Tries to
            // find a line with a stateAfter, so that it can start with a
            // valid state. If that fails, it returns the line with the
            // smallest indentation, which tends to need the least context to
            // parse correctly.
            function findStartLine(cm, n, precise) {
              var minindent, minline, doc = cm.doc;
              var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
              for (var search = n; search > lim; --search) {
                if (search <= doc.first) return doc.first;
                var line = getLine(doc, search - 1);
                if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
                var indented = countColumn(line.text, null, cm.options.tabSize);
                if (minline == null || minindent > indented) {
                  minline = search - 1;
                  minindent = indented;
                }
              }
              return minline;
            }
          
            function getStateBefore(cm, n, precise) {
              var doc = cm.doc, display = cm.display;
              if (!doc.mode.startState) return true;
              var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
              if (!state) state = startState(doc.mode);
              else state = copyState(doc.mode, state);
              doc.iter(pos, n, function(line) {
                processLine(cm, line.text, state);
                var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo;
                line.stateAfter = save ? copyState(doc.mode, state) : null;
                ++pos;
              });
              if (precise) doc.frontier = pos;
              return state;
            }
          
            // POSITION MEASUREMENT
          
            function paddingTop(display) {return display.lineSpace.offsetTop;}
            function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
            function paddingH(display) {
              if (display.cachedPaddingH) return display.cachedPaddingH;
              var e = removeChildrenAndAdd(display.measure, elt("pre", "x"));
              var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;
              var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};
              if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data;
              return data;
            }
          
            function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; }
            function displayWidth(cm) {
              return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth;
            }
            function displayHeight(cm) {
              return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight;
            }
          
            // Ensure the lineView.wrapping.heights array is populated. This is
            // an array of bottom offsets for the lines that make up a drawn
            // line. When lineWrapping is on, there might be more than one
            // height.
            function ensureLineHeights(cm, lineView, rect) {
              var wrapping = cm.options.lineWrapping;
              var curWidth = wrapping && displayWidth(cm);
              if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
                var heights = lineView.measure.heights = [];
                if (wrapping) {
                  lineView.measure.width = curWidth;
                  var rects = lineView.text.firstChild.getClientRects();
                  for (var i = 0; i < rects.length - 1; i++) {
                    var cur = rects[i], next = rects[i + 1];
                    if (Math.abs(cur.bottom - next.bottom) > 2)
                      heights.push((cur.bottom + next.top) / 2 - rect.top);
                  }
                }
                heights.push(rect.bottom - rect.top);
              }
            }
          
            // Find a line map (mapping character offsets to text nodes) and a
            // measurement cache for the given line number. (A line view might
            // contain multiple lines when collapsed ranges are present.)
            function mapFromLineView(lineView, line, lineN) {
              if (lineView.line == line)
                return {map: lineView.measure.map, cache: lineView.measure.cache};
              for (var i = 0; i < lineView.rest.length; i++)
                if (lineView.rest[i] == line)
                  return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]};
              for (var i = 0; i < lineView.rest.length; i++)
                if (lineNo(lineView.rest[i]) > lineN)
                  return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true};
            }
          
            // Render a line into the hidden node display.externalMeasured. Used
            // when measurement is needed for a line that's not in the viewport.
            function updateExternalMeasurement(cm, line) {
              line = visualLine(line);
              var lineN = lineNo(line);
              var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN);
              view.lineN = lineN;
              var built = view.built = buildLineContent(cm, view);
              view.text = built.pre;
              removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
              return view;
            }
          
            // Get a {top, bottom, left, right} box (in line-local coordinates)
            // for a given character.
            function measureChar(cm, line, ch, bias) {
              return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias);
            }
          
            // Find a line view that corresponds to the given line number.
            function findViewForLine(cm, lineN) {
              if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
                return cm.display.view[findViewIndex(cm, lineN)];
              var ext = cm.display.externalMeasured;
              if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
                return ext;
            }
          
            // Measurement can be split in two steps, the set-up work that
            // applies to the whole line, and the measurement of the actual
            // character. Functions like coordsChar, that need to do a lot of
            // measurements in a row, can thus ensure that the set-up work is
            // only done once.
            function prepareMeasureForLine(cm, line) {
              var lineN = lineNo(line);
              var view = findViewForLine(cm, lineN);
              if (view && !view.text)
                view = null;
              else if (view && view.changes)
                updateLineForChanges(cm, view, lineN, getDimensions(cm));
              if (!view)
                view = updateExternalMeasurement(cm, line);
          
              var info = mapFromLineView(view, line, lineN);
              return {
                line: line, view: view, rect: null,
                map: info.map, cache: info.cache, before: info.before,
                hasHeights: false
              };
            }
          
            // Given a prepared measurement object, measures the position of an
            // actual character (or fetches it from the cache).
            function measureCharPrepared(cm, prepared, ch, bias, varHeight) {
              if (prepared.before) ch = -1;
              var key = ch + (bias || ""), found;
              if (prepared.cache.hasOwnProperty(key)) {
                found = prepared.cache[key];
              } else {
                if (!prepared.rect)
                  prepared.rect = prepared.view.text.getBoundingClientRect();
                if (!prepared.hasHeights) {
                  ensureLineHeights(cm, prepared.view, prepared.rect);
                  prepared.hasHeights = true;
                }
                found = measureCharInner(cm, prepared, ch, bias);
                if (!found.bogus) prepared.cache[key] = found;
              }
              return {left: found.left, right: found.right,
                      top: varHeight ? found.rtop : found.top,
                      bottom: varHeight ? found.rbottom : found.bottom};
            }
          
            var nullRect = {left: 0, right: 0, top: 0, bottom: 0};
          
            function nodeAndOffsetInLineMap(map, ch, bias) {
              var node, start, end, collapse;
              // First, search the line map for the text node corresponding to,
              // or closest to, the target character.
              for (var i = 0; i < map.length; i += 3) {
                var mStart = map[i], mEnd = map[i + 1];
                if (ch < mStart) {
                  start = 0; end = 1;
                  collapse = "left";
                } else if (ch < mEnd) {
                  start = ch - mStart;
                  end = start + 1;
                } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
                  end = mEnd - mStart;
                  start = end - 1;
                  if (ch >= mEnd) collapse = "right";
                }
                if (start != null) {
                  node = map[i + 2];
                  if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
                    collapse = bias;
                  if (bias == "left" && start == 0)
                    while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
                      node = map[(i -= 3) + 2];
                      collapse = "left";
                    }
                  if (bias == "right" && start == mEnd - mStart)
                    while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
                      node = map[(i += 3) + 2];
                      collapse = "right";
                    }
                  break;
                }
              }
              return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd};
            }
          
            function measureCharInner(cm, prepared, ch, bias) {
              var place = nodeAndOffsetInLineMap(prepared.map, ch, bias);
              var node = place.node, start = place.start, end = place.end, collapse = place.collapse;
          
              var rect;
              if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
                for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned
                  while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) --start;
                  while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end;
                  if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) {
                    rect = node.parentNode.getBoundingClientRect();
                  } else if (ie && cm.options.lineWrapping) {
                    var rects = range(node, start, end).getClientRects();
                    if (rects.length)
                      rect = rects[bias == "right" ? rects.length - 1 : 0];
                    else
                      rect = nullRect;
                  } else {
                    rect = range(node, start, end).getBoundingClientRect() || nullRect;
                  }
                  if (rect.left || rect.right || start == 0) break;
                  end = start;
                  start = start - 1;
                  collapse = "right";
                }
                if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect);
              } else { // If it is a widget, simply get the box for the whole widget.
                if (start > 0) collapse = bias = "right";
                var rects;
                if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
                  rect = rects[bias == "right" ? rects.length - 1 : 0];
                else
                  rect = node.getBoundingClientRect();
              }
              if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {
                var rSpan = node.parentNode.getClientRects()[0];
                if (rSpan)
                  rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom};
                else
                  rect = nullRect;
              }
          
              var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top;
              var mid = (rtop + rbot) / 2;
              var heights = prepared.view.measure.heights;
              for (var i = 0; i < heights.length - 1; i++)
                if (mid < heights[i]) break;
              var top = i ? heights[i - 1] : 0, bot = heights[i];
              var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
                            right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
                            top: top, bottom: bot};
              if (!rect.left && !rect.right) result.bogus = true;
              if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }
          
              return result;
            }
          
            // Work around problem with bounding client rects on ranges being
            // returned incorrectly when zoomed on IE10 and below.
            function maybeUpdateRectForZooming(measure, rect) {
              if (!window.screen || screen.logicalXDPI == null ||
                  screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
                return rect;
              var scaleX = screen.logicalXDPI / screen.deviceXDPI;
              var scaleY = screen.logicalYDPI / screen.deviceYDPI;
              return {left: rect.left * scaleX, right: rect.right * scaleX,
                      top: rect.top * scaleY, bottom: rect.bottom * scaleY};
            }
          
            function clearLineMeasurementCacheFor(lineView) {
              if (lineView.measure) {
                lineView.measure.cache = {};
                lineView.measure.heights = null;
                if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
                  lineView.measure.caches[i] = {};
              }
            }
          
            function clearLineMeasurementCache(cm) {
              cm.display.externalMeasure = null;
              removeChildren(cm.display.lineMeasure);
              for (var i = 0; i < cm.display.view.length; i++)
                clearLineMeasurementCacheFor(cm.display.view[i]);
            }
          
            function clearCaches(cm) {
              clearLineMeasurementCache(cm);
              cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;
              if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
              cm.display.lineNumChars = null;
            }
          
            function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
            function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
          
            // Converts a {top, bottom, left, right} box from line-local
            // coordinates into another coordinate system. Context may be one of
            // "line", "div" (display.lineDiv), "local"/null (editor), "window",
            // or "page".
            function intoCoordSystem(cm, lineObj, rect, context) {
              if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
                var size = widgetHeight(lineObj.widgets[i]);
                rect.top += size; rect.bottom += size;
              }
              if (context == "line") return rect;
              if (!context) context = "local";
              var yOff = heightAtLine(lineObj);
              if (context == "local") yOff += paddingTop(cm.display);
              else yOff -= cm.display.viewOffset;
              if (context == "page" || context == "window") {
                var lOff = cm.display.lineSpace.getBoundingClientRect();
                yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
                var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
                rect.left += xOff; rect.right += xOff;
              }
              rect.top += yOff; rect.bottom += yOff;
              return rect;
            }
          
            // Coverts a box from "div" coords to another coordinate system.
            // Context may be "window", "page", "div", or "local"/null.
            function fromCoordSystem(cm, coords, context) {
              if (context == "div") return coords;
              var left = coords.left, top = coords.top;
              // First move into "page" coordinate system
              if (context == "page") {
                left -= pageScrollX();
                top -= pageScrollY();
              } else if (context == "local" || !context) {
                var localBox = cm.display.sizer.getBoundingClientRect();
                left += localBox.left;
                top += localBox.top;
              }
          
              var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();
              return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
            }
          
            function charCoords(cm, pos, context, lineObj, bias) {
              if (!lineObj) lineObj = getLine(cm.doc, pos.line);
              return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context);
            }
          
            // Returns a box for a given cursor position, which may have an
            // 'other' property containing the position of the secondary cursor
            // on a bidi boundary.
            function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {
              lineObj = lineObj || getLine(cm.doc, pos.line);
              if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj);
              function get(ch, right) {
                var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight);
                if (right) m.left = m.right; else m.right = m.left;
                return intoCoordSystem(cm, lineObj, m, context);
              }
              function getBidi(ch, partPos) {
                var part = order[partPos], right = part.level % 2;
                if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
                  part = order[--partPos];
                  ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
                  right = true;
                } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
                  part = order[++partPos];
                  ch = bidiLeft(part) - part.level % 2;
                  right = false;
                }
                if (right && ch == part.to && ch > part.from) return get(ch - 1);
                return get(ch, right);
              }
              var order = getOrder(lineObj), ch = pos.ch;
              if (!order) return get(ch);
              var partPos = getBidiPartAt(order, ch);
              var val = getBidi(ch, partPos);
              if (bidiOther != null) val.other = getBidi(ch, bidiOther);
              return val;
            }
          
            // Used to cheaply estimate the coordinates for a position. Used for
            // intermediate scroll updates.
            function estimateCoords(cm, pos) {
              var left = 0, pos = clipPos(cm.doc, pos);
              if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch;
              var lineObj = getLine(cm.doc, pos.line);
              var top = heightAtLine(lineObj) + paddingTop(cm.display);
              return {left: left, right: left, top: top, bottom: top + lineObj.height};
            }
          
            // Positions returned by coordsChar contain some extra information.
            // xRel is the relative x position of the input coordinates compared
            // to the found position (so xRel > 0 means the coordinates are to
            // the right of the character position, for example). When outside
            // is true, that means the coordinates lie outside the line's
            // vertical range.
            function PosWithInfo(line, ch, outside, xRel) {
              var pos = Pos(line, ch);
              pos.xRel = xRel;
              if (outside) pos.outside = true;
              return pos;
            }
          
            // Compute the character position closest to the given coordinates.
            // Input must be lineSpace-local ("div" coordinate system).
            function coordsChar(cm, x, y) {
              var doc = cm.doc;
              y += cm.display.viewOffset;
              if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
              var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
              if (lineN > last)
                return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
              if (x < 0) x = 0;
          
              var lineObj = getLine(doc, lineN);
              for (;;) {
                var found = coordsCharInner(cm, lineObj, lineN, x, y);
                var merged = collapsedSpanAtEnd(lineObj);
                var mergedPos = merged && merged.find(0, true);
                if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
                  lineN = lineNo(lineObj = mergedPos.to.line);
                else
                  return found;
              }
            }
          
            function coordsCharInner(cm, lineObj, lineNo, x, y) {
              var innerOff = y - heightAtLine(lineObj);
              var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
              var preparedMeasure = prepareMeasureForLine(cm, lineObj);
          
              function getX(ch) {
                var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure);
                wrongLine = true;
                if (innerOff > sp.bottom) return sp.left - adjust;
                else if (innerOff < sp.top) return sp.left + adjust;
                else wrongLine = false;
                return sp.left;
              }
          
              var bidi = getOrder(lineObj), dist = lineObj.text.length;
              var from = lineLeft(lineObj), to = lineRight(lineObj);
              var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
          
              if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
              // Do a binary search between these bounds.
              for (;;) {
                if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
                  var ch = x < fromX || x - fromX <= toX - x ? from : to;
                  var xDiff = x - (ch == from ? fromX : toX);
                  while (isExtendingChar(lineObj.text.charAt(ch))) ++ch;
                  var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
                                        xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0);
                  return pos;
                }
                var step = Math.ceil(dist / 2), middle = from + step;
                if (bidi) {
                  middle = from;
                  for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
                }
                var middleX = getX(middle);
                if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
                else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
              }
            }
          
            var measureText;
            // Compute the default text height.
            function textHeight(display) {
              if (display.cachedTextHeight != null) return display.cachedTextHeight;
              if (measureText == null) {
                measureText = elt("pre");
                // Measure a bunch of lines, for browsers that compute
                // fractional heights.
                for (var i = 0; i < 49; ++i) {
                  measureText.appendChild(document.createTextNode("x"));
                  measureText.appendChild(elt("br"));
                }
                measureText.appendChild(document.createTextNode("x"));
              }
              removeChildrenAndAdd(display.measure, measureText);
              var height = measureText.offsetHeight / 50;
              if (height > 3) display.cachedTextHeight = height;
              removeChildren(display.measure);
              return height || 1;
            }
          
            // Compute the default character width.
            function charWidth(display) {
              if (display.cachedCharWidth != null) return display.cachedCharWidth;
              var anchor = elt("span", "xxxxxxxxxx");
              var pre = elt("pre", [anchor]);
              removeChildrenAndAdd(display.measure, pre);
              var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;
              if (width > 2) display.cachedCharWidth = width;
              return width || 10;
            }
          
            // OPERATIONS
          
            // Operations are used to wrap a series of changes to the editor
            // state in such a way that each change won't have to update the
            // cursor and display (which would be awkward, slow, and
            // error-prone). Instead, display updates are batched and then all
            // combined and executed at once.
          
            var operationGroup = null;
          
            var nextOpId = 0;
            // Start a new operation.
            function startOperation(cm) {
              cm.curOp = {
                cm: cm,
                viewChanged: false,      // Flag that indicates that lines might need to be redrawn
                startHeight: cm.doc.height, // Used to detect need to update scrollbar
                forceUpdate: false,      // Used to force a redraw
                updateInput: null,       // Whether to reset the input textarea
                typing: false,           // Whether this reset should be careful to leave existing text (for compositing)
                changeObjs: null,        // Accumulated changes, for firing change events
                cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
                cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already
                selectionChanged: false, // Whether the selection needs to be redrawn
                updateMaxLine: false,    // Set when the widest line needs to be determined anew
                scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
                scrollToPos: null,       // Used to scroll to a specific position
                focus: false,
                id: ++nextOpId           // Unique ID
              };
              if (operationGroup) {
                operationGroup.ops.push(cm.curOp);
              } else {
                cm.curOp.ownsGroup = operationGroup = {
                  ops: [cm.curOp],
                  delayedCallbacks: []
                };
              }
            }
          
            function fireCallbacksForOps(group) {
              // Calls delayed callbacks and cursorActivity handlers until no
              // new ones appear
              var callbacks = group.delayedCallbacks, i = 0;
              do {
                for (; i < callbacks.length; i++)
                  callbacks[i]();
                for (var j = 0; j < group.ops.length; j++) {
                  var op = group.ops[j];
                  if (op.cursorActivityHandlers)
                    while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
                      op.cursorActivityHandlers[op.cursorActivityCalled++](op.cm);
                }
              } while (i < callbacks.length);
            }
          
            // Finish an operation, updating the display and signalling delayed events
            function endOperation(cm) {
              var op = cm.curOp, group = op.ownsGroup;
              if (!group) return;
          
              try { fireCallbacksForOps(group); }
              finally {
                operationGroup = null;
                for (var i = 0; i < group.ops.length; i++)
                  group.ops[i].cm.curOp = null;
                endOperations(group);
              }
            }
          
            // The DOM updates done when an operation finishes are batched so
            // that the minimum number of relayouts are required.
            function endOperations(group) {
              var ops = group.ops;
              for (var i = 0; i < ops.length; i++) // Read DOM
                endOperation_R1(ops[i]);
              for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
                endOperation_W1(ops[i]);
              for (var i = 0; i < ops.length; i++) // Read DOM
                endOperation_R2(ops[i]);
              for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
                endOperation_W2(ops[i]);
              for (var i = 0; i < ops.length; i++) // Read DOM
                endOperation_finish(ops[i]);
            }
          
            function endOperation_R1(op) {
              var cm = op.cm, display = cm.display;
              maybeClipScrollbars(cm);
              if (op.updateMaxLine) findMaxLine(cm);
          
              op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
                op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
                                   op.scrollToPos.to.line >= display.viewTo) ||
                display.maxLineChanged && cm.options.lineWrapping;
              op.update = op.mustUpdate &&
                new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);
            }
          
            function endOperation_W1(op) {
              op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);
            }
          
            function endOperation_R2(op) {
              var cm = op.cm, display = cm.display;
              if (op.updatedDisplay) updateHeightsInViewport(cm);
          
              op.barMeasure = measureForScrollbars(cm);
          
              // If the max line changed since it was last measured, measure it,
              // and ensure the document's width matches it.
              // updateDisplay_W2 will use these properties to do the actual resizing
              if (display.maxLineChanged && !cm.options.lineWrapping) {
                op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;
                cm.display.sizerWidth = op.adjustWidthTo;
                op.barMeasure.scrollWidth =
                  Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);
                op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));
              }
          
              if (op.updatedDisplay || op.selectionChanged)
                op.preparedSelection = display.input.prepareSelection();
            }
          
            function endOperation_W2(op) {
              var cm = op.cm;
          
              if (op.adjustWidthTo != null) {
                cm.display.sizer.style.minWidth = op.adjustWidthTo + "px";
                if (op.maxScrollLeft < cm.doc.scrollLeft)
                  setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true);
                cm.display.maxLineChanged = false;
              }
          
              if (op.preparedSelection)
                cm.display.input.showSelection(op.preparedSelection);
              if (op.updatedDisplay)
                setDocumentHeight(cm, op.barMeasure);
              if (op.updatedDisplay || op.startHeight != cm.doc.height)
                updateScrollbars(cm, op.barMeasure);
          
              if (op.selectionChanged) restartBlink(cm);
          
              if (cm.state.focused && op.updateInput)
                cm.display.input.reset(op.typing);
              if (op.focus && op.focus == activeElt()) ensureFocus(op.cm);
            }
          
            function endOperation_finish(op) {
              var cm = op.cm, display = cm.display, doc = cm.doc;
          
              if (op.updatedDisplay) postUpdateDisplay(cm, op.update);
          
              // Abort mouse wheel delta measurement, when scrolling explicitly
              if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
                display.wheelStartX = display.wheelStartY = null;
          
              // Propagate the scroll position to the actual DOM scroller
              if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) {
                doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));
                display.scrollbars.setScrollTop(doc.scrollTop);
                display.scroller.scrollTop = doc.scrollTop;
              }
              if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {
                doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - displayWidth(cm), op.scrollLeft));
                display.scrollbars.setScrollLeft(doc.scrollLeft);
                display.scroller.scrollLeft = doc.scrollLeft;
                alignHorizontally(cm);
              }
              // If we need to scroll a specific position into view, do so.
              if (op.scrollToPos) {
                var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
                                               clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);
                if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords);
              }
          
              // Fire events for markers that are hidden/unidden by editing or
              // undoing
              var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
              if (hidden) for (var i = 0; i < hidden.length; ++i)
                if (!hidden[i].lines.length) signal(hidden[i], "hide");
              if (unhidden) for (var i = 0; i < unhidden.length; ++i)
                if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
          
              if (display.wrapper.offsetHeight)
                doc.scrollTop = cm.display.scroller.scrollTop;
          
              // Fire change events, and delayed event handlers
              if (op.changeObjs)
                signal(cm, "changes", cm, op.changeObjs);
              if (op.update)
                op.update.finish();
            }
          
            // Run the given function in an operation
            function runInOp(cm, f) {
              if (cm.curOp) return f();
              startOperation(cm);
              try { return f(); }
              finally { endOperation(cm); }
            }
            // Wraps a function in an operation. Returns the wrapped function.
            function operation(cm, f) {
              return function() {
                if (cm.curOp) return f.apply(cm, arguments);
                startOperation(cm);
                try { return f.apply(cm, arguments); }
                finally { endOperation(cm); }
              };
            }
            // Used to add methods to editor and doc instances, wrapping them in
            // operations.
            function methodOp(f) {
              return function() {
                if (this.curOp) return f.apply(this, arguments);
                startOperation(this);
                try { return f.apply(this, arguments); }
                finally { endOperation(this); }
              };
            }
            function docMethodOp(f) {
              return function() {
                var cm = this.cm;
                if (!cm || cm.curOp) return f.apply(this, arguments);
                startOperation(cm);
                try { return f.apply(this, arguments); }
                finally { endOperation(cm); }
              };
            }
          
            // VIEW TRACKING
          
            // These objects are used to represent the visible (currently drawn)
            // part of the document. A LineView may correspond to multiple
            // logical lines, if those are connected by collapsed ranges.
            function LineView(doc, line, lineN) {
              // The starting line
              this.line = line;
              // Continuing lines, if any
              this.rest = visualLineContinued(line);
              // Number of logical lines in this visual line
              this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;
              this.node = this.text = null;
              this.hidden = lineIsHidden(doc, line);
            }
          
            // Create a range of LineView objects for the given lines.
            function buildViewArray(cm, from, to) {
              var array = [], nextPos;
              for (var pos = from; pos < to; pos = nextPos) {
                var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);
                nextPos = pos + view.size;
                array.push(view);
              }
              return array;
            }
          
            // Updates the display.view data structure for a given change to the
            // document. From and to are in pre-change coordinates. Lendiff is
            // the amount of lines added or subtracted by the change. This is
            // used for changes that span multiple lines, or change the way
            // lines are divided into visual lines. regLineChange (below)
            // registers single-line changes.
            function regChange(cm, from, to, lendiff) {
              if (from == null) from = cm.doc.first;
              if (to == null) to = cm.doc.first + cm.doc.size;
              if (!lendiff) lendiff = 0;
          
              var display = cm.display;
              if (lendiff && to < display.viewTo &&
                  (display.updateLineNumbers == null || display.updateLineNumbers > from))
                display.updateLineNumbers = from;
          
              cm.curOp.viewChanged = true;
          
              if (from >= display.viewTo) { // Change after
                if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
                  resetView(cm);
              } else if (to <= display.viewFrom) { // Change before
                if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
                  resetView(cm);
                } else {
                  display.viewFrom += lendiff;
                  display.viewTo += lendiff;
                }
              } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap
                resetView(cm);
              } else if (from <= display.viewFrom) { // Top overlap
                var cut = viewCuttingPoint(cm, to, to + lendiff, 1);
                if (cut) {
                  display.view = display.view.slice(cut.index);
                  display.viewFrom = cut.lineN;
                  display.viewTo += lendiff;
                } else {
                  resetView(cm);
                }
              } else if (to >= display.viewTo) { // Bottom overlap
                var cut = viewCuttingPoint(cm, from, from, -1);
                if (cut) {
                  display.view = display.view.slice(0, cut.index);
                  display.viewTo = cut.lineN;
                } else {
                  resetView(cm);
                }
              } else { // Gap in the middle
                var cutTop = viewCuttingPoint(cm, from, from, -1);
                var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1);
                if (cutTop && cutBot) {
                  display.view = display.view.slice(0, cutTop.index)
                    .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))
                    .concat(display.view.slice(cutBot.index));
                  display.viewTo += lendiff;
                } else {
                  resetView(cm);
                }
              }
          
              var ext = display.externalMeasured;
              if (ext) {
                if (to < ext.lineN)
                  ext.lineN += lendiff;
                else if (from < ext.lineN + ext.size)
                  display.externalMeasured = null;
              }
            }
          
            // Register a change to a single line. Type must be one of "text",
            // "gutter", "class", "widget"
            function regLineChange(cm, line, type) {
              cm.curOp.viewChanged = true;
              var display = cm.display, ext = cm.display.externalMeasured;
              if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
                display.externalMeasured = null;
          
              if (line < display.viewFrom || line >= display.viewTo) return;
              var lineView = display.view[findViewIndex(cm, line)];
              if (lineView.node == null) return;
              var arr = lineView.changes || (lineView.changes = []);
              if (indexOf(arr, type) == -1) arr.push(type);
            }
          
            // Clear the view.
            function resetView(cm) {
              cm.display.viewFrom = cm.display.viewTo = cm.doc.first;
              cm.display.view = [];
              cm.display.viewOffset = 0;
            }
          
            // Find the view element corresponding to a given line. Return null
            // when the line isn't visible.
            function findViewIndex(cm, n) {
              if (n >= cm.display.viewTo) return null;
              n -= cm.display.viewFrom;
              if (n < 0) return null;
              var view = cm.display.view;
              for (var i = 0; i < view.length; i++) {
                n -= view[i].size;
                if (n < 0) return i;
              }
            }
          
            function viewCuttingPoint(cm, oldN, newN, dir) {
              var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
              if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
                return {index: index, lineN: newN};
              for (var i = 0, n = cm.display.viewFrom; i < index; i++)
                n += view[i].size;
              if (n != oldN) {
                if (dir > 0) {
                  if (index == view.length - 1) return null;
                  diff = (n + view[index].size) - oldN;
                  index++;
                } else {
                  diff = n - oldN;
                }
                oldN += diff; newN += diff;
              }
              while (visualLineNo(cm.doc, newN) != newN) {
                if (index == (dir < 0 ? 0 : view.length - 1)) return null;
                newN += dir * view[index - (dir < 0 ? 1 : 0)].size;
                index += dir;
              }
              return {index: index, lineN: newN};
            }
          
            // Force the view to cover a given range, adding empty view element
            // or clipping off existing ones as needed.
            function adjustView(cm, from, to) {
              var display = cm.display, view = display.view;
              if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {
                display.view = buildViewArray(cm, from, to);
                display.viewFrom = from;
              } else {
                if (display.viewFrom > from)
                  display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view);
                else if (display.viewFrom < from)
                  display.view = display.view.slice(findViewIndex(cm, from));
                display.viewFrom = from;
                if (display.viewTo < to)
                  display.view = display.view.concat(buildViewArray(cm, display.viewTo, to));
                else if (display.viewTo > to)
                  display.view = display.view.slice(0, findViewIndex(cm, to));
              }
              display.viewTo = to;
            }
          
            // Count the number of lines in the view whose DOM representation is
            // out of date (or nonexistent).
            function countDirtyView(cm) {
              var view = cm.display.view, dirty = 0;
              for (var i = 0; i < view.length; i++) {
                var lineView = view[i];
                if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty;
              }
              return dirty;
            }
          
            // EVENT HANDLERS
          
            // Attach the necessary event handlers when initializing the editor
            function registerEventHandlers(cm) {
              var d = cm.display;
              on(d.scroller, "mousedown", operation(cm, onMouseDown));
              // Older IE's will not fire a second mousedown for a double click
              if (ie && ie_version < 11)
                on(d.scroller, "dblclick", operation(cm, function(e) {
                  if (signalDOMEvent(cm, e)) return;
                  var pos = posFromMouse(cm, e);
                  if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
                  e_preventDefault(e);
                  var word = cm.findWordAt(pos);
                  extendSelection(cm.doc, word.anchor, word.head);
                }));
              else
                on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
              // Some browsers fire contextmenu *after* opening the menu, at
              // which point we can't mess with it anymore. Context menu is
              // handled in onMouseDown for these browsers.
              if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
          
              // Used to suppress mouse event handling when a touch happens
              var touchFinished, prevTouch = {end: 0};
              function finishTouch() {
                if (d.activeTouch) {
                  touchFinished = setTimeout(function() {d.activeTouch = null;}, 1000);
                  prevTouch = d.activeTouch;
                  prevTouch.end = +new Date;
                }
              };
              function isMouseLikeTouchEvent(e) {
                if (e.touches.length != 1) return false;
                var touch = e.touches[0];
                return touch.radiusX <= 1 && touch.radiusY <= 1;
              }
              function farAway(touch, other) {
                if (other.left == null) return true;
                var dx = other.left - touch.left, dy = other.top - touch.top;
                return dx * dx + dy * dy > 20 * 20;
              }
              on(d.scroller, "touchstart", function(e) {
                if (!isMouseLikeTouchEvent(e)) {
                  clearTimeout(touchFinished);
                  var now = +new Date;
                  d.activeTouch = {start: now, moved: false,
                                   prev: now - prevTouch.end <= 300 ? prevTouch : null};
                  if (e.touches.length == 1) {
                    d.activeTouch.left = e.touches[0].pageX;
                    d.activeTouch.top = e.touches[0].pageY;
                  }
                }
              });
              on(d.scroller, "touchmove", function() {
                if (d.activeTouch) d.activeTouch.moved = true;
              });
              on(d.scroller, "touchend", function(e) {
                var touch = d.activeTouch;
                if (touch && !eventInWidget(d, e) && touch.left != null &&
                    !touch.moved && new Date - touch.start < 300) {
                  var pos = cm.coordsChar(d.activeTouch, "page"), range;
                  if (!touch.prev || farAway(touch, touch.prev)) // Single tap
                    range = new Range(pos, pos);
                  else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
                    range = cm.findWordAt(pos);
                  else // Triple tap
                    range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0)));
                  cm.setSelection(range.anchor, range.head);
                  cm.focus();
                  e_preventDefault(e);
                }
                finishTouch();
              });
              on(d.scroller, "touchcancel", finishTouch);
          
              // Sync scrolling between fake scrollbars and real scrollable
              // area, ensure viewport is updated when scrolling.
              on(d.scroller, "scroll", function() {
                if (d.scroller.clientHeight) {
                  setScrollTop(cm, d.scroller.scrollTop);
                  setScrollLeft(cm, d.scroller.scrollLeft, true);
                  signal(cm, "scroll", cm);
                }
              });
          
              // Listen to wheel events in order to try and update the viewport on time.
              on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
              on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
          
              // Prevent wrapper from ever scrolling
              on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
          
              d.dragFunctions = {
                simple: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);},
                start: function(e){onDragStart(cm, e);},
                drop: operation(cm, onDrop)
              };
          
              var inp = d.input.getField();
              on(inp, "keyup", function(e) { onKeyUp.call(cm, e); });
              on(inp, "keydown", operation(cm, onKeyDown));
              on(inp, "keypress", operation(cm, onKeyPress));
              on(inp, "focus", bind(onFocus, cm));
              on(inp, "blur", bind(onBlur, cm));
            }
          
            function dragDropChanged(cm, value, old) {
              var wasOn = old && old != CodeMirror.Init;
              if (!value != !wasOn) {
                var funcs = cm.display.dragFunctions;
                var toggle = value ? on : off;
                toggle(cm.display.scroller, "dragstart", funcs.start);
                toggle(cm.display.scroller, "dragenter", funcs.simple);
                toggle(cm.display.scroller, "dragover", funcs.simple);
                toggle(cm.display.scroller, "drop", funcs.drop);
              }
            }
          
            // Called when the window resizes
            function onResize(cm) {
              var d = cm.display;
              if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)
                return;
              // Might be a text scaling operation, clear size caches.
              d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
              d.scrollbarsClipped = false;
              cm.setSize();
            }
          
            // MOUSE EVENTS
          
            // Return true when the given mouse event happened in a widget
            function eventInWidget(display, e) {
              for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
                if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
                    (n.parentNode == display.sizer && n != display.mover))
                  return true;
              }
            }
          
            // Given a mouse event, find the corresponding position. If liberal
            // is false, it checks whether a gutter or scrollbar was clicked,
            // and returns null if it was. forRect is used by rectangular
            // selections, and tries to estimate a character position even for
            // coordinates beyond the right of the text.
            function posFromMouse(cm, e, liberal, forRect) {
              var display = cm.display;
              if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") return null;
          
              var x, y, space = display.lineSpace.getBoundingClientRect();
              // Fails unpredictably on IE[67] when mouse is dragged around quickly.
              try { x = e.clientX - space.left; y = e.clientY - space.top; }
              catch (e) { return null; }
              var coords = coordsChar(cm, x, y), line;
              if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
                var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
                coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));
              }
              return coords;
            }
          
            // A mouse down can be a single click, double click, triple click,
            // start of selection drag, start of text drag, new cursor
            // (ctrl-click), rectangle drag (alt-drag), or xwin
            // middle-click-paste. Or it might be a click on something we should
            // not interfere with, such as a scrollbar or widget.
            function onMouseDown(e) {
              var cm = this, display = cm.display;
              if (display.activeTouch && display.input.supportsTouch() || signalDOMEvent(cm, e)) return;
              display.shift = e.shiftKey;
          
              if (eventInWidget(display, e)) {
                if (!webkit) {
                  // Briefly turn off draggability, to allow widgets to do
                  // normal dragging things.
                  display.scroller.draggable = false;
                  setTimeout(function(){display.scroller.draggable = true;}, 100);
                }
                return;
              }
              if (clickInGutter(cm, e)) return;
              var start = posFromMouse(cm, e);
              window.focus();
          
              switch (e_button(e)) {
              case 1:
                if (start)
                  leftButtonDown(cm, e, start);
                else if (e_target(e) == display.scroller)
                  e_preventDefault(e);
                break;
              case 2:
                if (webkit) cm.state.lastMiddleDown = +new Date;
                if (start) extendSelection(cm.doc, start);
                setTimeout(function() {display.input.focus();}, 20);
                e_preventDefault(e);
                break;
              case 3:
                if (captureRightClick) onContextMenu(cm, e);
                else delayBlurEvent(cm);
                break;
              }
            }
          
            var lastClick, lastDoubleClick;
            function leftButtonDown(cm, e, start) {
              if (ie) setTimeout(bind(ensureFocus, cm), 0);
              else cm.curOp.focus = activeElt();
          
              var now = +new Date, type;
              if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
                type = "triple";
              } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {
                type = "double";
                lastDoubleClick = {time: now, pos: start};
              } else {
                type = "single";
                lastClick = {time: now, pos: start};
              }
          
              var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained;
              if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&
                  type == "single" && (contained = sel.contains(start)) > -1 &&
                  !sel.ranges[contained].empty())
                leftButtonStartDrag(cm, e, start, modifier);
              else
                leftButtonSelect(cm, e, start, type, modifier);
            }
          
            // Start a text drag. When it ends, see if any dragging actually
            // happen, and treat as a click if it didn't.
            function leftButtonStartDrag(cm, e, start, modifier) {
              var display = cm.display, startTime = +new Date;
              var dragEnd = operation(cm, function(e2) {
                if (webkit) display.scroller.draggable = false;
                cm.state.draggingText = false;
                off(document, "mouseup", dragEnd);
                off(display.scroller, "drop", dragEnd);
                if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
                  e_preventDefault(e2);
                  if (!modifier && +new Date - 200 < startTime)
                    extendSelection(cm.doc, start);
                  // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
                  if (webkit || ie && ie_version == 9)
                    setTimeout(function() {document.body.focus(); display.input.focus();}, 20);
                  else
                    display.input.focus();
                }
              });
              // Let the drag handler handle this.
              if (webkit) display.scroller.draggable = true;
              cm.state.draggingText = dragEnd;
              // IE's approach to draggable
              if (display.scroller.dragDrop) display.scroller.dragDrop();
              on(document, "mouseup", dragEnd);
              on(display.scroller, "drop", dragEnd);
            }
          
            // Normal selection, as opposed to text dragging.
            function leftButtonSelect(cm, e, start, type, addNew) {
              var display = cm.display, doc = cm.doc;
              e_preventDefault(e);
          
              var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;
              if (addNew && !e.shiftKey) {
                ourIndex = doc.sel.contains(start);
                if (ourIndex > -1)
                  ourRange = ranges[ourIndex];
                else
                  ourRange = new Range(start, start);
              } else {
                ourRange = doc.sel.primary();
                ourIndex = doc.sel.primIndex;
              }
          
              if (e.altKey) {
                type = "rect";
                if (!addNew) ourRange = new Range(start, start);
                start = posFromMouse(cm, e, true, true);
                ourIndex = -1;
              } else if (type == "double") {
                var word = cm.findWordAt(start);
                if (cm.display.shift || doc.extend)
                  ourRange = extendRange(doc, ourRange, word.anchor, word.head);
                else
                  ourRange = word;
              } else if (type == "triple") {
                var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0)));
                if (cm.display.shift || doc.extend)
                  ourRange = extendRange(doc, ourRange, line.anchor, line.head);
                else
                  ourRange = line;
              } else {
                ourRange = extendRange(doc, ourRange, start);
              }
          
              if (!addNew) {
                ourIndex = 0;
                setSelection(doc, new Selection([ourRange], 0), sel_mouse);
                startSel = doc.sel;
              } else if (ourIndex == -1) {
                ourIndex = ranges.length;
                setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),
                             {scroll: false, origin: "*mouse"});
              } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) {
                setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0));
                startSel = doc.sel;
              } else {
                replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
              }
          
              var lastPos = start;
              function extendTo(pos) {
                if (cmp(lastPos, pos) == 0) return;
                lastPos = pos;
          
                if (type == "rect") {
                  var ranges = [], tabSize = cm.options.tabSize;
                  var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);
                  var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);
                  var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);
                  for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
                       line <= end; line++) {
                    var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);
                    if (left == right)
                      ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos)));
                    else if (text.length > leftPos)
                      ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize))));
                  }
                  if (!ranges.length) ranges.push(new Range(start, start));
                  setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
                               {origin: "*mouse", scroll: false});
                  cm.scrollIntoView(pos);
                } else {
                  var oldRange = ourRange;
                  var anchor = oldRange.anchor, head = pos;
                  if (type != "single") {
                    if (type == "double")
                      var range = cm.findWordAt(pos);
                    else
                      var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));
                    if (cmp(range.anchor, anchor) > 0) {
                      head = range.head;
                      anchor = minPos(oldRange.from(), range.anchor);
                    } else {
                      head = range.anchor;
                      anchor = maxPos(oldRange.to(), range.head);
                    }
                  }
                  var ranges = startSel.ranges.slice(0);
                  ranges[ourIndex] = new Range(clipPos(doc, anchor), head);
                  setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse);
                }
              }
          
              var editorSize = display.wrapper.getBoundingClientRect();
              // Used to ensure timeout re-tries don't fire when another extend
              // happened in the meantime (clearTimeout isn't reliable -- at
              // least on Chrome, the timeouts still happen even when cleared,
              // if the clear happens after their scheduled firing time).
              var counter = 0;
          
              function extend(e) {
                var curCount = ++counter;
                var cur = posFromMouse(cm, e, true, type == "rect");
                if (!cur) return;
                if (cmp(cur, lastPos) != 0) {
                  cm.curOp.focus = activeElt();
                  extendTo(cur);
                  var visible = visibleLines(display, doc);
                  if (cur.line >= visible.to || cur.line < visible.from)
                    setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
                } else {
                  var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
                  if (outside) setTimeout(operation(cm, function() {
                    if (counter != curCount) return;
                    display.scroller.scrollTop += outside;
                    extend(e);
                  }), 50);
                }
              }
          
              function done(e) {
                counter = Infinity;
                e_preventDefault(e);
                display.input.focus();
                off(document, "mousemove", move);
                off(document, "mouseup", up);
                doc.history.lastSelOrigin = null;
              }
          
              var move = operation(cm, function(e) {
                if (!e_button(e)) done(e);
                else extend(e);
              });
              var up = operation(cm, done);
              on(document, "mousemove", move);
              on(document, "mouseup", up);
            }
          
            // Determines whether an event happened in the gutter, and fires the
            // handlers for the corresponding event.
            function gutterEvent(cm, e, type, prevent, signalfn) {
              try { var mX = e.clientX, mY = e.clientY; }
              catch(e) { return false; }
              if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false;
              if (prevent) e_preventDefault(e);
          
              var display = cm.display;
              var lineBox = display.lineDiv.getBoundingClientRect();
          
              if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);
              mY -= lineBox.top - display.viewOffset;
          
              for (var i = 0; i < cm.options.gutters.length; ++i) {
                var g = display.gutters.childNodes[i];
                if (g && g.getBoundingClientRect().right >= mX) {
                  var line = lineAtHeight(cm.doc, mY);
                  var gutter = cm.options.gutters[i];
                  signalfn(cm, type, cm, line, gutter, e);
                  return e_defaultPrevented(e);
                }
              }
            }
          
            function clickInGutter(cm, e) {
              return gutterEvent(cm, e, "gutterClick", true, signalLater);
            }
          
            // Kludge to work around strange IE behavior where it'll sometimes
            // re-fire a series of drag-related events right after the drop (#1551)
            var lastDrop = 0;
          
            function onDrop(e) {
              var cm = this;
              if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
                return;
              e_preventDefault(e);
              if (ie) lastDrop = +new Date;
              var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
              if (!pos || isReadOnly(cm)) return;
              // Might be a file drop, in which case we simply extract the text
              // and insert it.
              if (files && files.length && window.FileReader && window.File) {
                var n = files.length, text = Array(n), read = 0;
                var loadFile = function(file, i) {
                  var reader = new FileReader;
                  reader.onload = operation(cm, function() {
                    text[i] = reader.result;
                    if (++read == n) {
                      pos = clipPos(cm.doc, pos);
                      var change = {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"};
                      makeChange(cm.doc, change);
                      setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));
                    }
                  });
                  reader.readAsText(file);
                };
                for (var i = 0; i < n; ++i) loadFile(files[i], i);
              } else { // Normal drop
                // Don't do a replace if the drop happened inside of the selected text.
                if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
                  cm.state.draggingText(e);
                  // Ensure the editor is re-focused
                  setTimeout(function() {cm.display.input.focus();}, 20);
                  return;
                }
                try {
                  var text = e.dataTransfer.getData("Text");
                  if (text) {
                    if (cm.state.draggingText && !(mac ? e.altKey : e.ctrlKey))
                      var selected = cm.listSelections();
                    setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
                    if (selected) for (var i = 0; i < selected.length; ++i)
                      replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag");
                    cm.replaceSelection(text, "around", "paste");
                    cm.display.input.focus();
                  }
                }
                catch(e){}
              }
            }
          
            function onDragStart(cm, e) {
              if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
              if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
          
              e.dataTransfer.setData("Text", cm.getSelection());
          
              // Use dummy image instead of default browsers image.
              // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
              if (e.dataTransfer.setDragImage && !safari) {
                var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
                img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
                if (presto) {
                  img.width = img.height = 1;
                  cm.display.wrapper.appendChild(img);
                  // Force a relayout, or Opera won't use our image for some obscure reason
                  img._top = img.offsetTop;
                }
                e.dataTransfer.setDragImage(img, 0, 0);
                if (presto) img.parentNode.removeChild(img);
              }
            }
          
            // SCROLL EVENTS
          
            // Sync the scrollable area and scrollbars, ensure the viewport
            // covers the visible area.
            function setScrollTop(cm, val) {
              if (Math.abs(cm.doc.scrollTop - val) < 2) return;
              cm.doc.scrollTop = val;
              if (!gecko) updateDisplaySimple(cm, {top: val});
              if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
              cm.display.scrollbars.setScrollTop(val);
              if (gecko) updateDisplaySimple(cm);
              startWorker(cm, 100);
            }
            // Sync scroller and scrollbar, ensure the gutter elements are
            // aligned.
            function setScrollLeft(cm, val, isScroller) {
              if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
              val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
              cm.doc.scrollLeft = val;
              alignHorizontally(cm);
              if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
              cm.display.scrollbars.setScrollLeft(val);
            }
          
            // Since the delta values reported on mouse wheel events are
            // unstandardized between browsers and even browser versions, and
            // generally horribly unpredictable, this code starts by measuring
            // the scroll effect that the first few mouse wheel events have,
            // and, from that, detects the way it can convert deltas to pixel
            // offsets afterwards.
            //
            // The reason we want to know the amount a wheel event will scroll
            // is that it gives us a chance to update the display before the
            // actual scrolling happens, reducing flickering.
          
            var wheelSamples = 0, wheelPixelsPerUnit = null;
            // Fill in a browser-detected starting value on browsers where we
            // know one. These don't have to be accurate -- the result of them
            // being wrong would just be a slight flicker on the first wheel
            // scroll (if it is large enough).
            if (ie) wheelPixelsPerUnit = -.53;
            else if (gecko) wheelPixelsPerUnit = 15;
            else if (chrome) wheelPixelsPerUnit = -.7;
            else if (safari) wheelPixelsPerUnit = -1/3;
          
            var wheelEventDelta = function(e) {
              var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
              if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
              if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
              else if (dy == null) dy = e.wheelDelta;
              return {x: dx, y: dy};
            };
            CodeMirror.wheelEventPixels = function(e) {
              var delta = wheelEventDelta(e);
              delta.x *= wheelPixelsPerUnit;
              delta.y *= wheelPixelsPerUnit;
              return delta;
            };
          
            function onScrollWheel(cm, e) {
              var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
          
              var display = cm.display, scroll = display.scroller;
              // Quit if there's nothing to scroll here
              if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
                    dy && scroll.scrollHeight > scroll.clientHeight)) return;
          
              // Webkit browsers on OS X abort momentum scrolls when the target
              // of the scroll event is removed from the scrollable element.
              // This hack (see related code in patchDisplay) makes sure the
              // element is kept around.
              if (dy && mac && webkit) {
                outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
                  for (var i = 0; i < view.length; i++) {
                    if (view[i].node == cur) {
                      cm.display.currentWheelTarget = cur;
                      break outer;
                    }
                  }
                }
              }
          
              // On some browsers, horizontal scrolling will cause redraws to
              // happen before the gutter has been realigned, causing it to
              // wriggle around in a most unseemly way. When we have an
              // estimated pixels/delta value, we just handle horizontal
              // scrolling entirely here. It'll be slightly off from native, but
              // better than glitching out.
              if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
                if (dy)
                  setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
                setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
                e_preventDefault(e);
                display.wheelStartX = null; // Abort measurement, if in progress
                return;
              }
          
              // 'Project' the visible viewport to cover the area that is being
              // scrolled into view (if we know enough to estimate it).
              if (dy && wheelPixelsPerUnit != null) {
                var pixels = dy * wheelPixelsPerUnit;
                var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
                if (pixels < 0) top = Math.max(0, top + pixels - 50);
                else bot = Math.min(cm.doc.height, bot + pixels + 50);
                updateDisplaySimple(cm, {top: top, bottom: bot});
              }
          
              if (wheelSamples < 20) {
                if (display.wheelStartX == null) {
                  display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
                  display.wheelDX = dx; display.wheelDY = dy;
                  setTimeout(function() {
                    if (display.wheelStartX == null) return;
                    var movedX = scroll.scrollLeft - display.wheelStartX;
                    var movedY = scroll.scrollTop - display.wheelStartY;
                    var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
                      (movedX && display.wheelDX && movedX / display.wheelDX);
                    display.wheelStartX = display.wheelStartY = null;
                    if (!sample) return;
                    wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
                    ++wheelSamples;
                  }, 200);
                } else {
                  display.wheelDX += dx; display.wheelDY += dy;
                }
              }
            }
          
            // KEY EVENTS
          
            // Run a handler that was bound to a key.
            function doHandleBinding(cm, bound, dropShift) {
              if (typeof bound == "string") {
                bound = commands[bound];
                if (!bound) return false;
              }
              // Ensure previous input has been read, so that the handler sees a
              // consistent view of the document
              cm.display.input.ensurePolled();
              var prevShift = cm.display.shift, done = false;
              try {
                if (isReadOnly(cm)) cm.state.suppressEdits = true;
                if (dropShift) cm.display.shift = false;
                done = bound(cm) != Pass;
              } finally {
                cm.display.shift = prevShift;
                cm.state.suppressEdits = false;
              }
              return done;
            }
          
            function lookupKeyForEditor(cm, name, handle) {
              for (var i = 0; i < cm.state.keyMaps.length; i++) {
                var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);
                if (result) return result;
              }
              return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
                || lookupKey(name, cm.options.keyMap, handle, cm);
            }
          
            var stopSeq = new Delayed;
            function dispatchKey(cm, name, e, handle) {
              var seq = cm.state.keySeq;
              if (seq) {
                if (isModifierKey(name)) return "handled";
                stopSeq.set(50, function() {
                  if (cm.state.keySeq == seq) {
                    cm.state.keySeq = null;
                    cm.display.input.reset();
                  }
                });
                name = seq + " " + name;
              }
              var result = lookupKeyForEditor(cm, name, handle);
          
              if (result == "multi")
                cm.state.keySeq = name;
              if (result == "handled")
                signalLater(cm, "keyHandled", cm, name, e);
          
              if (result == "handled" || result == "multi") {
                e_preventDefault(e);
                restartBlink(cm);
              }
          
              if (seq && !result && /\'$/.test(name)) {
                e_preventDefault(e);
                return true;
              }
              return !!result;
            }
          
            // Handle a key from the keydown event.
            function handleKeyBinding(cm, e) {
              var name = keyName(e, true);
              if (!name) return false;
          
              if (e.shiftKey && !cm.state.keySeq) {
                // First try to resolve full name (including 'Shift-'). Failing
                // that, see if there is a cursor-motion command (starting with
                // 'go') bound to the keyname without 'Shift-'.
                return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);})
                    || dispatchKey(cm, name, e, function(b) {
                         if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
                           return doHandleBinding(cm, b);
                       });
              } else {
                return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); });
              }
            }
          
            // Handle a key from the keypress event
            function handleCharBinding(cm, e, ch) {
              return dispatchKey(cm, "'" + ch + "'", e,
                                 function(b) { return doHandleBinding(cm, b, true); });
            }
          
            var lastStoppedKey = null;
            function onKeyDown(e) {
              var cm = this;
              cm.curOp.focus = activeElt();
              if (signalDOMEvent(cm, e)) return;
              // IE does strange things with escape.
              if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false;
              var code = e.keyCode;
              cm.display.shift = code == 16 || e.shiftKey;
              var handled = handleKeyBinding(cm, e);
              if (presto) {
                lastStoppedKey = handled ? code : null;
                // Opera has no cut event... we try to at least catch the key combo
                if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
                  cm.replaceSelection("", null, "cut");
              }
          
              // Turn mouse into crosshair when Alt is held on Mac.
              if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
                showCrossHair(cm);
            }
          
            function showCrossHair(cm) {
              var lineDiv = cm.display.lineDiv;
              addClass(lineDiv, "CodeMirror-crosshair");
          
              function up(e) {
                if (e.keyCode == 18 || !e.altKey) {
                  rmClass(lineDiv, "CodeMirror-crosshair");
                  off(document, "keyup", up);
                  off(document, "mouseover", up);
                }
              }
              on(document, "keyup", up);
              on(document, "mouseover", up);
            }
          
            function onKeyUp(e) {
              if (e.keyCode == 16) this.doc.sel.shift = false;
              signalDOMEvent(this, e);
            }
          
            function onKeyPress(e) {
              var cm = this;
              if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return;
              var keyCode = e.keyCode, charCode = e.charCode;
              if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
              if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) return;
              var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
              if (handleCharBinding(cm, e, ch)) return;
              cm.display.input.onKeyPress(e);
            }
          
            // FOCUS/BLUR EVENTS
          
            function delayBlurEvent(cm) {
              cm.state.delayingBlurEvent = true;
              setTimeout(function() {
                if (cm.state.delayingBlurEvent) {
                  cm.state.delayingBlurEvent = false;
                  onBlur(cm);
                }
              }, 100);
            }
          
            function onFocus(cm) {
              if (cm.state.delayingBlurEvent) cm.state.delayingBlurEvent = false;
          
              if (cm.options.readOnly == "nocursor") return;
              if (!cm.state.focused) {
                signal(cm, "focus", cm);
                cm.state.focused = true;
                addClass(cm.display.wrapper, "CodeMirror-focused");
                // This test prevents this from firing when a context
                // menu is closed (since the input reset would kill the
                // select-all detection hack)
                if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
                  cm.display.input.reset();
                  if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue #1730
                }
                cm.display.input.receivedFocus();
              }
              restartBlink(cm);
            }
            function onBlur(cm) {
              if (cm.state.delayingBlurEvent) return;
          
              if (cm.state.focused) {
                signal(cm, "blur", cm);
                cm.state.focused = false;
                rmClass(cm.display.wrapper, "CodeMirror-focused");
              }
              clearInterval(cm.display.blinker);
              setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150);
            }
          
            // CONTEXT MENU HANDLING
          
            // To make the context menu work, we need to briefly unhide the
            // textarea (making it as unobtrusive as possible) to let the
            // right-click take effect on it.
            function onContextMenu(cm, e) {
              if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return;
              cm.display.input.onContextMenu(e);
            }
          
            function contextMenuInGutter(cm, e) {
              if (!hasHandler(cm, "gutterContextMenu")) return false;
              return gutterEvent(cm, e, "gutterContextMenu", false, signal);
            }
          
            // UPDATING
          
            // Compute the position of the end of a change (its 'to' property
            // refers to the pre-change end).
            var changeEnd = CodeMirror.changeEnd = function(change) {
              if (!change.text) return change.to;
              return Pos(change.from.line + change.text.length - 1,
                         lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
            };
          
            // Adjust a position to refer to the post-change position of the
            // same text, or the end of the change if the change covers it.
            function adjustForChange(pos, change) {
              if (cmp(pos, change.from) < 0) return pos;
              if (cmp(pos, change.to) <= 0) return changeEnd(change);
          
              var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
              if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch;
              return Pos(line, ch);
            }
          
            function computeSelAfterChange(doc, change) {
              var out = [];
              for (var i = 0; i < doc.sel.ranges.length; i++) {
                var range = doc.sel.ranges[i];
                out.push(new Range(adjustForChange(range.anchor, change),
                                   adjustForChange(range.head, change)));
              }
              return normalizeSelection(out, doc.sel.primIndex);
            }
          
            function offsetPos(pos, old, nw) {
              if (pos.line == old.line)
                return Pos(nw.line, pos.ch - old.ch + nw.ch);
              else
                return Pos(nw.line + (pos.line - old.line), pos.ch);
            }
          
            // Used by replaceSelections to allow moving the selection to the
            // start or around the replaced test. Hint may be "start" or "around".
            function computeReplacedSel(doc, changes, hint) {
              var out = [];
              var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;
              for (var i = 0; i < changes.length; i++) {
                var change = changes[i];
                var from = offsetPos(change.from, oldPrev, newPrev);
                var to = offsetPos(changeEnd(change), oldPrev, newPrev);
                oldPrev = change.to;
                newPrev = to;
                if (hint == "around") {
                  var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;
                  out[i] = new Range(inv ? to : from, inv ? from : to);
                } else {
                  out[i] = new Range(from, from);
                }
              }
              return new Selection(out, doc.sel.primIndex);
            }
          
            // Allow "beforeChange" event handlers to influence a change
            function filterChange(doc, change, update) {
              var obj = {
                canceled: false,
                from: change.from,
                to: change.to,
                text: change.text,
                origin: change.origin,
                cancel: function() { this.canceled = true; }
              };
              if (update) obj.update = function(from, to, text, origin) {
                if (from) this.from = clipPos(doc, from);
                if (to) this.to = clipPos(doc, to);
                if (text) this.text = text;
                if (origin !== undefined) this.origin = origin;
              };
              signal(doc, "beforeChange", doc, obj);
              if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
          
              if (obj.canceled) return null;
              return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
            }
          
            // Apply a change to a document, and add it to the document's
            // history, and propagating it to all linked documents.
            function makeChange(doc, change, ignoreReadOnly) {
              if (doc.cm) {
                if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly);
                if (doc.cm.state.suppressEdits) return;
              }
          
              if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
                change = filterChange(doc, change, true);
                if (!change) return;
              }
          
              // Possibly split or suppress the update based on the presence
              // of read-only spans in its range.
              var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
              if (split) {
                for (var i = split.length - 1; i >= 0; --i)
                  makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text});
              } else {
                makeChangeInner(doc, change);
              }
            }
          
            function makeChangeInner(doc, change) {
              if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) return;
              var selAfter = computeSelAfterChange(doc, change);
              addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
          
              makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
              var rebased = [];
          
              linkedDocs(doc, function(doc, sharedHist) {
                if (!sharedHist && indexOf(rebased, doc.history) == -1) {
                  rebaseHist(doc.history, change);
                  rebased.push(doc.history);
                }
                makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
              });
            }
          
            // Revert a change stored in a document's history.
            function makeChangeFromHistory(doc, type, allowSelectionOnly) {
              if (doc.cm && doc.cm.state.suppressEdits) return;
          
              var hist = doc.history, event, selAfter = doc.sel;
              var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done;
          
              // Verify that there is a useable event (so that ctrl-z won't
              // needlessly clear selection events)
              for (var i = 0; i < source.length; i++) {
                event = source[i];
                if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
                  break;
              }
              if (i == source.length) return;
              hist.lastOrigin = hist.lastSelOrigin = null;
          
              for (;;) {
                event = source.pop();
                if (event.ranges) {
                  pushSelectionToHistory(event, dest);
                  if (allowSelectionOnly && !event.equals(doc.sel)) {
                    setSelection(doc, event, {clearRedo: false});
                    return;
                  }
                  selAfter = event;
                }
                else break;
              }
          
              // Build up a reverse change object to add to the opposite history
              // stack (redo when undoing, and vice versa).
              var antiChanges = [];
              pushSelectionToHistory(selAfter, dest);
              dest.push({changes: antiChanges, generation: hist.generation});
              hist.generation = event.generation || ++hist.maxGeneration;
          
              var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
          
              for (var i = event.changes.length - 1; i >= 0; --i) {
                var change = event.changes[i];
                change.origin = type;
                if (filter && !filterChange(doc, change, false)) {
                  source.length = 0;
                  return;
                }
          
                antiChanges.push(historyChangeFromChange(doc, change));
          
                var after = i ? computeSelAfterChange(doc, change) : lst(source);
                makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
                if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)});
                var rebased = [];
          
                // Propagate to the linked documents
                linkedDocs(doc, function(doc, sharedHist) {
                  if (!sharedHist && indexOf(rebased, doc.history) == -1) {
                    rebaseHist(doc.history, change);
                    rebased.push(doc.history);
                  }
                  makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
                });
              }
            }
          
            // Sub-views need their line numbers shifted when text is added
            // above or below them in the parent document.
            function shiftDoc(doc, distance) {
              if (distance == 0) return;
              doc.first += distance;
              doc.sel = new Selection(map(doc.sel.ranges, function(range) {
                return new Range(Pos(range.anchor.line + distance, range.anchor.ch),
                                 Pos(range.head.line + distance, range.head.ch));
              }), doc.sel.primIndex);
              if (doc.cm) {
                regChange(doc.cm, doc.first, doc.first - distance, distance);
                for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
                  regLineChange(doc.cm, l, "gutter");
              }
            }
          
            // More lower-level change function, handling only a single document
            // (not linked ones).
            function makeChangeSingleDoc(doc, change, selAfter, spans) {
              if (doc.cm && !doc.cm.curOp)
                return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
          
              if (change.to.line < doc.first) {
                shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
                return;
              }
              if (change.from.line > doc.lastLine()) return;
          
              // Clip the change to the size of this doc
              if (change.from.line < doc.first) {
                var shift = change.text.length - 1 - (doc.first - change.from.line);
                shiftDoc(doc, shift);
                change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
                          text: [lst(change.text)], origin: change.origin};
              }
              var last = doc.lastLine();
              if (change.to.line > last) {
                change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
                          text: [change.text[0]], origin: change.origin};
              }
          
              change.removed = getBetween(doc, change.from, change.to);
          
              if (!selAfter) selAfter = computeSelAfterChange(doc, change);
              if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans);
              else updateDoc(doc, change, spans);
              setSelectionNoUndo(doc, selAfter, sel_dontScroll);
            }
          
            // Handle the interaction of a change to a document with the editor
            // that this document is part of.
            function makeChangeSingleDocInEditor(cm, change, spans) {
              var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
          
              var recomputeMaxLength = false, checkWidthStart = from.line;
              if (!cm.options.lineWrapping) {
                checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));
                doc.iter(checkWidthStart, to.line + 1, function(line) {
                  if (line == display.maxLine) {
                    recomputeMaxLength = true;
                    return true;
                  }
                });
              }
          
              if (doc.sel.contains(change.from, change.to) > -1)
                signalCursorActivity(cm);
          
              updateDoc(doc, change, spans, estimateHeight(cm));
          
              if (!cm.options.lineWrapping) {
                doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
                  var len = lineLength(line);
                  if (len > display.maxLineLength) {
                    display.maxLine = line;
                    display.maxLineLength = len;
                    display.maxLineChanged = true;
                    recomputeMaxLength = false;
                  }
                });
                if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
              }
          
              // Adjust frontier, schedule worker
              doc.frontier = Math.min(doc.frontier, from.line);
              startWorker(cm, 400);
          
              var lendiff = change.text.length - (to.line - from.line) - 1;
              // Remember that these lines changed, for updating the display
              if (change.full)
                regChange(cm);
              else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
                regLineChange(cm, from.line, "text");
              else
                regChange(cm, from.line, to.line + 1, lendiff);
          
              var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change");
              if (changeHandler || changesHandler) {
                var obj = {
                  from: from, to: to,
                  text: change.text,
                  removed: change.removed,
                  origin: change.origin
                };
                if (changeHandler) signalLater(cm, "change", cm, obj);
                if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj);
              }
              cm.display.selForContextMenu = null;
            }
          
            function replaceRange(doc, code, from, to, origin) {
              if (!to) to = from;
              if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }
              if (typeof code == "string") code = splitLines(code);
              makeChange(doc, {from: from, to: to, text: code, origin: origin});
            }
          
            // SCROLLING THINGS INTO VIEW
          
            // If an editor sits on the top or bottom of the window, partially
            // scrolled out of view, this ensures that the cursor is visible.
            function maybeScrollWindow(cm, coords) {
              if (signalDOMEvent(cm, "scrollCursorIntoView")) return;
          
              var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
              if (coords.top + box.top < 0) doScroll = true;
              else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
              if (doScroll != null && !phantom) {
                var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " +
                                     (coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " +
                                     (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px; left: " +
                                     coords.left + "px; width: 2px;");
                cm.display.lineSpace.appendChild(scrollNode);
                scrollNode.scrollIntoView(doScroll);
                cm.display.lineSpace.removeChild(scrollNode);
              }
            }
          
            // Scroll a given position into view (immediately), verifying that
            // it actually became visible (as line heights are accurately
            // measured, the position of something may 'drift' during drawing).
            function scrollPosIntoView(cm, pos, end, margin) {
              if (margin == null) margin = 0;
              for (var limit = 0; limit < 5; limit++) {
                var changed = false, coords = cursorCoords(cm, pos);
                var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
                var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
                                                   Math.min(coords.top, endCoords.top) - margin,
                                                   Math.max(coords.left, endCoords.left),
                                                   Math.max(coords.bottom, endCoords.bottom) + margin);
                var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
                if (scrollPos.scrollTop != null) {
                  setScrollTop(cm, scrollPos.scrollTop);
                  if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
                }
                if (scrollPos.scrollLeft != null) {
                  setScrollLeft(cm, scrollPos.scrollLeft);
                  if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
                }
                if (!changed) break;
              }
              return coords;
            }
          
            // Scroll a given set of coordinates into view (immediately).
            function scrollIntoView(cm, x1, y1, x2, y2) {
              var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
              if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
              if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
            }
          
            // Calculate a new scroll position needed to scroll the given
            // rectangle into view. Returns an object with scrollTop and
            // scrollLeft properties. When these are undefined, the
            // vertical/horizontal position does not need to be adjusted.
            function calculateScrollPos(cm, x1, y1, x2, y2) {
              var display = cm.display, snapMargin = textHeight(cm.display);
              if (y1 < 0) y1 = 0;
              var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;
              var screen = displayHeight(cm), result = {};
              if (y2 - y1 > screen) y2 = y1 + screen;
              var docBottom = cm.doc.height + paddingVert(display);
              var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
              if (y1 < screentop) {
                result.scrollTop = atTop ? 0 : y1;
              } else if (y2 > screentop + screen) {
                var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
                if (newTop != screentop) result.scrollTop = newTop;
              }
          
              var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;
              var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);
              var tooWide = x2 - x1 > screenw;
              if (tooWide) x2 = x1 + screenw;
              if (x1 < 10)
                result.scrollLeft = 0;
              else if (x1 < screenleft)
                result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10));
              else if (x2 > screenw + screenleft - 3)
                result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw;
              return result;
            }
          
            // Store a relative adjustment to the scroll position in the current
            // operation (to be applied when the operation finishes).
            function addToScrollPos(cm, left, top) {
              if (left != null || top != null) resolveScrollToPos(cm);
              if (left != null)
                cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left;
              if (top != null)
                cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;
            }
          
            // Make sure that at the end of the operation the current cursor is
            // shown.
            function ensureCursorVisible(cm) {
              resolveScrollToPos(cm);
              var cur = cm.getCursor(), from = cur, to = cur;
              if (!cm.options.lineWrapping) {
                from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur;
                to = Pos(cur.line, cur.ch + 1);
              }
              cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true};
            }
          
            // When an operation has its scrollToPos property set, and another
            // scroll action is applied before the end of the operation, this
            // 'simulates' scrolling that position into view in a cheap way, so
            // that the effect of intermediate scroll commands is not ignored.
            function resolveScrollToPos(cm) {
              var range = cm.curOp.scrollToPos;
              if (range) {
                cm.curOp.scrollToPos = null;
                var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to);
                var sPos = calculateScrollPos(cm, Math.min(from.left, to.left),
                                              Math.min(from.top, to.top) - range.margin,
                                              Math.max(from.right, to.right),
                                              Math.max(from.bottom, to.bottom) + range.margin);
                cm.scrollTo(sPos.scrollLeft, sPos.scrollTop);
              }
            }
          
            // API UTILITIES
          
            // Indent the given line. The how parameter can be "smart",
            // "add"/null, "subtract", or "prev". When aggressive is false
            // (typically set to true for forced single-line indents), empty
            // lines are not indented, and places where the mode returns Pass
            // are left alone.
            function indentLine(cm, n, how, aggressive) {
              var doc = cm.doc, state;
              if (how == null) how = "add";
              if (how == "smart") {
                // Fall back to "prev" when the mode doesn't have an indentation
                // method.
                if (!doc.mode.indent) how = "prev";
                else state = getStateBefore(cm, n);
              }
          
              var tabSize = cm.options.tabSize;
              var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
              if (line.stateAfter) line.stateAfter = null;
              var curSpaceString = line.text.match(/^\s*/)[0], indentation;
              if (!aggressive && !/\S/.test(line.text)) {
                indentation = 0;
                how = "not";
              } else if (how == "smart") {
                indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
                if (indentation == Pass || indentation > 150) {
                  if (!aggressive) return;
                  how = "prev";
                }
              }
              if (how == "prev") {
                if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
                else indentation = 0;
              } else if (how == "add") {
                indentation = curSpace + cm.options.indentUnit;
              } else if (how == "subtract") {
                indentation = curSpace - cm.options.indentUnit;
              } else if (typeof how == "number") {
                indentation = curSpace + how;
              }
              indentation = Math.max(0, indentation);
          
              var indentString = "", pos = 0;
              if (cm.options.indentWithTabs)
                for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
              if (pos < indentation) indentString += spaceStr(indentation - pos);
          
              if (indentString != curSpaceString) {
                replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
                line.stateAfter = null;
                return true;
              } else {
                // Ensure that, if the cursor was in the whitespace at the start
                // of the line, it is moved to the end of that space.
                for (var i = 0; i < doc.sel.ranges.length; i++) {
                  var range = doc.sel.ranges[i];
                  if (range.head.line == n && range.head.ch < curSpaceString.length) {
                    var pos = Pos(n, curSpaceString.length);
                    replaceOneSelection(doc, i, new Range(pos, pos));
                    break;
                  }
                }
              }
            }
          
            // Utility for applying a change to a line by handle or number,
            // returning the number and optionally registering the line as
            // changed.
            function changeLine(doc, handle, changeType, op) {
              var no = handle, line = handle;
              if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
              else no = lineNo(handle);
              if (no == null) return null;
              if (op(line, no) && doc.cm) regLineChange(doc.cm, no, changeType);
              return line;
            }
          
            // Helper for deleting text near the selection(s), used to implement
            // backspace, delete, and similar functionality.
            function deleteNearSelection(cm, compute) {
              var ranges = cm.doc.sel.ranges, kill = [];
              // Build up a set of ranges to kill first, merging overlapping
              // ranges.
              for (var i = 0; i < ranges.length; i++) {
                var toKill = compute(ranges[i]);
                while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
                  var replaced = kill.pop();
                  if (cmp(replaced.from, toKill.from) < 0) {
                    toKill.from = replaced.from;
                    break;
                  }
                }
                kill.push(toKill);
              }
              // Next, remove those actual ranges.
              runInOp(cm, function() {
                for (var i = kill.length - 1; i >= 0; i--)
                  replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete");
                ensureCursorVisible(cm);
              });
            }
          
            // Used for horizontal relative motion. Dir is -1 or 1 (left or
            // right), unit can be "char", "column" (like char, but doesn't
            // cross line boundaries), "word" (across next word), or "group" (to
            // the start of next group of word or non-word-non-whitespace
            // chars). The visually param controls whether, in right-to-left
            // text, direction 1 means to move towards the next index in the
            // string, or towards the character to the right of the current
            // position. The resulting position will have a hitSide=true
            // property if it reached the end of the document.
            function findPosH(doc, pos, dir, unit, visually) {
              var line = pos.line, ch = pos.ch, origDir = dir;
              var lineObj = getLine(doc, line);
              var possible = true;
              function findNextLine() {
                var l = line + dir;
                if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
                line = l;
                return lineObj = getLine(doc, l);
              }
              function moveOnce(boundToLine) {
                var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
                if (next == null) {
                  if (!boundToLine && findNextLine()) {
                    if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
                    else ch = dir < 0 ? lineObj.text.length : 0;
                  } else return (possible = false);
                } else ch = next;
                return true;
              }
          
              if (unit == "char") moveOnce();
              else if (unit == "column") moveOnce(true);
              else if (unit == "word" || unit == "group") {
                var sawType = null, group = unit == "group";
                var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
                for (var first = true;; first = false) {
                  if (dir < 0 && !moveOnce(!first)) break;
                  var cur = lineObj.text.charAt(ch) || "\n";
                  var type = isWordChar(cur, helper) ? "w"
                    : group && cur == "\n" ? "n"
                    : !group || /\s/.test(cur) ? null
                    : "p";
                  if (group && !first && !type) type = "s";
                  if (sawType && sawType != type) {
                    if (dir < 0) {dir = 1; moveOnce();}
                    break;
                  }
          
                  if (type) sawType = type;
                  if (dir > 0 && !moveOnce(!first)) break;
                }
              }
              var result = skipAtomic(doc, Pos(line, ch), origDir, true);
              if (!possible) result.hitSide = true;
              return result;
            }
          
            // For relative vertical movement. Dir may be -1 or 1. Unit can be
            // "page" or "line". The resulting position will have a hitSide=true
            // property if it reached the end of the document.
            function findPosV(cm, pos, dir, unit) {
              var doc = cm.doc, x = pos.left, y;
              if (unit == "page") {
                var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
                y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
              } else if (unit == "line") {
                y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
              }
              for (;;) {
                var target = coordsChar(cm, x, y);
                if (!target.outside) break;
                if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
                y += dir * 5;
              }
              return target;
            }
          
            // EDITOR METHODS
          
            // The publicly visible API. Note that methodOp(f) means
            // 'wrap f in an operation, performed on its `this` parameter'.
          
            // This is not the complete set of editor methods. Most of the
            // methods defined on the Doc type are also injected into
            // CodeMirror.prototype, for backwards compatibility and
            // convenience.
          
            CodeMirror.prototype = {
              constructor: CodeMirror,
              focus: function(){window.focus(); this.display.input.focus();},
          
              setOption: function(option, value) {
                var options = this.options, old = options[option];
                if (options[option] == value && option != "mode") return;
                options[option] = value;
                if (optionHandlers.hasOwnProperty(option))
                  operation(this, optionHandlers[option])(this, value, old);
              },
          
              getOption: function(option) {return this.options[option];},
              getDoc: function() {return this.doc;},
          
              addKeyMap: function(map, bottom) {
                this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map));
              },
              removeKeyMap: function(map) {
                var maps = this.state.keyMaps;
                for (var i = 0; i < maps.length; ++i)
                  if (maps[i] == map || maps[i].name == map) {
                    maps.splice(i, 1);
                    return true;
                  }
              },
          
              addOverlay: methodOp(function(spec, options) {
                var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
                if (mode.startState) throw new Error("Overlays may not be stateful.");
                this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
                this.state.modeGen++;
                regChange(this);
              }),
              removeOverlay: methodOp(function(spec) {
                var overlays = this.state.overlays;
                for (var i = 0; i < overlays.length; ++i) {
                  var cur = overlays[i].modeSpec;
                  if (cur == spec || typeof spec == "string" && cur.name == spec) {
                    overlays.splice(i, 1);
                    this.state.modeGen++;
                    regChange(this);
                    return;
                  }
                }
              }),
          
              indentLine: methodOp(function(n, dir, aggressive) {
                if (typeof dir != "string" && typeof dir != "number") {
                  if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
                  else dir = dir ? "add" : "subtract";
                }
                if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
              }),
              indentSelection: methodOp(function(how) {
                var ranges = this.doc.sel.ranges, end = -1;
                for (var i = 0; i < ranges.length; i++) {
                  var range = ranges[i];
                  if (!range.empty()) {
                    var from = range.from(), to = range.to();
                    var start = Math.max(end, from.line);
                    end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
                    for (var j = start; j < end; ++j)
                      indentLine(this, j, how);
                    var newRanges = this.doc.sel.ranges;
                    if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
                      replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll);
                  } else if (range.head.line > end) {
                    indentLine(this, range.head.line, how, true);
                    end = range.head.line;
                    if (i == this.doc.sel.primIndex) ensureCursorVisible(this);
                  }
                }
              }),
          
              // Fetch the parser token for a given character. Useful for hacks
              // that want to inspect the mode state (say, for completion).
              getTokenAt: function(pos, precise) {
                return takeToken(this, pos, precise);
              },
          
              getLineTokens: function(line, precise) {
                return takeToken(this, Pos(line), precise, true);
              },
          
              getTokenTypeAt: function(pos) {
                pos = clipPos(this.doc, pos);
                var styles = getLineStyles(this, getLine(this.doc, pos.line));
                var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
                var type;
                if (ch == 0) type = styles[2];
                else for (;;) {
                  var mid = (before + after) >> 1;
                  if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
                  else if (styles[mid * 2 + 1] < ch) before = mid + 1;
                  else { type = styles[mid * 2 + 2]; break; }
                }
                var cut = type ? type.indexOf("cm-overlay ") : -1;
                return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1);
              },
          
              getModeAt: function(pos) {
                var mode = this.doc.mode;
                if (!mode.innerMode) return mode;
                return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
              },
          
              getHelper: function(pos, type) {
                return this.getHelpers(pos, type)[0];
              },
          
              getHelpers: function(pos, type) {
                var found = [];
                if (!helpers.hasOwnProperty(type)) return found;
                var help = helpers[type], mode = this.getModeAt(pos);
                if (typeof mode[type] == "string") {
                  if (help[mode[type]]) found.push(help[mode[type]]);
                } else if (mode[type]) {
                  for (var i = 0; i < mode[type].length; i++) {
                    var val = help[mode[type][i]];
                    if (val) found.push(val);
                  }
                } else if (mode.helperType && help[mode.helperType]) {
                  found.push(help[mode.helperType]);
                } else if (help[mode.name]) {
                  found.push(help[mode.name]);
                }
                for (var i = 0; i < help._global.length; i++) {
                  var cur = help._global[i];
                  if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
                    found.push(cur.val);
                }
                return found;
              },
          
              getStateAfter: function(line, precise) {
                var doc = this.doc;
                line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
                return getStateBefore(this, line + 1, precise);
              },
          
              cursorCoords: function(start, mode) {
                var pos, range = this.doc.sel.primary();
                if (start == null) pos = range.head;
                else if (typeof start == "object") pos = clipPos(this.doc, start);
                else pos = start ? range.from() : range.to();
                return cursorCoords(this, pos, mode || "page");
              },
          
              charCoords: function(pos, mode) {
                return charCoords(this, clipPos(this.doc, pos), mode || "page");
              },
          
              coordsChar: function(coords, mode) {
                coords = fromCoordSystem(this, coords, mode || "page");
                return coordsChar(this, coords.left, coords.top);
              },
          
              lineAtHeight: function(height, mode) {
                height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
                return lineAtHeight(this.doc, height + this.display.viewOffset);
              },
              heightAtLine: function(line, mode) {
                var end = false, lineObj;
                if (typeof line == "number") {
                  var last = this.doc.first + this.doc.size - 1;
                  if (line < this.doc.first) line = this.doc.first;
                  else if (line > last) { line = last; end = true; }
                  lineObj = getLine(this.doc, line);
                } else {
                  lineObj = line;
                }
                return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top +
                  (end ? this.doc.height - heightAtLine(lineObj) : 0);
              },
          
              defaultTextHeight: function() { return textHeight(this.display); },
              defaultCharWidth: function() { return charWidth(this.display); },
          
              setGutterMarker: methodOp(function(line, gutterID, value) {
                return changeLine(this.doc, line, "gutter", function(line) {
                  var markers = line.gutterMarkers || (line.gutterMarkers = {});
                  markers[gutterID] = value;
                  if (!value && isEmpty(markers)) line.gutterMarkers = null;
                  return true;
                });
              }),
          
              clearGutter: methodOp(function(gutterID) {
                var cm = this, doc = cm.doc, i = doc.first;
                doc.iter(function(line) {
                  if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
                    line.gutterMarkers[gutterID] = null;
                    regLineChange(cm, i, "gutter");
                    if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
                  }
                  ++i;
                });
              }),
          
              lineInfo: function(line) {
                if (typeof line == "number") {
                  if (!isLine(this.doc, line)) return null;
                  var n = line;
                  line = getLine(this.doc, line);
                  if (!line) return null;
                } else {
                  var n = lineNo(line);
                  if (n == null) return null;
                }
                return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
                        textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
                        widgets: line.widgets};
              },
          
              getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};},
          
              addWidget: function(pos, node, scroll, vert, horiz) {
                var display = this.display;
                pos = cursorCoords(this, clipPos(this.doc, pos));
                var top = pos.bottom, left = pos.left;
                node.style.position = "absolute";
                node.setAttribute("cm-ignore-events", "true");
                this.display.input.setUneditable(node);
                display.sizer.appendChild(node);
                if (vert == "over") {
                  top = pos.top;
                } else if (vert == "above" || vert == "near") {
                  var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
                  hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
                  // Default to positioning above (if specified and possible); otherwise default to positioning below
                  if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
                    top = pos.top - node.offsetHeight;
                  else if (pos.bottom + node.offsetHeight <= vspace)
                    top = pos.bottom;
                  if (left + node.offsetWidth > hspace)
                    left = hspace - node.offsetWidth;
                }
                node.style.top = top + "px";
                node.style.left = node.style.right = "";
                if (horiz == "right") {
                  left = display.sizer.clientWidth - node.offsetWidth;
                  node.style.right = "0px";
                } else {
                  if (horiz == "left") left = 0;
                  else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
                  node.style.left = left + "px";
                }
                if (scroll)
                  scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
              },
          
              triggerOnKeyDown: methodOp(onKeyDown),
              triggerOnKeyPress: methodOp(onKeyPress),
              triggerOnKeyUp: onKeyUp,
          
              execCommand: function(cmd) {
                if (commands.hasOwnProperty(cmd))
                  return commands[cmd](this);
              },
          
              triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),
          
              findPosH: function(from, amount, unit, visually) {
                var dir = 1;
                if (amount < 0) { dir = -1; amount = -amount; }
                for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
                  cur = findPosH(this.doc, cur, dir, unit, visually);
                  if (cur.hitSide) break;
                }
                return cur;
              },
          
              moveH: methodOp(function(dir, unit) {
                var cm = this;
                cm.extendSelectionsBy(function(range) {
                  if (cm.display.shift || cm.doc.extend || range.empty())
                    return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually);
                  else
                    return dir < 0 ? range.from() : range.to();
                }, sel_move);
              }),
          
              deleteH: methodOp(function(dir, unit) {
                var sel = this.doc.sel, doc = this.doc;
                if (sel.somethingSelected())
                  doc.replaceSelection("", null, "+delete");
                else
                  deleteNearSelection(this, function(range) {
                    var other = findPosH(doc, range.head, dir, unit, false);
                    return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other};
                  });
              }),
          
              findPosV: function(from, amount, unit, goalColumn) {
                var dir = 1, x = goalColumn;
                if (amount < 0) { dir = -1; amount = -amount; }
                for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
                  var coords = cursorCoords(this, cur, "div");
                  if (x == null) x = coords.left;
                  else coords.left = x;
                  cur = findPosV(this, coords, dir, unit);
                  if (cur.hitSide) break;
                }
                return cur;
              },
          
              moveV: methodOp(function(dir, unit) {
                var cm = this, doc = this.doc, goals = [];
                var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected();
                doc.extendSelectionsBy(function(range) {
                  if (collapse)
                    return dir < 0 ? range.from() : range.to();
                  var headPos = cursorCoords(cm, range.head, "div");
                  if (range.goalColumn != null) headPos.left = range.goalColumn;
                  goals.push(headPos.left);
                  var pos = findPosV(cm, headPos, dir, unit);
                  if (unit == "page" && range == doc.sel.primary())
                    addToScrollPos(cm, null, charCoords(cm, pos, "div").top - headPos.top);
                  return pos;
                }, sel_move);
                if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++)
                  doc.sel.ranges[i].goalColumn = goals[i];
              }),
          
              // Find the word at the given position (as returned by coordsChar).
              findWordAt: function(pos) {
                var doc = this.doc, line = getLine(doc, pos.line).text;
                var start = pos.ch, end = pos.ch;
                if (line) {
                  var helper = this.getHelper(pos, "wordChars");
                  if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
                  var startChar = line.charAt(start);
                  var check = isWordChar(startChar, helper)
                    ? function(ch) { return isWordChar(ch, helper); }
                    : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
                    : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
                  while (start > 0 && check(line.charAt(start - 1))) --start;
                  while (end < line.length && check(line.charAt(end))) ++end;
                }
                return new Range(Pos(pos.line, start), Pos(pos.line, end));
              },
          
              toggleOverwrite: function(value) {
                if (value != null && value == this.state.overwrite) return;
                if (this.state.overwrite = !this.state.overwrite)
                  addClass(this.display.cursorDiv, "CodeMirror-overwrite");
                else
                  rmClass(this.display.cursorDiv, "CodeMirror-overwrite");
          
                signal(this, "overwriteToggle", this, this.state.overwrite);
              },
              hasFocus: function() { return this.display.input.getField() == activeElt(); },
          
              scrollTo: methodOp(function(x, y) {
                if (x != null || y != null) resolveScrollToPos(this);
                if (x != null) this.curOp.scrollLeft = x;
                if (y != null) this.curOp.scrollTop = y;
              }),
              getScrollInfo: function() {
                var scroller = this.display.scroller;
                return {left: scroller.scrollLeft, top: scroller.scrollTop,
                        height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
                        width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
                        clientHeight: displayHeight(this), clientWidth: displayWidth(this)};
              },
          
              scrollIntoView: methodOp(function(range, margin) {
                if (range == null) {
                  range = {from: this.doc.sel.primary().head, to: null};
                  if (margin == null) margin = this.options.cursorScrollMargin;
                } else if (typeof range == "number") {
                  range = {from: Pos(range, 0), to: null};
                } else if (range.from == null) {
                  range = {from: range, to: null};
                }
                if (!range.to) range.to = range.from;
                range.margin = margin || 0;
          
                if (range.from.line != null) {
                  resolveScrollToPos(this);
                  this.curOp.scrollToPos = range;
                } else {
                  var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left),
                                                Math.min(range.from.top, range.to.top) - range.margin,
                                                Math.max(range.from.right, range.to.right),
                                                Math.max(range.from.bottom, range.to.bottom) + range.margin);
                  this.scrollTo(sPos.scrollLeft, sPos.scrollTop);
                }
              }),
          
              setSize: methodOp(function(width, height) {
                var cm = this;
                function interpret(val) {
                  return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
                }
                if (width != null) cm.display.wrapper.style.width = interpret(width);
                if (height != null) cm.display.wrapper.style.height = interpret(height);
                if (cm.options.lineWrapping) clearLineMeasurementCache(this);
                var lineNo = cm.display.viewFrom;
                cm.doc.iter(lineNo, cm.display.viewTo, function(line) {
                  if (line.widgets) for (var i = 0; i < line.widgets.length; i++)
                    if (line.widgets[i].noHScroll) { regLineChange(cm, lineNo, "widget"); break; }
                  ++lineNo;
                });
                cm.curOp.forceUpdate = true;
                signal(cm, "refresh", this);
              }),
          
              operation: function(f){return runInOp(this, f);},
          
              refresh: methodOp(function() {
                var oldHeight = this.display.cachedTextHeight;
                regChange(this);
                this.curOp.forceUpdate = true;
                clearCaches(this);
                this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop);
                updateGutterSpace(this);
                if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
                  estimateLineHeights(this);
                signal(this, "refresh", this);
              }),
          
              swapDoc: methodOp(function(doc) {
                var old = this.doc;
                old.cm = null;
                attachDoc(this, doc);
                clearCaches(this);
                this.display.input.reset();
                this.scrollTo(doc.scrollLeft, doc.scrollTop);
                this.curOp.forceScroll = true;
                signalLater(this, "swapDoc", this, old);
                return old;
              }),
          
              getInputField: function(){return this.display.input.getField();},
              getWrapperElement: function(){return this.display.wrapper;},
              getScrollerElement: function(){return this.display.scroller;},
              getGutterElement: function(){return this.display.gutters;}
            };
            eventMixin(CodeMirror);
          
            // OPTION DEFAULTS
          
            // The default configuration options.
            var defaults = CodeMirror.defaults = {};
            // Functions to run when options are changed.
            var optionHandlers = CodeMirror.optionHandlers = {};
          
            function option(name, deflt, handle, notOnInit) {
              CodeMirror.defaults[name] = deflt;
              if (handle) optionHandlers[name] =
                notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
            }
          
            // Passed to option handlers when there is no old value.
            var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
          
            // These two are, on init, called from the constructor because they
            // have to be initialized before the editor can start at all.
            option("value", "", function(cm, val) {
              cm.setValue(val);
            }, true);
            option("mode", null, function(cm, val) {
              cm.doc.modeOption = val;
              loadMode(cm);
            }, true);
          
            option("indentUnit", 2, loadMode, true);
            option("indentWithTabs", false);
            option("smartIndent", true);
            option("tabSize", 4, function(cm) {
              resetModeState(cm);
              clearCaches(cm);
              regChange(cm);
            }, true);
            option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val, old) {
              cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
              if (old != CodeMirror.Init) cm.refresh();
            });
            option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);
            option("electricChars", true);
            option("inputStyle", mobile ? "contenteditable" : "textarea", function() {
              throw new Error("inputStyle can not (yet) be changed in a running editor"); // FIXME
            }, true);
            option("rtlMoveVisually", !windows);
            option("wholeLineUpdateBefore", true);
          
            option("theme", "default", function(cm) {
              themeChanged(cm);
              guttersChanged(cm);
            }, true);
            option("keyMap", "default", function(cm, val, old) {
              var next = getKeyMap(val);
              var prev = old != CodeMirror.Init && getKeyMap(old);
              if (prev && prev.detach) prev.detach(cm, next);
              if (next.attach) next.attach(cm, prev || null);
            });
            option("extraKeys", null);
          
            option("lineWrapping", false, wrappingChanged, true);
            option("gutters", [], function(cm) {
              setGuttersForLineNumbers(cm.options);
              guttersChanged(cm);
            }, true);
            option("fixedGutter", true, function(cm, val) {
              cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
              cm.refresh();
            }, true);
            option("coverGutterNextToScrollbar", false, function(cm) {updateScrollbars(cm);}, true);
            option("scrollbarStyle", "native", function(cm) {
              initScrollbars(cm);
              updateScrollbars(cm);
              cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);
              cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);
            }, true);
            option("lineNumbers", false, function(cm) {
              setGuttersForLineNumbers(cm.options);
              guttersChanged(cm);
            }, true);
            option("firstLineNumber", 1, guttersChanged, true);
            option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
            option("showCursorWhenSelecting", false, updateSelection, true);
          
            option("resetSelectionOnContextMenu", true);
            option("lineWiseCopyCut", true);
          
            option("readOnly", false, function(cm, val) {
              if (val == "nocursor") {
                onBlur(cm);
                cm.display.input.blur();
                cm.display.disabled = true;
              } else {
                cm.display.disabled = false;
                if (!val) cm.display.input.reset();
              }
            });
            option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true);
            option("dragDrop", true, dragDropChanged);
          
            option("cursorBlinkRate", 530);
            option("cursorScrollMargin", 0);
            option("cursorHeight", 1, updateSelection, true);
            option("singleCursorHeightPerLine", true, updateSelection, true);
            option("workTime", 100);
            option("workDelay", 100);
            option("flattenSpans", true, resetModeState, true);
            option("addModeClass", false, resetModeState, true);
            option("pollInterval", 100);
            option("undoDepth", 200, function(cm, val){cm.doc.history.undoDepth = val;});
            option("historyEventDelay", 1250);
            option("viewportMargin", 10, function(cm){cm.refresh();}, true);
            option("maxHighlightLength", 10000, resetModeState, true);
            option("moveInputWithCursor", true, function(cm, val) {
              if (!val) cm.display.input.resetPosition();
            });
          
            option("tabindex", null, function(cm, val) {
              cm.display.input.getField().tabIndex = val || "";
            });
            option("autofocus", null);
          
            // MODE DEFINITION AND QUERYING
          
            // Known modes, by name and by MIME
            var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
          
            // Extra arguments are stored as the mode's dependencies, which is
            // used by (legacy) mechanisms like loadmode.js to automatically
            // load a mode. (Preferred mechanism is the require/define calls.)
            CodeMirror.defineMode = function(name, mode) {
              if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
              if (arguments.length > 2)
                mode.dependencies = Array.prototype.slice.call(arguments, 2);
              modes[name] = mode;
            };
          
            CodeMirror.defineMIME = function(mime, spec) {
              mimeModes[mime] = spec;
            };
          
            // Given a MIME type, a {name, ...options} config object, or a name
            // string, return a mode config object.
            CodeMirror.resolveMode = function(spec) {
              if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
                spec = mimeModes[spec];
              } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
                var found = mimeModes[spec.name];
                if (typeof found == "string") found = {name: found};
                spec = createObj(found, spec);
                spec.name = found.name;
              } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
                return CodeMirror.resolveMode("application/xml");
              }
              if (typeof spec == "string") return {name: spec};
              else return spec || {name: "null"};
            };
          
            // Given a mode spec (anything that resolveMode accepts), find and
            // initialize an actual mode object.
            CodeMirror.getMode = function(options, spec) {
              var spec = CodeMirror.resolveMode(spec);
              var mfactory = modes[spec.name];
              if (!mfactory) return CodeMirror.getMode(options, "text/plain");
              var modeObj = mfactory(options, spec);
              if (modeExtensions.hasOwnProperty(spec.name)) {
                var exts = modeExtensions[spec.name];
                for (var prop in exts) {
                  if (!exts.hasOwnProperty(prop)) continue;
                  if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
                  modeObj[prop] = exts[prop];
                }
              }
              modeObj.name = spec.name;
              if (spec.helperType) modeObj.helperType = spec.helperType;
              if (spec.modeProps) for (var prop in spec.modeProps)
                modeObj[prop] = spec.modeProps[prop];
          
              return modeObj;
            };
          
            // Minimal default mode.
            CodeMirror.defineMode("null", function() {
              return {token: function(stream) {stream.skipToEnd();}};
            });
            CodeMirror.defineMIME("text/plain", "null");
          
            // This can be used to attach properties to mode objects from
            // outside the actual mode definition.
            var modeExtensions = CodeMirror.modeExtensions = {};
            CodeMirror.extendMode = function(mode, properties) {
              var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
              copyObj(properties, exts);
            };
          
            // EXTENSIONS
          
            CodeMirror.defineExtension = function(name, func) {
              CodeMirror.prototype[name] = func;
            };
            CodeMirror.defineDocExtension = function(name, func) {
              Doc.prototype[name] = func;
            };
            CodeMirror.defineOption = option;
          
            var initHooks = [];
            CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
          
            var helpers = CodeMirror.helpers = {};
            CodeMirror.registerHelper = function(type, name, value) {
              if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []};
              helpers[type][name] = value;
            };
            CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
              CodeMirror.registerHelper(type, name, value);
              helpers[type]._global.push({pred: predicate, val: value});
            };
          
            // MODE STATE HANDLING
          
            // Utility functions for working with state. Exported because nested
            // modes need to do this for their inner modes.
          
            var copyState = CodeMirror.copyState = function(mode, state) {
              if (state === true) return state;
              if (mode.copyState) return mode.copyState(state);
              var nstate = {};
              for (var n in state) {
                var val = state[n];
                if (val instanceof Array) val = val.concat([]);
                nstate[n] = val;
              }
              return nstate;
            };
          
            var startState = CodeMirror.startState = function(mode, a1, a2) {
              return mode.startState ? mode.startState(a1, a2) : true;
            };
          
            // Given a mode and a state (for that mode), find the inner mode and
            // state at the position that the state refers to.
            CodeMirror.innerMode = function(mode, state) {
              while (mode.innerMode) {
                var info = mode.innerMode(state);
                if (!info || info.mode == mode) break;
                state = info.state;
                mode = info.mode;
              }
              return info || {mode: mode, state: state};
            };
          
            // STANDARD COMMANDS
          
            // Commands are parameter-less actions that can be performed on an
            // editor, mostly used for keybindings.
            var commands = CodeMirror.commands = {
              selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);},
              singleSelection: function(cm) {
                cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll);
              },
              killLine: function(cm) {
                deleteNearSelection(cm, function(range) {
                  if (range.empty()) {
                    var len = getLine(cm.doc, range.head.line).text.length;
                    if (range.head.ch == len && range.head.line < cm.lastLine())
                      return {from: range.head, to: Pos(range.head.line + 1, 0)};
                    else
                      return {from: range.head, to: Pos(range.head.line, len)};
                  } else {
                    return {from: range.from(), to: range.to()};
                  }
                });
              },
              deleteLine: function(cm) {
                deleteNearSelection(cm, function(range) {
                  return {from: Pos(range.from().line, 0),
                          to: clipPos(cm.doc, Pos(range.to().line + 1, 0))};
                });
              },
              delLineLeft: function(cm) {
                deleteNearSelection(cm, function(range) {
                  return {from: Pos(range.from().line, 0), to: range.from()};
                });
              },
              delWrappedLineLeft: function(cm) {
                deleteNearSelection(cm, function(range) {
                  var top = cm.charCoords(range.head, "div").top + 5;
                  var leftPos = cm.coordsChar({left: 0, top: top}, "div");
                  return {from: leftPos, to: range.from()};
                });
              },
              delWrappedLineRight: function(cm) {
                deleteNearSelection(cm, function(range) {
                  var top = cm.charCoords(range.head, "div").top + 5;
                  var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
                  return {from: range.from(), to: rightPos };
                });
              },
              undo: function(cm) {cm.undo();},
              redo: function(cm) {cm.redo();},
              undoSelection: function(cm) {cm.undoSelection();},
              redoSelection: function(cm) {cm.redoSelection();},
              goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
              goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
              goLineStart: function(cm) {
                cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); },
                                      {origin: "+move", bias: 1});
              },
              goLineStartSmart: function(cm) {
                cm.extendSelectionsBy(function(range) {
                  return lineStartSmart(cm, range.head);
                }, {origin: "+move", bias: 1});
              },
              goLineEnd: function(cm) {
                cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); },
                                      {origin: "+move", bias: -1});
              },
              goLineRight: function(cm) {
                cm.extendSelectionsBy(function(range) {
                  var top = cm.charCoords(range.head, "div").top + 5;
                  return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
                }, sel_move);
              },
              goLineLeft: function(cm) {
                cm.extendSelectionsBy(function(range) {
                  var top = cm.charCoords(range.head, "div").top + 5;
                  return cm.coordsChar({left: 0, top: top}, "div");
                }, sel_move);
              },
              goLineLeftSmart: function(cm) {
                cm.extendSelectionsBy(function(range) {
                  var top = cm.charCoords(range.head, "div").top + 5;
                  var pos = cm.coordsChar({left: 0, top: top}, "div");
                  if (pos.ch < cm.getLine(pos.line).search(/\S/)) return lineStartSmart(cm, range.head);
                  return pos;
                }, sel_move);
              },
              goLineUp: function(cm) {cm.moveV(-1, "line");},
              goLineDown: function(cm) {cm.moveV(1, "line");},
              goPageUp: function(cm) {cm.moveV(-1, "page");},
              goPageDown: function(cm) {cm.moveV(1, "page");},
              goCharLeft: function(cm) {cm.moveH(-1, "char");},
              goCharRight: function(cm) {cm.moveH(1, "char");},
              goColumnLeft: function(cm) {cm.moveH(-1, "column");},
              goColumnRight: function(cm) {cm.moveH(1, "column");},
              goWordLeft: function(cm) {cm.moveH(-1, "word");},
              goGroupRight: function(cm) {cm.moveH(1, "group");},
              goGroupLeft: function(cm) {cm.moveH(-1, "group");},
              goWordRight: function(cm) {cm.moveH(1, "word");},
              delCharBefore: function(cm) {cm.deleteH(-1, "char");},
              delCharAfter: function(cm) {cm.deleteH(1, "char");},
              delWordBefore: function(cm) {cm.deleteH(-1, "word");},
              delWordAfter: function(cm) {cm.deleteH(1, "word");},
              delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
              delGroupAfter: function(cm) {cm.deleteH(1, "group");},
              indentAuto: function(cm) {cm.indentSelection("smart");},
              indentMore: function(cm) {cm.indentSelection("add");},
              indentLess: function(cm) {cm.indentSelection("subtract");},
              insertTab: function(cm) {cm.replaceSelection("\t");},
              insertSoftTab: function(cm) {
                var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;
                for (var i = 0; i < ranges.length; i++) {
                  var pos = ranges[i].from();
                  var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);
                  spaces.push(new Array(tabSize - col % tabSize + 1).join(" "));
                }
                cm.replaceSelections(spaces);
              },
              defaultTab: function(cm) {
                if (cm.somethingSelected()) cm.indentSelection("add");
                else cm.execCommand("insertTab");
              },
              transposeChars: function(cm) {
                runInOp(cm, function() {
                  var ranges = cm.listSelections(), newSel = [];
                  for (var i = 0; i < ranges.length; i++) {
                    var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
                    if (line) {
                      if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1);
                      if (cur.ch > 0) {
                        cur = new Pos(cur.line, cur.ch + 1);
                        cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
                                        Pos(cur.line, cur.ch - 2), cur, "+transpose");
                      } else if (cur.line > cm.doc.first) {
                        var prev = getLine(cm.doc, cur.line - 1).text;
                        if (prev)
                          cm.replaceRange(line.charAt(0) + "\n" + prev.charAt(prev.length - 1),
                                          Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose");
                      }
                    }
                    newSel.push(new Range(cur, cur));
                  }
                  cm.setSelections(newSel);
                });
              },
              newlineAndIndent: function(cm) {
                runInOp(cm, function() {
                  var len = cm.listSelections().length;
                  for (var i = 0; i < len; i++) {
                    var range = cm.listSelections()[i];
                    cm.replaceRange("\n", range.anchor, range.head, "+input");
                    cm.indentLine(range.from().line + 1, null, true);
                    ensureCursorVisible(cm);
                  }
                });
              },
              toggleOverwrite: function(cm) {cm.toggleOverwrite();}
            };
          
          
            // STANDARD KEYMAPS
          
            var keyMap = CodeMirror.keyMap = {};
          
            keyMap.basic = {
              "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
              "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
              "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
              "Tab": "defaultTab", "Shift-Tab": "indentAuto",
              "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
              "Esc": "singleSelection"
            };
            // Note that the save and find-related commands aren't defined by
            // default. User code or addons can define them. Unknown commands
            // are simply ignored.
            keyMap.pcDefault = {
              "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
              "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",
              "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
              "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
              "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
              "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
              "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
              fallthrough: "basic"
            };
            // Very basic readline/emacs-style bindings, which are standard on Mac.
            keyMap.emacsy = {
              "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
              "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
              "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
              "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
            };
            keyMap.macDefault = {
              "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
              "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
              "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
              "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
              "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
              "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
              "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
              fallthrough: ["basic", "emacsy"]
            };
            keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
          
            // KEYMAP DISPATCH
          
            function normalizeKeyName(name) {
              var parts = name.split(/-(?!$)/), name = parts[parts.length - 1];
              var alt, ctrl, shift, cmd;
              for (var i = 0; i < parts.length - 1; i++) {
                var mod = parts[i];
                if (/^(cmd|meta|m)$/i.test(mod)) cmd = true;
                else if (/^a(lt)?$/i.test(mod)) alt = true;
                else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true;
                else if (/^s(hift)$/i.test(mod)) shift = true;
                else throw new Error("Unrecognized modifier name: " + mod);
              }
              if (alt) name = "Alt-" + name;
              if (ctrl) name = "Ctrl-" + name;
              if (cmd) name = "Cmd-" + name;
              if (shift) name = "Shift-" + name;
              return name;
            }
          
            // This is a kludge to keep keymaps mostly working as raw objects
            // (backwards compatibility) while at the same time support features
            // like normalization and multi-stroke key bindings. It compiles a
            // new normalized keymap, and then updates the old object to reflect
            // this.
            CodeMirror.normalizeKeyMap = function(keymap) {
              var copy = {};
              for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) {
                var value = keymap[keyname];
                if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue;
                if (value == "...") { delete keymap[keyname]; continue; }
          
                var keys = map(keyname.split(" "), normalizeKeyName);
                for (var i = 0; i < keys.length; i++) {
                  var val, name;
                  if (i == keys.length - 1) {
                    name = keys.join(" ");
                    val = value;
                  } else {
                    name = keys.slice(0, i + 1).join(" ");
                    val = "...";
                  }
                  var prev = copy[name];
                  if (!prev) copy[name] = val;
                  else if (prev != val) throw new Error("Inconsistent bindings for " + name);
                }
                delete keymap[keyname];
              }
              for (var prop in copy) keymap[prop] = copy[prop];
              return keymap;
            };
          
            var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) {
              map = getKeyMap(map);
              var found = map.call ? map.call(key, context) : map[key];
              if (found === false) return "nothing";
              if (found === "...") return "multi";
              if (found != null && handle(found)) return "handled";
          
              if (map.fallthrough) {
                if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
                  return lookupKey(key, map.fallthrough, handle, context);
                for (var i = 0; i < map.fallthrough.length; i++) {
                  var result = lookupKey(key, map.fallthrough[i], handle, context);
                  if (result) return result;
                }
              }
            };
          
            // Modifier key presses don't count as 'real' key presses for the
            // purpose of keymap fallthrough.
            var isModifierKey = CodeMirror.isModifierKey = function(value) {
              var name = typeof value == "string" ? value : keyNames[value.keyCode];
              return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
            };
          
            // Look up the name of a key as indicated by an event object.
            var keyName = CodeMirror.keyName = function(event, noShift) {
              if (presto && event.keyCode == 34 && event["char"]) return false;
              var base = keyNames[event.keyCode], name = base;
              if (name == null || event.altGraphKey) return false;
              if (event.altKey && base != "Alt") name = "Alt-" + name;
              if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name;
              if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name;
              if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name;
              return name;
            };
          
            function getKeyMap(val) {
              return typeof val == "string" ? keyMap[val] : val;
            }
          
            // FROMTEXTAREA
          
            CodeMirror.fromTextArea = function(textarea, options) {
              options = options ? copyObj(options) : {};
              options.value = textarea.value;
              if (!options.tabindex && textarea.tabIndex)
                options.tabindex = textarea.tabIndex;
              if (!options.placeholder && textarea.placeholder)
                options.placeholder = textarea.placeholder;
              // Set autofocus to true if this textarea is focused, or if it has
              // autofocus and no other element is focused.
              if (options.autofocus == null) {
                var hasFocus = activeElt();
                options.autofocus = hasFocus == textarea ||
                  textarea.getAttribute("autofocus") != null && hasFocus == document.body;
              }
          
              function save() {textarea.value = cm.getValue();}
              if (textarea.form) {
                on(textarea.form, "submit", save);
                // Deplorable hack to make the submit method do the right thing.
                if (!options.leaveSubmitMethodAlone) {
                  var form = textarea.form, realSubmit = form.submit;
                  try {
                    var wrappedSubmit = form.submit = function() {
                      save();
                      form.submit = realSubmit;
                      form.submit();
                      form.submit = wrappedSubmit;
                    };
                  } catch(e) {}
                }
              }
          
              options.finishInit = function(cm) {
                cm.save = save;
                cm.getTextArea = function() { return textarea; };
                cm.toTextArea = function() {
                  cm.toTextArea = isNaN; // Prevent this from being ran twice
                  save();
                  textarea.parentNode.removeChild(cm.getWrapperElement());
                  textarea.style.display = "";
                  if (textarea.form) {
                    off(textarea.form, "submit", save);
                    if (typeof textarea.form.submit == "function")
                      textarea.form.submit = realSubmit;
                  }
                };
              };
          
              textarea.style.display = "none";
              var cm = CodeMirror(function(node) {
                textarea.parentNode.insertBefore(node, textarea.nextSibling);
              }, options);
              return cm;
            };
          
            // STRING STREAM
          
            // Fed to the mode parsers, provides helper functions to make
            // parsers more succinct.
          
            var StringStream = CodeMirror.StringStream = function(string, tabSize) {
              this.pos = this.start = 0;
              this.string = string;
              this.tabSize = tabSize || 8;
              this.lastColumnPos = this.lastColumnValue = 0;
              this.lineStart = 0;
            };
          
            StringStream.prototype = {
              eol: function() {return this.pos >= this.string.length;},
              sol: function() {return this.pos == this.lineStart;},
              peek: function() {return this.string.charAt(this.pos) || undefined;},
              next: function() {
                if (this.pos < this.string.length)
                  return this.string.charAt(this.pos++);
              },
              eat: function(match) {
                var ch = this.string.charAt(this.pos);
                if (typeof match == "string") var ok = ch == match;
                else var ok = ch && (match.test ? match.test(ch) : match(ch));
                if (ok) {++this.pos; return ch;}
              },
              eatWhile: function(match) {
                var start = this.pos;
                while (this.eat(match)){}
                return this.pos > start;
              },
              eatSpace: function() {
                var start = this.pos;
                while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
                return this.pos > start;
              },
              skipToEnd: function() {this.pos = this.string.length;},
              skipTo: function(ch) {
                var found = this.string.indexOf(ch, this.pos);
                if (found > -1) {this.pos = found; return true;}
              },
              backUp: function(n) {this.pos -= n;},
              column: function() {
                if (this.lastColumnPos < this.start) {
                  this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
                  this.lastColumnPos = this.start;
                }
                return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
              },
              indentation: function() {
                return countColumn(this.string, null, this.tabSize) -
                  (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
              },
              match: function(pattern, consume, caseInsensitive) {
                if (typeof pattern == "string") {
                  var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
                  var substr = this.string.substr(this.pos, pattern.length);
                  if (cased(substr) == cased(pattern)) {
                    if (consume !== false) this.pos += pattern.length;
                    return true;
                  }
                } else {
                  var match = this.string.slice(this.pos).match(pattern);
                  if (match && match.index > 0) return null;
                  if (match && consume !== false) this.pos += match[0].length;
                  return match;
                }
              },
              current: function(){return this.string.slice(this.start, this.pos);},
              hideFirstChars: function(n, inner) {
                this.lineStart += n;
                try { return inner(); }
                finally { this.lineStart -= n; }
              }
            };
          
            // TEXTMARKERS
          
            // Created with markText and setBookmark methods. A TextMarker is a
            // handle that can be used to clear or find a marked position in the
            // document. Line objects hold arrays (markedSpans) containing
            // {from, to, marker} object pointing to such marker objects, and
            // indicating that such a marker is present on that line. Multiple
            // lines may point to the same marker when it spans across lines.
            // The spans will have null for their from/to properties when the
            // marker continues beyond the start/end of the line. Markers have
            // links back to the lines they currently touch.
          
            var nextMarkerId = 0;
          
            var TextMarker = CodeMirror.TextMarker = function(doc, type) {
              this.lines = [];
              this.type = type;
              this.doc = doc;
              this.id = ++nextMarkerId;
            };
            eventMixin(TextMarker);
          
            // Clear the marker.
            TextMarker.prototype.clear = function() {
              if (this.explicitlyCleared) return;
              var cm = this.doc.cm, withOp = cm && !cm.curOp;
              if (withOp) startOperation(cm);
              if (hasHandler(this, "clear")) {
                var found = this.find();
                if (found) signalLater(this, "clear", found.from, found.to);
              }
              var min = null, max = null;
              for (var i = 0; i < this.lines.length; ++i) {
                var line = this.lines[i];
                var span = getMarkedSpanFor(line.markedSpans, this);
                if (cm && !this.collapsed) regLineChange(cm, lineNo(line), "text");
                else if (cm) {
                  if (span.to != null) max = lineNo(line);
                  if (span.from != null) min = lineNo(line);
                }
                line.markedSpans = removeMarkedSpan(line.markedSpans, span);
                if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm)
                  updateLineHeight(line, textHeight(cm.display));
              }
              if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
                var visual = visualLine(this.lines[i]), len = lineLength(visual);
                if (len > cm.display.maxLineLength) {
                  cm.display.maxLine = visual;
                  cm.display.maxLineLength = len;
                  cm.display.maxLineChanged = true;
                }
              }
          
              if (min != null && cm && this.collapsed) regChange(cm, min, max + 1);
              this.lines.length = 0;
              this.explicitlyCleared = true;
              if (this.atomic && this.doc.cantEdit) {
                this.doc.cantEdit = false;
                if (cm) reCheckSelection(cm.doc);
              }
              if (cm) signalLater(cm, "markerCleared", cm, this);
              if (withOp) endOperation(cm);
              if (this.parent) this.parent.clear();
            };
          
            // Find the position of the marker in the document. Returns a {from,
            // to} object by default. Side can be passed to get a specific side
            // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
            // Pos objects returned contain a line object, rather than a line
            // number (used to prevent looking up the same line twice).
            TextMarker.prototype.find = function(side, lineObj) {
              if (side == null && this.type == "bookmark") side = 1;
              var from, to;
              for (var i = 0; i < this.lines.length; ++i) {
                var line = this.lines[i];
                var span = getMarkedSpanFor(line.markedSpans, this);
                if (span.from != null) {
                  from = Pos(lineObj ? line : lineNo(line), span.from);
                  if (side == -1) return from;
                }
                if (span.to != null) {
                  to = Pos(lineObj ? line : lineNo(line), span.to);
                  if (side == 1) return to;
                }
              }
              return from && {from: from, to: to};
            };
          
            // Signals that the marker's widget changed, and surrounding layout
            // should be recomputed.
            TextMarker.prototype.changed = function() {
              var pos = this.find(-1, true), widget = this, cm = this.doc.cm;
              if (!pos || !cm) return;
              runInOp(cm, function() {
                var line = pos.line, lineN = lineNo(pos.line);
                var view = findViewForLine(cm, lineN);
                if (view) {
                  clearLineMeasurementCacheFor(view);
                  cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;
                }
                cm.curOp.updateMaxLine = true;
                if (!lineIsHidden(widget.doc, line) && widget.height != null) {
                  var oldHeight = widget.height;
                  widget.height = null;
                  var dHeight = widgetHeight(widget) - oldHeight;
                  if (dHeight)
                    updateLineHeight(line, line.height + dHeight);
                }
              });
            };
          
            TextMarker.prototype.attachLine = function(line) {
              if (!this.lines.length && this.doc.cm) {
                var op = this.doc.cm.curOp;
                if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
                  (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
              }
              this.lines.push(line);
            };
            TextMarker.prototype.detachLine = function(line) {
              this.lines.splice(indexOf(this.lines, line), 1);
              if (!this.lines.length && this.doc.cm) {
                var op = this.doc.cm.curOp;
                (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
              }
            };
          
            // Collapsed markers have unique ids, in order to be able to order
            // them, which is needed for uniquely determining an outer marker
            // when they overlap (they may nest, but not partially overlap).
            var nextMarkerId = 0;
          
            // Create a marker, wire it up to the right lines, and
            function markText(doc, from, to, options, type) {
              // Shared markers (across linked documents) are handled separately
              // (markTextShared will call out to this again, once per
              // document).
              if (options && options.shared) return markTextShared(doc, from, to, options, type);
              // Ensure we are in an operation.
              if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
          
              var marker = new TextMarker(doc, type), diff = cmp(from, to);
              if (options) copyObj(options, marker, false);
              // Don't connect empty markers unless clearWhenEmpty is false
              if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
                return marker;
              if (marker.replacedWith) {
                // Showing up as a widget implies collapsed (widget replaces text)
                marker.collapsed = true;
                marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget");
                if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true");
                if (options.insertLeft) marker.widgetNode.insertLeft = true;
              }
              if (marker.collapsed) {
                if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
                    from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
                  throw new Error("Inserting collapsed marker partially overlapping an existing one");
                sawCollapsedSpans = true;
              }
          
              if (marker.addToHistory)
                addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN);
          
              var curLine = from.line, cm = doc.cm, updateMaxLine;
              doc.iter(curLine, to.line + 1, function(line) {
                if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
                  updateMaxLine = true;
                if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0);
                addMarkedSpan(line, new MarkedSpan(marker,
                                                   curLine == from.line ? from.ch : null,
                                                   curLine == to.line ? to.ch : null));
                ++curLine;
              });
              // lineIsHidden depends on the presence of the spans, so needs a second pass
              if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
                if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
              });
          
              if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
          
              if (marker.readOnly) {
                sawReadOnlySpans = true;
                if (doc.history.done.length || doc.history.undone.length)
                  doc.clearHistory();
              }
              if (marker.collapsed) {
                marker.id = ++nextMarkerId;
                marker.atomic = true;
              }
              if (cm) {
                // Sync editor state
                if (updateMaxLine) cm.curOp.updateMaxLine = true;
                if (marker.collapsed)
                  regChange(cm, from.line, to.line + 1);
                else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)
                  for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text");
                if (marker.atomic) reCheckSelection(cm.doc);
                signalLater(cm, "markerAdded", cm, marker);
              }
              return marker;
            }
          
            // SHARED TEXTMARKERS
          
            // A shared marker spans multiple linked documents. It is
            // implemented as a meta-marker-object controlling multiple normal
            // markers.
            var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) {
              this.markers = markers;
              this.primary = primary;
              for (var i = 0; i < markers.length; ++i)
                markers[i].parent = this;
            };
            eventMixin(SharedTextMarker);
          
            SharedTextMarker.prototype.clear = function() {
              if (this.explicitlyCleared) return;
              this.explicitlyCleared = true;
              for (var i = 0; i < this.markers.length; ++i)
                this.markers[i].clear();
              signalLater(this, "clear");
            };
            SharedTextMarker.prototype.find = function(side, lineObj) {
              return this.primary.find(side, lineObj);
            };
          
            function markTextShared(doc, from, to, options, type) {
              options = copyObj(options);
              options.shared = false;
              var markers = [markText(doc, from, to, options, type)], primary = markers[0];
              var widget = options.widgetNode;
              linkedDocs(doc, function(doc) {
                if (widget) options.widgetNode = widget.cloneNode(true);
                markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
                for (var i = 0; i < doc.linked.length; ++i)
                  if (doc.linked[i].isParent) return;
                primary = lst(markers);
              });
              return new SharedTextMarker(markers, primary);
            }
          
            function findSharedMarkers(doc) {
              return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())),
                                   function(m) { return m.parent; });
            }
          
            function copySharedMarkers(doc, markers) {
              for (var i = 0; i < markers.length; i++) {
                var marker = markers[i], pos = marker.find();
                var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);
                if (cmp(mFrom, mTo)) {
                  var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);
                  marker.markers.push(subMark);
                  subMark.parent = marker;
                }
              }
            }
          
            function detachSharedMarkers(markers) {
              for (var i = 0; i < markers.length; i++) {
                var marker = markers[i], linked = [marker.primary.doc];;
                linkedDocs(marker.primary.doc, function(d) { linked.push(d); });
                for (var j = 0; j < marker.markers.length; j++) {
                  var subMarker = marker.markers[j];
                  if (indexOf(linked, subMarker.doc) == -1) {
                    subMarker.parent = null;
                    marker.markers.splice(j--, 1);
                  }
                }
              }
            }
          
            // TEXTMARKER SPANS
          
            function MarkedSpan(marker, from, to) {
              this.marker = marker;
              this.from = from; this.to = to;
            }
          
            // Search an array of spans for a span matching the given marker.
            function getMarkedSpanFor(spans, marker) {
              if (spans) for (var i = 0; i < spans.length; ++i) {
                var span = spans[i];
                if (span.marker == marker) return span;
              }
            }
            // Remove a span from an array, returning undefined if no spans are
            // left (we don't store arrays for lines without spans).
            function removeMarkedSpan(spans, span) {
              for (var r, i = 0; i < spans.length; ++i)
                if (spans[i] != span) (r || (r = [])).push(spans[i]);
              return r;
            }
            // Add a span to a line.
            function addMarkedSpan(line, span) {
              line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
              span.marker.attachLine(line);
            }
          
            // Used for the algorithm that adjusts markers for a change in the
            // document. These functions cut an array of spans at a given
            // character position, returning an array of remaining chunks (or
            // undefined if nothing remains).
            function markedSpansBefore(old, startCh, isInsert) {
              if (old) for (var i = 0, nw; i < old.length; ++i) {
                var span = old[i], marker = span.marker;
                var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
                if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
                  var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
                  (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));
                }
              }
              return nw;
            }
            function markedSpansAfter(old, endCh, isInsert) {
              if (old) for (var i = 0, nw; i < old.length; ++i) {
                var span = old[i], marker = span.marker;
                var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
                if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
                  var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
                  (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
                                                        span.to == null ? null : span.to - endCh));
                }
              }
              return nw;
            }
          
            // Given a change object, compute the new set of marker spans that
            // cover the line in which the change took place. Removes spans
            // entirely within the change, reconnects spans belonging to the
            // same marker that appear on both sides of the change, and cuts off
            // spans partially within the change. Returns an array of span
            // arrays with one element for each line in (after) the change.
            function stretchSpansOverChange(doc, change) {
              if (change.full) return null;
              var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
              var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
              if (!oldFirst && !oldLast) return null;
          
              var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;
              // Get the spans that 'stick out' on both sides
              var first = markedSpansBefore(oldFirst, startCh, isInsert);
              var last = markedSpansAfter(oldLast, endCh, isInsert);
          
              // Next, merge those two ends
              var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
              if (first) {
                // Fix up .to properties of first
                for (var i = 0; i < first.length; ++i) {
                  var span = first[i];
                  if (span.to == null) {
                    var found = getMarkedSpanFor(last, span.marker);
                    if (!found) span.to = startCh;
                    else if (sameLine) span.to = found.to == null ? null : found.to + offset;
                  }
                }
              }
              if (last) {
                // Fix up .from in last (or move them into first in case of sameLine)
                for (var i = 0; i < last.length; ++i) {
                  var span = last[i];
                  if (span.to != null) span.to += offset;
                  if (span.from == null) {
                    var found = getMarkedSpanFor(first, span.marker);
                    if (!found) {
                      span.from = offset;
                      if (sameLine) (first || (first = [])).push(span);
                    }
                  } else {
                    span.from += offset;
                    if (sameLine) (first || (first = [])).push(span);
                  }
                }
              }
              // Make sure we didn't create any zero-length spans
              if (first) first = clearEmptySpans(first);
              if (last && last != first) last = clearEmptySpans(last);
          
              var newMarkers = [first];
              if (!sameLine) {
                // Fill gap with whole-line-spans
                var gap = change.text.length - 2, gapMarkers;
                if (gap > 0 && first)
                  for (var i = 0; i < first.length; ++i)
                    if (first[i].to == null)
                      (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null));
                for (var i = 0; i < gap; ++i)
                  newMarkers.push(gapMarkers);
                newMarkers.push(last);
              }
              return newMarkers;
            }
          
            // Remove spans that are empty and don't have a clearWhenEmpty
            // option of false.
            function clearEmptySpans(spans) {
              for (var i = 0; i < spans.length; ++i) {
                var span = spans[i];
                if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
                  spans.splice(i--, 1);
              }
              if (!spans.length) return null;
              return spans;
            }
          
            // Used for un/re-doing changes from the history. Combines the
            // result of computing the existing spans with the set of spans that
            // existed in the history (so that deleting around a span and then
            // undoing brings back the span).
            function mergeOldSpans(doc, change) {
              var old = getOldSpans(doc, change);
              var stretched = stretchSpansOverChange(doc, change);
              if (!old) return stretched;
              if (!stretched) return old;
          
              for (var i = 0; i < old.length; ++i) {
                var oldCur = old[i], stretchCur = stretched[i];
                if (oldCur && stretchCur) {
                  spans: for (var j = 0; j < stretchCur.length; ++j) {
                    var span = stretchCur[j];
                    for (var k = 0; k < oldCur.length; ++k)
                      if (oldCur[k].marker == span.marker) continue spans;
                    oldCur.push(span);
                  }
                } else if (stretchCur) {
                  old[i] = stretchCur;
                }
              }
              return old;
            }
          
            // Used to 'clip' out readOnly ranges when making a change.
            function removeReadOnlyRanges(doc, from, to) {
              var markers = null;
              doc.iter(from.line, to.line + 1, function(line) {
                if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
                  var mark = line.markedSpans[i].marker;
                  if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
                    (markers || (markers = [])).push(mark);
                }
              });
              if (!markers) return null;
              var parts = [{from: from, to: to}];
              for (var i = 0; i < markers.length; ++i) {
                var mk = markers[i], m = mk.find(0);
                for (var j = 0; j < parts.length; ++j) {
                  var p = parts[j];
                  if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue;
                  var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);
                  if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
                    newParts.push({from: p.from, to: m.from});
                  if (dto > 0 || !mk.inclusiveRight && !dto)
                    newParts.push({from: m.to, to: p.to});
                  parts.splice.apply(parts, newParts);
                  j += newParts.length - 1;
                }
              }
              return parts;
            }
          
            // Connect or disconnect spans from a line.
            function detachMarkedSpans(line) {
              var spans = line.markedSpans;
              if (!spans) return;
              for (var i = 0; i < spans.length; ++i)
                spans[i].marker.detachLine(line);
              line.markedSpans = null;
            }
            function attachMarkedSpans(line, spans) {
              if (!spans) return;
              for (var i = 0; i < spans.length; ++i)
                spans[i].marker.attachLine(line);
              line.markedSpans = spans;
            }
          
            // Helpers used when computing which overlapping collapsed span
            // counts as the larger one.
            function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; }
            function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; }
          
            // Returns a number indicating which of two overlapping collapsed
            // spans is larger (and thus includes the other). Falls back to
            // comparing ids when the spans cover exactly the same range.
            function compareCollapsedMarkers(a, b) {
              var lenDiff = a.lines.length - b.lines.length;
              if (lenDiff != 0) return lenDiff;
              var aPos = a.find(), bPos = b.find();
              var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);
              if (fromCmp) return -fromCmp;
              var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);
              if (toCmp) return toCmp;
              return b.id - a.id;
            }
          
            // Find out whether a line ends or starts in a collapsed span. If
            // so, return the marker for that span.
            function collapsedSpanAtSide(line, start) {
              var sps = sawCollapsedSpans && line.markedSpans, found;
              if (sps) for (var sp, i = 0; i < sps.length; ++i) {
                sp = sps[i];
                if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
                    (!found || compareCollapsedMarkers(found, sp.marker) < 0))
                  found = sp.marker;
              }
              return found;
            }
            function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); }
            function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); }
          
            // Test whether there exists a collapsed span that partially
            // overlaps (covers the start or end, but not both) of a new span.
            // Such overlap is not allowed.
            function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
              var line = getLine(doc, lineNo);
              var sps = sawCollapsedSpans && line.markedSpans;
              if (sps) for (var i = 0; i < sps.length; ++i) {
                var sp = sps[i];
                if (!sp.marker.collapsed) continue;
                var found = sp.marker.find(0);
                var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);
                var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);
                if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue;
                if (fromCmp <= 0 && (cmp(found.to, from) > 0 || (sp.marker.inclusiveRight && marker.inclusiveLeft)) ||
                    fromCmp >= 0 && (cmp(found.from, to) < 0 || (sp.marker.inclusiveLeft && marker.inclusiveRight)))
                  return true;
              }
            }
          
            // A visual line is a line as drawn on the screen. Folding, for
            // example, can cause multiple logical lines to appear on the same
            // visual line. This finds the start of the visual line that the
            // given line is part of (usually that is the line itself).
            function visualLine(line) {
              var merged;
              while (merged = collapsedSpanAtStart(line))
                line = merged.find(-1, true).line;
              return line;
            }
          
            // Returns an array of logical lines that continue the visual line
            // started by the argument, or undefined if there are no such lines.
            function visualLineContinued(line) {
              var merged, lines;
              while (merged = collapsedSpanAtEnd(line)) {
                line = merged.find(1, true).line;
                (lines || (lines = [])).push(line);
              }
              return lines;
            }
          
            // Get the line number of the start of the visual line that the
            // given line number is part of.
            function visualLineNo(doc, lineN) {
              var line = getLine(doc, lineN), vis = visualLine(line);
              if (line == vis) return lineN;
              return lineNo(vis);
            }
            // Get the line number of the start of the next visual line after
            // the given line.
            function visualLineEndNo(doc, lineN) {
              if (lineN > doc.lastLine()) return lineN;
              var line = getLine(doc, lineN), merged;
              if (!lineIsHidden(doc, line)) return lineN;
              while (merged = collapsedSpanAtEnd(line))
                line = merged.find(1, true).line;
              return lineNo(line) + 1;
            }
          
            // Compute whether a line is hidden. Lines count as hidden when they
            // are part of a visual line that starts with another line, or when
            // they are entirely covered by collapsed, non-widget span.
            function lineIsHidden(doc, line) {
              var sps = sawCollapsedSpans && line.markedSpans;
              if (sps) for (var sp, i = 0; i < sps.length; ++i) {
                sp = sps[i];
                if (!sp.marker.collapsed) continue;
                if (sp.from == null) return true;
                if (sp.marker.widgetNode) continue;
                if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
                  return true;
              }
            }
            function lineIsHiddenInner(doc, line, span) {
              if (span.to == null) {
                var end = span.marker.find(1, true);
                return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker));
              }
              if (span.marker.inclusiveRight && span.to == line.text.length)
                return true;
              for (var sp, i = 0; i < line.markedSpans.length; ++i) {
                sp = line.markedSpans[i];
                if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
                    (sp.to == null || sp.to != span.from) &&
                    (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
                    lineIsHiddenInner(doc, line, sp)) return true;
              }
            }
          
            // LINE WIDGETS
          
            // Line widgets are block elements displayed above or below a line.
          
            var LineWidget = CodeMirror.LineWidget = function(doc, node, options) {
              if (options) for (var opt in options) if (options.hasOwnProperty(opt))
                this[opt] = options[opt];
              this.doc = doc;
              this.node = node;
            };
            eventMixin(LineWidget);
          
            function adjustScrollWhenAboveVisible(cm, line, diff) {
              if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
                addToScrollPos(cm, null, diff);
            }
          
            LineWidget.prototype.clear = function() {
              var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
              if (no == null || !ws) return;
              for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
              if (!ws.length) line.widgets = null;
              var height = widgetHeight(this);
              updateLineHeight(line, Math.max(0, line.height - height));
              if (cm) runInOp(cm, function() {
                adjustScrollWhenAboveVisible(cm, line, -height);
                regLineChange(cm, no, "widget");
              });
            };
            LineWidget.prototype.changed = function() {
              var oldH = this.height, cm = this.doc.cm, line = this.line;
              this.height = null;
              var diff = widgetHeight(this) - oldH;
              if (!diff) return;
              updateLineHeight(line, line.height + diff);
              if (cm) runInOp(cm, function() {
                cm.curOp.forceUpdate = true;
                adjustScrollWhenAboveVisible(cm, line, diff);
              });
            };
          
            function widgetHeight(widget) {
              if (widget.height != null) return widget.height;
              var cm = widget.doc.cm;
              if (!cm) return 0;
              if (!contains(document.body, widget.node)) {
                var parentStyle = "position: relative;";
                if (widget.coverGutter)
                  parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;";
                if (widget.noHScroll)
                  parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;";
                removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle));
              }
              return widget.height = widget.node.offsetHeight;
            }
          
            function addLineWidget(doc, handle, node, options) {
              var widget = new LineWidget(doc, node, options);
              var cm = doc.cm;
              if (cm && widget.noHScroll) cm.display.alignWidgets = true;
              changeLine(doc, handle, "widget", function(line) {
                var widgets = line.widgets || (line.widgets = []);
                if (widget.insertAt == null) widgets.push(widget);
                else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
                widget.line = line;
                if (cm && !lineIsHidden(doc, line)) {
                  var aboveVisible = heightAtLine(line) < doc.scrollTop;
                  updateLineHeight(line, line.height + widgetHeight(widget));
                  if (aboveVisible) addToScrollPos(cm, null, widget.height);
                  cm.curOp.forceUpdate = true;
                }
                return true;
              });
              return widget;
            }
          
            // LINE DATA STRUCTURE
          
            // Line objects. These hold state related to a line, including
            // highlighting info (the styles array).
            var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
              this.text = text;
              attachMarkedSpans(this, markedSpans);
              this.height = estimateHeight ? estimateHeight(this) : 1;
            };
            eventMixin(Line);
            Line.prototype.lineNo = function() { return lineNo(this); };
          
            // Change the content (text, markers) of a line. Automatically
            // invalidates cached information and tries to re-estimate the
            // line's height.
            function updateLine(line, text, markedSpans, estimateHeight) {
              line.text = text;
              if (line.stateAfter) line.stateAfter = null;
              if (line.styles) line.styles = null;
              if (line.order != null) line.order = null;
              detachMarkedSpans(line);
              attachMarkedSpans(line, markedSpans);
              var estHeight = estimateHeight ? estimateHeight(line) : 1;
              if (estHeight != line.height) updateLineHeight(line, estHeight);
            }
          
            // Detach a line from the document tree and its markers.
            function cleanUpLine(line) {
              line.parent = null;
              detachMarkedSpans(line);
            }
          
            function extractLineClasses(type, output) {
              if (type) for (;;) {
                var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/);
                if (!lineClass) break;
                type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);
                var prop = lineClass[1] ? "bgClass" : "textClass";
                if (output[prop] == null)
                  output[prop] = lineClass[2];
                else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop]))
                  output[prop] += " " + lineClass[2];
              }
              return type;
            }
          
            function callBlankLine(mode, state) {
              if (mode.blankLine) return mode.blankLine(state);
              if (!mode.innerMode) return;
              var inner = CodeMirror.innerMode(mode, state);
              if (inner.mode.blankLine) return inner.mode.blankLine(inner.state);
            }
          
            function readToken(mode, stream, state, inner) {
              for (var i = 0; i < 10; i++) {
                if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode;
                var style = mode.token(stream, state);
                if (stream.pos > stream.start) return style;
              }
              throw new Error("Mode " + mode.name + " failed to advance stream.");
            }
          
            // Utility for getTokenAt and getLineTokens
            function takeToken(cm, pos, precise, asArray) {
              function getObj(copy) {
                return {start: stream.start, end: stream.pos,
                        string: stream.current(),
                        type: style || null,
                        state: copy ? copyState(doc.mode, state) : state};
              }
          
              var doc = cm.doc, mode = doc.mode, style;
              pos = clipPos(doc, pos);
              var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise);
              var stream = new StringStream(line.text, cm.options.tabSize), tokens;
              if (asArray) tokens = [];
              while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
                stream.start = stream.pos;
                style = readToken(mode, stream, state);
                if (asArray) tokens.push(getObj(true));
              }
              return asArray ? tokens : getObj();
            }
          
            // Run the given mode's parser over a line, calling f for each token.
            function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {
              var flattenSpans = mode.flattenSpans;
              if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
              var curStart = 0, curStyle = null;
              var stream = new StringStream(text, cm.options.tabSize), style;
              var inner = cm.options.addModeClass && [null];
              if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses);
              while (!stream.eol()) {
                if (stream.pos > cm.options.maxHighlightLength) {
                  flattenSpans = false;
                  if (forceToEnd) processLine(cm, text, state, stream.pos);
                  stream.pos = text.length;
                  style = null;
                } else {
                  style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses);
                }
                if (inner) {
                  var mName = inner[0].name;
                  if (mName) style = "m-" + (style ? mName + " " + style : mName);
                }
                if (!flattenSpans || curStyle != style) {
                  while (curStart < stream.start) {
                    curStart = Math.min(stream.start, curStart + 50000);
                    f(curStart, curStyle);
                  }
                  curStyle = style;
                }
                stream.start = stream.pos;
              }
              while (curStart < stream.pos) {
                // Webkit seems to refuse to render text nodes longer than 57444 characters
                var pos = Math.min(stream.pos, curStart + 50000);
                f(pos, curStyle);
                curStart = pos;
              }
            }
          
            // Compute a style array (an array starting with a mode generation
            // -- for invalidation -- followed by pairs of end positions and
            // style strings), which is used to highlight the tokens on the
            // line.
            function highlightLine(cm, line, state, forceToEnd) {
              // A styles array always starts with a number identifying the
              // mode/overlays that it is based on (for easy invalidation).
              var st = [cm.state.modeGen], lineClasses = {};
              // Compute the base array of styles
              runMode(cm, line.text, cm.doc.mode, state, function(end, style) {
                st.push(end, style);
              }, lineClasses, forceToEnd);
          
              // Run overlays, adjust style array.
              for (var o = 0; o < cm.state.overlays.length; ++o) {
                var overlay = cm.state.overlays[o], i = 1, at = 0;
                runMode(cm, line.text, overlay.mode, true, function(end, style) {
                  var start = i;
                  // Ensure there's a token end at the current position, and that i points at it
                  while (at < end) {
                    var i_end = st[i];
                    if (i_end > end)
                      st.splice(i, 1, end, st[i+1], i_end);
                    i += 2;
                    at = Math.min(end, i_end);
                  }
                  if (!style) return;
                  if (overlay.opaque) {
                    st.splice(start, i - start, end, "cm-overlay " + style);
                    i = start + 2;
                  } else {
                    for (; start < i; start += 2) {
                      var cur = st[start+1];
                      st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style;
                    }
                  }
                }, lineClasses);
              }
          
              return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null};
            }
          
            function getLineStyles(cm, line, updateFrontier) {
              if (!line.styles || line.styles[0] != cm.state.modeGen) {
                var result = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
                line.styles = result.styles;
                if (result.classes) line.styleClasses = result.classes;
                else if (line.styleClasses) line.styleClasses = null;
                if (updateFrontier === cm.doc.frontier) cm.doc.frontier++;
              }
              return line.styles;
            }
          
            // Lightweight form of highlight -- proceed over this line and
            // update state, but don't save a style array. Used for lines that
            // aren't currently visible.
            function processLine(cm, text, state, startAt) {
              var mode = cm.doc.mode;
              var stream = new StringStream(text, cm.options.tabSize);
              stream.start = stream.pos = startAt || 0;
              if (text == "") callBlankLine(mode, state);
              while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
                readToken(mode, stream, state);
                stream.start = stream.pos;
              }
            }
          
            // Convert a style as returned by a mode (either null, or a string
            // containing one or more styles) to a CSS style. This is cached,
            // and also looks for line-wide styles.
            var styleToClassCache = {}, styleToClassCacheWithMode = {};
            function interpretTokenStyle(style, options) {
              if (!style || /^\s*$/.test(style)) return null;
              var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
              return cache[style] ||
                (cache[style] = style.replace(/\S+/g, "cm-$&"));
            }
          
            // Render the DOM representation of the text of a line. Also builds
            // up a 'line map', which points at the DOM nodes that represent
            // specific stretches of text, and is used by the measuring code.
            // The returned object contains the DOM node, this map, and
            // information about line-wide styles that were set by the mode.
            function buildLineContent(cm, lineView) {
              // The padding-right forces the element to have a 'border', which
              // is needed on Webkit to be able to get line-level bounding
              // rectangles for it (in measureChar).
              var content = elt("span", null, null, webkit ? "padding-right: .1px" : null);
              var builder = {pre: elt("pre", [content]), content: content,
                             col: 0, pos: 0, cm: cm,
                             splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")};
              lineView.measure = {};
          
              // Iterate over the logical lines that make up this visual line.
              for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
                var line = i ? lineView.rest[i - 1] : lineView.line, order;
                builder.pos = 0;
                builder.addToken = buildToken;
                // Optionally wire in some hacks into the token-rendering
                // algorithm, to deal with browser quirks.
                if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
                  builder.addToken = buildTokenBadBidi(builder.addToken, order);
                builder.map = [];
                var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);
                insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));
                if (line.styleClasses) {
                  if (line.styleClasses.bgClass)
                    builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "");
                  if (line.styleClasses.textClass)
                    builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "");
                }
          
                // Ensure at least a single node is present, for measuring.
                if (builder.map.length == 0)
                  builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure)));
          
                // Store the map and a cache object for the current logical line
                if (i == 0) {
                  lineView.measure.map = builder.map;
                  lineView.measure.cache = {};
                } else {
                  (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map);
                  (lineView.measure.caches || (lineView.measure.caches = [])).push({});
                }
              }
          
              // See issue #2901
              if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className))
                builder.content.className = "cm-tab-wrap-hack";
          
              signal(cm, "renderLine", cm, lineView.line, builder.pre);
              if (builder.pre.className)
                builder.textClass = joinClasses(builder.pre.className, builder.textClass || "");
          
              return builder;
            }
          
            function defaultSpecialCharPlaceholder(ch) {
              var token = elt("span", "\u2022", "cm-invalidchar");
              token.title = "\\u" + ch.charCodeAt(0).toString(16);
              token.setAttribute("aria-label", token.title);
              return token;
            }
          
            // Build up the DOM representation for a single token, and add it to
            // the line map. Takes care to render special characters separately.
            function buildToken(builder, text, style, startStyle, endStyle, title, css) {
              if (!text) return;
              var displayText = builder.splitSpaces ? text.replace(/ {3,}/g, splitSpaces) : text;
              var special = builder.cm.state.specialChars, mustWrap = false;
              if (!special.test(text)) {
                builder.col += text.length;
                var content = document.createTextNode(displayText);
                builder.map.push(builder.pos, builder.pos + text.length, content);
                if (ie && ie_version < 9) mustWrap = true;
                builder.pos += text.length;
              } else {
                var content = document.createDocumentFragment(), pos = 0;
                while (true) {
                  special.lastIndex = pos;
                  var m = special.exec(text);
                  var skipped = m ? m.index - pos : text.length - pos;
                  if (skipped) {
                    var txt = document.createTextNode(displayText.slice(pos, pos + skipped));
                    if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
                    else content.appendChild(txt);
                    builder.map.push(builder.pos, builder.pos + skipped, txt);
                    builder.col += skipped;
                    builder.pos += skipped;
                  }
                  if (!m) break;
                  pos += skipped + 1;
                  if (m[0] == "\t") {
                    var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
                    var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
                    txt.setAttribute("role", "presentation");
                    txt.setAttribute("cm-text", "\t");
                    builder.col += tabWidth;
                  } else {
                    var txt = builder.cm.options.specialCharPlaceholder(m[0]);
                    txt.setAttribute("cm-text", m[0]);
                    if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
                    else content.appendChild(txt);
                    builder.col += 1;
                  }
                  builder.map.push(builder.pos, builder.pos + 1, txt);
                  builder.pos++;
                }
              }
              if (style || startStyle || endStyle || mustWrap || css) {
                var fullStyle = style || "";
                if (startStyle) fullStyle += startStyle;
                if (endStyle) fullStyle += endStyle;
                var token = elt("span", [content], fullStyle, css);
                if (title) token.title = title;
                return builder.content.appendChild(token);
              }
              builder.content.appendChild(content);
            }
          
            function splitSpaces(old) {
              var out = " ";
              for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
              out += " ";
              return out;
            }
          
            // Work around nonsense dimensions being reported for stretches of
            // right-to-left text.
            function buildTokenBadBidi(inner, order) {
              return function(builder, text, style, startStyle, endStyle, title, css) {
                style = style ? style + " cm-force-border" : "cm-force-border";
                var start = builder.pos, end = start + text.length;
                for (;;) {
                  // Find the part that overlaps with the start of this text
                  for (var i = 0; i < order.length; i++) {
                    var part = order[i];
                    if (part.to > start && part.from <= start) break;
                  }
                  if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css);
                  inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css);
                  startStyle = null;
                  text = text.slice(part.to - start);
                  start = part.to;
                }
              };
            }
          
            function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
              var widget = !ignoreWidget && marker.widgetNode;
              if (widget) builder.map.push(builder.pos, builder.pos + size, widget);
              if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
                if (!widget)
                  widget = builder.content.appendChild(document.createElement("span"));
                widget.setAttribute("cm-marker", marker.id);
              }
              if (widget) {
                builder.cm.display.input.setUneditable(widget);
                builder.content.appendChild(widget);
              }
              builder.pos += size;
            }
          
            // Outputs a number of spans to make up a line, taking highlighting
            // and marked text into account.
            function insertLineContent(line, builder, styles) {
              var spans = line.markedSpans, allText = line.text, at = 0;
              if (!spans) {
                for (var i = 1; i < styles.length; i+=2)
                  builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options));
                return;
              }
          
              var len = allText.length, pos = 0, i = 1, text = "", style, css;
              var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
              for (;;) {
                if (nextChange == pos) { // Update current marker set
                  spanStyle = spanEndStyle = spanStartStyle = title = css = "";
                  collapsed = null; nextChange = Infinity;
                  var foundBookmarks = [];
                  for (var j = 0; j < spans.length; ++j) {
                    var sp = spans[j], m = sp.marker;
                    if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
                      foundBookmarks.push(m);
                    } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
                      if (sp.to != null && sp.to != pos && nextChange > sp.to) {
                        nextChange = sp.to;
                        spanEndStyle = "";
                      }
                      if (m.className) spanStyle += " " + m.className;
                      if (m.css) css = m.css;
                      if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
                      if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
                      if (m.title && !title) title = m.title;
                      if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
                        collapsed = sp;
                    } else if (sp.from > pos && nextChange > sp.from) {
                      nextChange = sp.from;
                    }
                  }
                  if (collapsed && (collapsed.from || 0) == pos) {
                    buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
                                       collapsed.marker, collapsed.from == null);
                    if (collapsed.to == null) return;
                    if (collapsed.to == pos) collapsed = false;
                  }
                  if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
                    buildCollapsedSpan(builder, 0, foundBookmarks[j]);
                }
                if (pos >= len) break;
          
                var upto = Math.min(len, nextChange);
                while (true) {
                  if (text) {
                    var end = pos + text.length;
                    if (!collapsed) {
                      var tokenText = end > upto ? text.slice(0, upto - pos) : text;
                      builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
                                       spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css);
                    }
                    if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
                    pos = end;
                    spanStartStyle = "";
                  }
                  text = allText.slice(at, at = styles[i++]);
                  style = interpretTokenStyle(styles[i++], builder.cm.options);
                }
              }
            }
          
            // DOCUMENT DATA STRUCTURE
          
            // By default, updates that start and end at the beginning of a line
            // are treated specially, in order to make the association of line
            // widgets and marker elements with the text behave more intuitive.
            function isWholeLineUpdate(doc, change) {
              return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
                (!doc.cm || doc.cm.options.wholeLineUpdateBefore);
            }
          
            // Perform a change on the document data structure.
            function updateDoc(doc, change, markedSpans, estimateHeight) {
              function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
              function update(line, text, spans) {
                updateLine(line, text, spans, estimateHeight);
                signalLater(line, "change", line, change);
              }
              function linesFor(start, end) {
                for (var i = start, result = []; i < end; ++i)
                  result.push(new Line(text[i], spansFor(i), estimateHeight));
                return result;
              }
          
              var from = change.from, to = change.to, text = change.text;
              var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
              var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
          
              // Adjust the line structure
              if (change.full) {
                doc.insert(0, linesFor(0, text.length));
                doc.remove(text.length, doc.size - text.length);
              } else if (isWholeLineUpdate(doc, change)) {
                // This is a whole-line replace. Treated specially to make
                // sure line objects move the way they are supposed to.
                var added = linesFor(0, text.length - 1);
                update(lastLine, lastLine.text, lastSpans);
                if (nlines) doc.remove(from.line, nlines);
                if (added.length) doc.insert(from.line, added);
              } else if (firstLine == lastLine) {
                if (text.length == 1) {
                  update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
                } else {
                  var added = linesFor(1, text.length - 1);
                  added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
                  update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
                  doc.insert(from.line + 1, added);
                }
              } else if (text.length == 1) {
                update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
                doc.remove(from.line + 1, nlines);
              } else {
                update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
                update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
                var added = linesFor(1, text.length - 1);
                if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
                doc.insert(from.line + 1, added);
              }
          
              signalLater(doc, "change", doc, change);
            }
          
            // The document is represented as a BTree consisting of leaves, with
            // chunk of lines in them, and branches, with up to ten leaves or
            // other branch nodes below them. The top node is always a branch
            // node, and is the document object itself (meaning it has
            // additional methods and properties).
            //
            // All nodes have parent links. The tree is used both to go from
            // line numbers to line objects, and to go from objects to numbers.
            // It also indexes by height, and is used to convert between height
            // and line object, and to find the total height of the document.
            //
            // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html
          
            function LeafChunk(lines) {
              this.lines = lines;
              this.parent = null;
              for (var i = 0, height = 0; i < lines.length; ++i) {
                lines[i].parent = this;
                height += lines[i].height;
              }
              this.height = height;
            }
          
            LeafChunk.prototype = {
              chunkSize: function() { return this.lines.length; },
              // Remove the n lines at offset 'at'.
              removeInner: function(at, n) {
                for (var i = at, e = at + n; i < e; ++i) {
                  var line = this.lines[i];
                  this.height -= line.height;
                  cleanUpLine(line);
                  signalLater(line, "delete");
                }
                this.lines.splice(at, n);
              },
              // Helper used to collapse a small branch into a single leaf.
              collapse: function(lines) {
                lines.push.apply(lines, this.lines);
              },
              // Insert the given array of lines at offset 'at', count them as
              // having the given height.
              insertInner: function(at, lines, height) {
                this.height += height;
                this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
                for (var i = 0; i < lines.length; ++i) lines[i].parent = this;
              },
              // Used to iterate over a part of the tree.
              iterN: function(at, n, op) {
                for (var e = at + n; at < e; ++at)
                  if (op(this.lines[at])) return true;
              }
            };
          
            function BranchChunk(children) {
              this.children = children;
              var size = 0, height = 0;
              for (var i = 0; i < children.length; ++i) {
                var ch = children[i];
                size += ch.chunkSize(); height += ch.height;
                ch.parent = this;
              }
              this.size = size;
              this.height = height;
              this.parent = null;
            }
          
            BranchChunk.prototype = {
              chunkSize: function() { return this.size; },
              removeInner: function(at, n) {
                this.size -= n;
                for (var i = 0; i < this.children.length; ++i) {
                  var child = this.children[i], sz = child.chunkSize();
                  if (at < sz) {
                    var rm = Math.min(n, sz - at), oldHeight = child.height;
                    child.removeInner(at, rm);
                    this.height -= oldHeight - child.height;
                    if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
                    if ((n -= rm) == 0) break;
                    at = 0;
                  } else at -= sz;
                }
                // If the result is smaller than 25 lines, ensure that it is a
                // single leaf node.
                if (this.size - n < 25 &&
                    (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
                  var lines = [];
                  this.collapse(lines);
                  this.children = [new LeafChunk(lines)];
                  this.children[0].parent = this;
                }
              },
              collapse: function(lines) {
                for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines);
              },
              insertInner: function(at, lines, height) {
                this.size += lines.length;
                this.height += height;
                for (var i = 0; i < this.children.length; ++i) {
                  var child = this.children[i], sz = child.chunkSize();
                  if (at <= sz) {
                    child.insertInner(at, lines, height);
                    if (child.lines && child.lines.length > 50) {
                      while (child.lines.length > 50) {
                        var spilled = child.lines.splice(child.lines.length - 25, 25);
                        var newleaf = new LeafChunk(spilled);
                        child.height -= newleaf.height;
                        this.children.splice(i + 1, 0, newleaf);
                        newleaf.parent = this;
                      }
                      this.maybeSpill();
                    }
                    break;
                  }
                  at -= sz;
                }
              },
              // When a node has grown, check whether it should be split.
              maybeSpill: function() {
                if (this.children.length <= 10) return;
                var me = this;
                do {
                  var spilled = me.children.splice(me.children.length - 5, 5);
                  var sibling = new BranchChunk(spilled);
                  if (!me.parent) { // Become the parent node
                    var copy = new BranchChunk(me.children);
                    copy.parent = me;
                    me.children = [copy, sibling];
                    me = copy;
                  } else {
                    me.size -= sibling.size;
                    me.height -= sibling.height;
                    var myIndex = indexOf(me.parent.children, me);
                    me.parent.children.splice(myIndex + 1, 0, sibling);
                  }
                  sibling.parent = me.parent;
                } while (me.children.length > 10);
                me.parent.maybeSpill();
              },
              iterN: function(at, n, op) {
                for (var i = 0; i < this.children.length; ++i) {
                  var child = this.children[i], sz = child.chunkSize();
                  if (at < sz) {
                    var used = Math.min(n, sz - at);
                    if (child.iterN(at, used, op)) return true;
                    if ((n -= used) == 0) break;
                    at = 0;
                  } else at -= sz;
                }
              }
            };
          
            var nextDocId = 0;
            var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
              if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
              if (firstLine == null) firstLine = 0;
          
              BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
              this.first = firstLine;
              this.scrollTop = this.scrollLeft = 0;
              this.cantEdit = false;
              this.cleanGeneration = 1;
              this.frontier = firstLine;
              var start = Pos(firstLine, 0);
              this.sel = simpleSelection(start);
              this.history = new History(null);
              this.id = ++nextDocId;
              this.modeOption = mode;
          
              if (typeof text == "string") text = splitLines(text);
              updateDoc(this, {from: start, to: start, text: text});
              setSelection(this, simpleSelection(start), sel_dontScroll);
            };
          
            Doc.prototype = createObj(BranchChunk.prototype, {
              constructor: Doc,
              // Iterate over the document. Supports two forms -- with only one
              // argument, it calls that for each line in the document. With
              // three, it iterates over the range given by the first two (with
              // the second being non-inclusive).
              iter: function(from, to, op) {
                if (op) this.iterN(from - this.first, to - from, op);
                else this.iterN(this.first, this.first + this.size, from);
              },
          
              // Non-public interface for adding and removing lines.
              insert: function(at, lines) {
                var height = 0;
                for (var i = 0; i < lines.length; ++i) height += lines[i].height;
                this.insertInner(at - this.first, lines, height);
              },
              remove: function(at, n) { this.removeInner(at - this.first, n); },
          
              // From here, the methods are part of the public interface. Most
              // are also available from CodeMirror (editor) instances.
          
              getValue: function(lineSep) {
                var lines = getLines(this, this.first, this.first + this.size);
                if (lineSep === false) return lines;
                return lines.join(lineSep || "\n");
              },
              setValue: docMethodOp(function(code) {
                var top = Pos(this.first, 0), last = this.first + this.size - 1;
                makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
                                  text: splitLines(code), origin: "setValue", full: true}, true);
                setSelection(this, simpleSelection(top));
              }),
              replaceRange: function(code, from, to, origin) {
                from = clipPos(this, from);
                to = to ? clipPos(this, to) : from;
                replaceRange(this, code, from, to, origin);
              },
              getRange: function(from, to, lineSep) {
                var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
                if (lineSep === false) return lines;
                return lines.join(lineSep || "\n");
              },
          
              getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
          
              getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
              getLineNumber: function(line) {return lineNo(line);},
          
              getLineHandleVisualStart: function(line) {
                if (typeof line == "number") line = getLine(this, line);
                return visualLine(line);
              },
          
              lineCount: function() {return this.size;},
              firstLine: function() {return this.first;},
              lastLine: function() {return this.first + this.size - 1;},
          
              clipPos: function(pos) {return clipPos(this, pos);},
          
              getCursor: function(start) {
                var range = this.sel.primary(), pos;
                if (start == null || start == "head") pos = range.head;
                else if (start == "anchor") pos = range.anchor;
                else if (start == "end" || start == "to" || start === false) pos = range.to();
                else pos = range.from();
                return pos;
              },
              listSelections: function() { return this.sel.ranges; },
              somethingSelected: function() {return this.sel.somethingSelected();},
          
              setCursor: docMethodOp(function(line, ch, options) {
                setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options);
              }),
              setSelection: docMethodOp(function(anchor, head, options) {
                setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);
              }),
              extendSelection: docMethodOp(function(head, other, options) {
                extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);
              }),
              extendSelections: docMethodOp(function(heads, options) {
                extendSelections(this, clipPosArray(this, heads, options));
              }),
              extendSelectionsBy: docMethodOp(function(f, options) {
                extendSelections(this, map(this.sel.ranges, f), options);
              }),
              setSelections: docMethodOp(function(ranges, primary, options) {
                if (!ranges.length) return;
                for (var i = 0, out = []; i < ranges.length; i++)
                  out[i] = new Range(clipPos(this, ranges[i].anchor),
                                     clipPos(this, ranges[i].head));
                if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex);
                setSelection(this, normalizeSelection(out, primary), options);
              }),
              addSelection: docMethodOp(function(anchor, head, options) {
                var ranges = this.sel.ranges.slice(0);
                ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));
                setSelection(this, normalizeSelection(ranges, ranges.length - 1), options);
              }),
          
              getSelection: function(lineSep) {
                var ranges = this.sel.ranges, lines;
                for (var i = 0; i < ranges.length; i++) {
                  var sel = getBetween(this, ranges[i].from(), ranges[i].to());
                  lines = lines ? lines.concat(sel) : sel;
                }
                if (lineSep === false) return lines;
                else return lines.join(lineSep || "\n");
              },
              getSelections: function(lineSep) {
                var parts = [], ranges = this.sel.ranges;
                for (var i = 0; i < ranges.length; i++) {
                  var sel = getBetween(this, ranges[i].from(), ranges[i].to());
                  if (lineSep !== false) sel = sel.join(lineSep || "\n");
                  parts[i] = sel;
                }
                return parts;
              },
              replaceSelection: function(code, collapse, origin) {
                var dup = [];
                for (var i = 0; i < this.sel.ranges.length; i++)
                  dup[i] = code;
                this.replaceSelections(dup, collapse, origin || "+input");
              },
              replaceSelections: docMethodOp(function(code, collapse, origin) {
                var changes = [], sel = this.sel;
                for (var i = 0; i < sel.ranges.length; i++) {
                  var range = sel.ranges[i];
                  changes[i] = {from: range.from(), to: range.to(), text: splitLines(code[i]), origin: origin};
                }
                var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
                for (var i = changes.length - 1; i >= 0; i--)
                  makeChange(this, changes[i]);
                if (newSel) setSelectionReplaceHistory(this, newSel);
                else if (this.cm) ensureCursorVisible(this.cm);
              }),
              undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}),
              redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}),
              undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}),
              redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}),
          
              setExtending: function(val) {this.extend = val;},
              getExtending: function() {return this.extend;},
          
              historySize: function() {
                var hist = this.history, done = 0, undone = 0;
                for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done;
                for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone;
                return {undo: done, redo: undone};
              },
              clearHistory: function() {this.history = new History(this.history.maxGeneration);},
          
              markClean: function() {
                this.cleanGeneration = this.changeGeneration(true);
              },
              changeGeneration: function(forceSplit) {
                if (forceSplit)
                  this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null;
                return this.history.generation;
              },
              isClean: function (gen) {
                return this.history.generation == (gen || this.cleanGeneration);
              },
          
              getHistory: function() {
                return {done: copyHistoryArray(this.history.done),
                        undone: copyHistoryArray(this.history.undone)};
              },
              setHistory: function(histData) {
                var hist = this.history = new History(this.history.maxGeneration);
                hist.done = copyHistoryArray(histData.done.slice(0), null, true);
                hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
              },
          
              addLineClass: docMethodOp(function(handle, where, cls) {
                return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
                  var prop = where == "text" ? "textClass"
                           : where == "background" ? "bgClass"
                           : where == "gutter" ? "gutterClass" : "wrapClass";
                  if (!line[prop]) line[prop] = cls;
                  else if (classTest(cls).test(line[prop])) return false;
                  else line[prop] += " " + cls;
                  return true;
                });
              }),
              removeLineClass: docMethodOp(function(handle, where, cls) {
                return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
                  var prop = where == "text" ? "textClass"
                           : where == "background" ? "bgClass"
                           : where == "gutter" ? "gutterClass" : "wrapClass";
                  var cur = line[prop];
                  if (!cur) return false;
                  else if (cls == null) line[prop] = null;
                  else {
                    var found = cur.match(classTest(cls));
                    if (!found) return false;
                    var end = found.index + found[0].length;
                    line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
                  }
                  return true;
                });
              }),
          
              addLineWidget: docMethodOp(function(handle, node, options) {
                return addLineWidget(this, handle, node, options);
              }),
              removeLineWidget: function(widget) { widget.clear(); },
          
              markText: function(from, to, options) {
                return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
              },
              setBookmark: function(pos, options) {
                var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
                                insertLeft: options && options.insertLeft,
                                clearWhenEmpty: false, shared: options && options.shared,
                                handleMouseEvents: options && options.handleMouseEvents};
                pos = clipPos(this, pos);
                return markText(this, pos, pos, realOpts, "bookmark");
              },
              findMarksAt: function(pos) {
                pos = clipPos(this, pos);
                var markers = [], spans = getLine(this, pos.line).markedSpans;
                if (spans) for (var i = 0; i < spans.length; ++i) {
                  var span = spans[i];
                  if ((span.from == null || span.from <= pos.ch) &&
                      (span.to == null || span.to >= pos.ch))
                    markers.push(span.marker.parent || span.marker);
                }
                return markers;
              },
              findMarks: function(from, to, filter) {
                from = clipPos(this, from); to = clipPos(this, to);
                var found = [], lineNo = from.line;
                this.iter(from.line, to.line + 1, function(line) {
                  var spans = line.markedSpans;
                  if (spans) for (var i = 0; i < spans.length; i++) {
                    var span = spans[i];
                    if (!(lineNo == from.line && from.ch > span.to ||
                          span.from == null && lineNo != from.line||
                          lineNo == to.line && span.from > to.ch) &&
                        (!filter || filter(span.marker)))
                      found.push(span.marker.parent || span.marker);
                  }
                  ++lineNo;
                });
                return found;
              },
              getAllMarks: function() {
                var markers = [];
                this.iter(function(line) {
                  var sps = line.markedSpans;
                  if (sps) for (var i = 0; i < sps.length; ++i)
                    if (sps[i].from != null) markers.push(sps[i].marker);
                });
                return markers;
              },
          
              posFromIndex: function(off) {
                var ch, lineNo = this.first;
                this.iter(function(line) {
                  var sz = line.text.length + 1;
                  if (sz > off) { ch = off; return true; }
                  off -= sz;
                  ++lineNo;
                });
                return clipPos(this, Pos(lineNo, ch));
              },
              indexFromPos: function (coords) {
                coords = clipPos(this, coords);
                var index = coords.ch;
                if (coords.line < this.first || coords.ch < 0) return 0;
                this.iter(this.first, coords.line, function (line) {
                  index += line.text.length + 1;
                });
                return index;
              },
          
              copy: function(copyHistory) {
                var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
                doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
                doc.sel = this.sel;
                doc.extend = false;
                if (copyHistory) {
                  doc.history.undoDepth = this.history.undoDepth;
                  doc.setHistory(this.getHistory());
                }
                return doc;
              },
          
              linkedDoc: function(options) {
                if (!options) options = {};
                var from = this.first, to = this.first + this.size;
                if (options.from != null && options.from > from) from = options.from;
                if (options.to != null && options.to < to) to = options.to;
                var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
                if (options.sharedHist) copy.history = this.history;
                (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
                copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
                copySharedMarkers(copy, findSharedMarkers(this));
                return copy;
              },
              unlinkDoc: function(other) {
                if (other instanceof CodeMirror) other = other.doc;
                if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
                  var link = this.linked[i];
                  if (link.doc != other) continue;
                  this.linked.splice(i, 1);
                  other.unlinkDoc(this);
                  detachSharedMarkers(findSharedMarkers(this));
                  break;
                }
                // If the histories were shared, split them again
                if (other.history == this.history) {
                  var splitIds = [other.id];
                  linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
                  other.history = new History(null);
                  other.history.done = copyHistoryArray(this.history.done, splitIds);
                  other.history.undone = copyHistoryArray(this.history.undone, splitIds);
                }
              },
              iterLinkedDocs: function(f) {linkedDocs(this, f);},
          
              getMode: function() {return this.mode;},
              getEditor: function() {return this.cm;}
            });
          
            // Public alias.
            Doc.prototype.eachLine = Doc.prototype.iter;
          
            // Set up methods on CodeMirror's prototype to redirect to the editor's document.
            var dontDelegate = "iter insert remove copy getEditor".split(" ");
            for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
              CodeMirror.prototype[prop] = (function(method) {
                return function() {return method.apply(this.doc, arguments);};
              })(Doc.prototype[prop]);
          
            eventMixin(Doc);
          
            // Call f for all linked documents.
            function linkedDocs(doc, f, sharedHistOnly) {
              function propagate(doc, skip, sharedHist) {
                if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
                  var rel = doc.linked[i];
                  if (rel.doc == skip) continue;
                  var shared = sharedHist && rel.sharedHist;
                  if (sharedHistOnly && !shared) continue;
                  f(rel.doc, shared);
                  propagate(rel.doc, doc, shared);
                }
              }
              propagate(doc, null, true);
            }
          
            // Attach a document to an editor.
            function attachDoc(cm, doc) {
              if (doc.cm) throw new Error("This document is already in use.");
              cm.doc = doc;
              doc.cm = cm;
              estimateLineHeights(cm);
              loadMode(cm);
              if (!cm.options.lineWrapping) findMaxLine(cm);
              cm.options.mode = doc.modeOption;
              regChange(cm);
            }
          
            // LINE UTILITIES
          
            // Find the line object corresponding to the given line number.
            function getLine(doc, n) {
              n -= doc.first;
              if (n < 0 || n >= doc.size) throw new Error("There is no line " + (n + doc.first) + " in the document.");
              for (var chunk = doc; !chunk.lines;) {
                for (var i = 0;; ++i) {
                  var child = chunk.children[i], sz = child.chunkSize();
                  if (n < sz) { chunk = child; break; }
                  n -= sz;
                }
              }
              return chunk.lines[n];
            }
          
            // Get the part of a document between two positions, as an array of
            // strings.
            function getBetween(doc, start, end) {
              var out = [], n = start.line;
              doc.iter(start.line, end.line + 1, function(line) {
                var text = line.text;
                if (n == end.line) text = text.slice(0, end.ch);
                if (n == start.line) text = text.slice(start.ch);
                out.push(text);
                ++n;
              });
              return out;
            }
            // Get the lines between from and to, as array of strings.
            function getLines(doc, from, to) {
              var out = [];
              doc.iter(from, to, function(line) { out.push(line.text); });
              return out;
            }
          
            // Update the height of a line, propagating the height change
            // upwards to parent nodes.
            function updateLineHeight(line, height) {
              var diff = height - line.height;
              if (diff) for (var n = line; n; n = n.parent) n.height += diff;
            }
          
            // Given a line object, find its line number by walking up through
            // its parent links.
            function lineNo(line) {
              if (line.parent == null) return null;
              var cur = line.parent, no = indexOf(cur.lines, line);
              for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
                for (var i = 0;; ++i) {
                  if (chunk.children[i] == cur) break;
                  no += chunk.children[i].chunkSize();
                }
              }
              return no + cur.first;
            }
          
            // Find the line at the given vertical position, using the height
            // information in the document tree.
            function lineAtHeight(chunk, h) {
              var n = chunk.first;
              outer: do {
                for (var i = 0; i < chunk.children.length; ++i) {
                  var child = chunk.children[i], ch = child.height;
                  if (h < ch) { chunk = child; continue outer; }
                  h -= ch;
                  n += child.chunkSize();
                }
                return n;
              } while (!chunk.lines);
              for (var i = 0; i < chunk.lines.length; ++i) {
                var line = chunk.lines[i], lh = line.height;
                if (h < lh) break;
                h -= lh;
              }
              return n + i;
            }
          
          
            // Find the height above the given line.
            function heightAtLine(lineObj) {
              lineObj = visualLine(lineObj);
          
              var h = 0, chunk = lineObj.parent;
              for (var i = 0; i < chunk.lines.length; ++i) {
                var line = chunk.lines[i];
                if (line == lineObj) break;
                else h += line.height;
              }
              for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
                for (var i = 0; i < p.children.length; ++i) {
                  var cur = p.children[i];
                  if (cur == chunk) break;
                  else h += cur.height;
                }
              }
              return h;
            }
          
            // Get the bidi ordering for the given line (and cache it). Returns
            // false for lines that are fully left-to-right, and an array of
            // BidiSpan objects otherwise.
            function getOrder(line) {
              var order = line.order;
              if (order == null) order = line.order = bidiOrdering(line.text);
              return order;
            }
          
            // HISTORY
          
            function History(startGen) {
              // Arrays of change events and selections. Doing something adds an
              // event to done and clears undo. Undoing moves events from done
              // to undone, redoing moves them in the other direction.
              this.done = []; this.undone = [];
              this.undoDepth = Infinity;
              // Used to track when changes can be merged into a single undo
              // event
              this.lastModTime = this.lastSelTime = 0;
              this.lastOp = this.lastSelOp = null;
              this.lastOrigin = this.lastSelOrigin = null;
              // Used by the isClean() method
              this.generation = this.maxGeneration = startGen || 1;
            }
          
            // Create a history change event from an updateDoc-style change
            // object.
            function historyChangeFromChange(doc, change) {
              var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
              attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
              linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
              return histChange;
            }
          
            // Pop all selection events off the end of a history array. Stop at
            // a change event.
            function clearSelectionEvents(array) {
              while (array.length) {
                var last = lst(array);
                if (last.ranges) array.pop();
                else break;
              }
            }
          
            // Find the top change event in the history. Pop off selection
            // events that are in the way.
            function lastChangeEvent(hist, force) {
              if (force) {
                clearSelectionEvents(hist.done);
                return lst(hist.done);
              } else if (hist.done.length && !lst(hist.done).ranges) {
                return lst(hist.done);
              } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
                hist.done.pop();
                return lst(hist.done);
              }
            }
          
            // Register a change in the history. Merges changes that are within
            // a single operation, ore are close together with an origin that
            // allows merging (starting with "+") into a single event.
            function addChangeToHistory(doc, change, selAfter, opId) {
              var hist = doc.history;
              hist.undone.length = 0;
              var time = +new Date, cur;
          
              if ((hist.lastOp == opId ||
                   hist.lastOrigin == change.origin && change.origin &&
                   ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||
                    change.origin.charAt(0) == "*")) &&
                  (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
                // Merge this change into the last event
                var last = lst(cur.changes);
                if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
                  // Optimized case for simple insertion -- don't want to add
                  // new changesets for every character typed
                  last.to = changeEnd(change);
                } else {
                  // Add new sub-event
                  cur.changes.push(historyChangeFromChange(doc, change));
                }
              } else {
                // Can not be merged, start a new event.
                var before = lst(hist.done);
                if (!before || !before.ranges)
                  pushSelectionToHistory(doc.sel, hist.done);
                cur = {changes: [historyChangeFromChange(doc, change)],
                       generation: hist.generation};
                hist.done.push(cur);
                while (hist.done.length > hist.undoDepth) {
                  hist.done.shift();
                  if (!hist.done[0].ranges) hist.done.shift();
                }
              }
              hist.done.push(selAfter);
              hist.generation = ++hist.maxGeneration;
              hist.lastModTime = hist.lastSelTime = time;
              hist.lastOp = hist.lastSelOp = opId;
              hist.lastOrigin = hist.lastSelOrigin = change.origin;
          
              if (!last) signal(doc, "historyAdded");
            }
          
            function selectionEventCanBeMerged(doc, origin, prev, sel) {
              var ch = origin.charAt(0);
              return ch == "*" ||
                ch == "+" &&
                prev.ranges.length == sel.ranges.length &&
                prev.somethingSelected() == sel.somethingSelected() &&
                new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500);
            }
          
            // Called whenever the selection changes, sets the new selection as
            // the pending selection in the history, and pushes the old pending
            // selection into the 'done' array when it was significantly
            // different (in number of selected ranges, emptiness, or time).
            function addSelectionToHistory(doc, sel, opId, options) {
              var hist = doc.history, origin = options && options.origin;
          
              // A new event is started when the previous origin does not match
              // the current, or the origins don't allow matching. Origins
              // starting with * are always merged, those starting with + are
              // merged when similar and close together in time.
              if (opId == hist.lastSelOp ||
                  (origin && hist.lastSelOrigin == origin &&
                   (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
                    selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
                hist.done[hist.done.length - 1] = sel;
              else
                pushSelectionToHistory(sel, hist.done);
          
              hist.lastSelTime = +new Date;
              hist.lastSelOrigin = origin;
              hist.lastSelOp = opId;
              if (options && options.clearRedo !== false)
                clearSelectionEvents(hist.undone);
            }
          
            function pushSelectionToHistory(sel, dest) {
              var top = lst(dest);
              if (!(top && top.ranges && top.equals(sel)))
                dest.push(sel);
            }
          
            // Used to store marked span information in the history.
            function attachLocalSpans(doc, change, from, to) {
              var existing = change["spans_" + doc.id], n = 0;
              doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
                if (line.markedSpans)
                  (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
                ++n;
              });
            }
          
            // When un/re-doing restores text containing marked spans, those
            // that have been explicitly cleared should not be restored.
            function removeClearedSpans(spans) {
              if (!spans) return null;
              for (var i = 0, out; i < spans.length; ++i) {
                if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
                else if (out) out.push(spans[i]);
              }
              return !out ? spans : out.length ? out : null;
            }
          
            // Retrieve and filter the old marked spans stored in a change event.
            function getOldSpans(doc, change) {
              var found = change["spans_" + doc.id];
              if (!found) return null;
              for (var i = 0, nw = []; i < change.text.length; ++i)
                nw.push(removeClearedSpans(found[i]));
              return nw;
            }
          
            // Used both to provide a JSON-safe object in .getHistory, and, when
            // detaching a document, to split the history in two
            function copyHistoryArray(events, newGroup, instantiateSel) {
              for (var i = 0, copy = []; i < events.length; ++i) {
                var event = events[i];
                if (event.ranges) {
                  copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);
                  continue;
                }
                var changes = event.changes, newChanges = [];
                copy.push({changes: newChanges});
                for (var j = 0; j < changes.length; ++j) {
                  var change = changes[j], m;
                  newChanges.push({from: change.from, to: change.to, text: change.text});
                  if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
                    if (indexOf(newGroup, Number(m[1])) > -1) {
                      lst(newChanges)[prop] = change[prop];
                      delete change[prop];
                    }
                  }
                }
              }
              return copy;
            }
          
            // Rebasing/resetting history to deal with externally-sourced changes
          
            function rebaseHistSelSingle(pos, from, to, diff) {
              if (to < pos.line) {
                pos.line += diff;
              } else if (from < pos.line) {
                pos.line = from;
                pos.ch = 0;
              }
            }
          
            // Tries to rebase an array of history events given a change in the
            // document. If the change touches the same lines as the event, the
            // event, and everything 'behind' it, is discarded. If the change is
            // before the event, the event's positions are updated. Uses a
            // copy-on-write scheme for the positions, to avoid having to
            // reallocate them all on every rebase, but also avoid problems with
            // shared position objects being unsafely updated.
            function rebaseHistArray(array, from, to, diff) {
              for (var i = 0; i < array.length; ++i) {
                var sub = array[i], ok = true;
                if (sub.ranges) {
                  if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }
                  for (var j = 0; j < sub.ranges.length; j++) {
                    rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);
                    rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);
                  }
                  continue;
                }
                for (var j = 0; j < sub.changes.length; ++j) {
                  var cur = sub.changes[j];
                  if (to < cur.from.line) {
                    cur.from = Pos(cur.from.line + diff, cur.from.ch);
                    cur.to = Pos(cur.to.line + diff, cur.to.ch);
                  } else if (from <= cur.to.line) {
                    ok = false;
                    break;
                  }
                }
                if (!ok) {
                  array.splice(0, i + 1);
                  i = 0;
                }
              }
            }
          
            function rebaseHist(hist, change) {
              var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
              rebaseHistArray(hist.done, from, to, diff);
              rebaseHistArray(hist.undone, from, to, diff);
            }
          
            // EVENT UTILITIES
          
            // Due to the fact that we still support jurassic IE versions, some
            // compatibility wrappers are needed.
          
            var e_preventDefault = CodeMirror.e_preventDefault = function(e) {
              if (e.preventDefault) e.preventDefault();
              else e.returnValue = false;
            };
            var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) {
              if (e.stopPropagation) e.stopPropagation();
              else e.cancelBubble = true;
            };
            function e_defaultPrevented(e) {
              return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
            }
            var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);};
          
            function e_target(e) {return e.target || e.srcElement;}
            function e_button(e) {
              var b = e.which;
              if (b == null) {
                if (e.button & 1) b = 1;
                else if (e.button & 2) b = 3;
                else if (e.button & 4) b = 2;
              }
              if (mac && e.ctrlKey && b == 1) b = 3;
              return b;
            }
          
            // EVENT HANDLING
          
            // Lightweight event framework. on/off also work on DOM nodes,
            // registering native DOM handlers.
          
            var on = CodeMirror.on = function(emitter, type, f) {
              if (emitter.addEventListener)
                emitter.addEventListener(type, f, false);
              else if (emitter.attachEvent)
                emitter.attachEvent("on" + type, f);
              else {
                var map = emitter._handlers || (emitter._handlers = {});
                var arr = map[type] || (map[type] = []);
                arr.push(f);
              }
            };
          
            var off = CodeMirror.off = function(emitter, type, f) {
              if (emitter.removeEventListener)
                emitter.removeEventListener(type, f, false);
              else if (emitter.detachEvent)
                emitter.detachEvent("on" + type, f);
              else {
                var arr = emitter._handlers && emitter._handlers[type];
                if (!arr) return;
                for (var i = 0; i < arr.length; ++i)
                  if (arr[i] == f) { arr.splice(i, 1); break; }
              }
            };
          
            var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {
              var arr = emitter._handlers && emitter._handlers[type];
              if (!arr) return;
              var args = Array.prototype.slice.call(arguments, 2);
              for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
            };
          
            var orphanDelayedCallbacks = null;
          
            // Often, we want to signal events at a point where we are in the
            // middle of some work, but don't want the handler to start calling
            // other methods on the editor, which might be in an inconsistent
            // state or simply not expect any other events to happen.
            // signalLater looks whether there are any handlers, and schedules
            // them to be executed when the last operation ends, or, if no
            // operation is active, when a timeout fires.
            function signalLater(emitter, type /*, values...*/) {
              var arr = emitter._handlers && emitter._handlers[type];
              if (!arr) return;
              var args = Array.prototype.slice.call(arguments, 2), list;
              if (operationGroup) {
                list = operationGroup.delayedCallbacks;
              } else if (orphanDelayedCallbacks) {
                list = orphanDelayedCallbacks;
              } else {
                list = orphanDelayedCallbacks = [];
                setTimeout(fireOrphanDelayed, 0);
              }
              function bnd(f) {return function(){f.apply(null, args);};};
              for (var i = 0; i < arr.length; ++i)
                list.push(bnd(arr[i]));
            }
          
            function fireOrphanDelayed() {
              var delayed = orphanDelayedCallbacks;
              orphanDelayedCallbacks = null;
              for (var i = 0; i < delayed.length; ++i) delayed[i]();
            }
          
            // The DOM events that CodeMirror handles can be overridden by
            // registering a (non-DOM) handler on the editor for the event name,
            // and preventDefault-ing the event in that handler.
            function signalDOMEvent(cm, e, override) {
              if (typeof e == "string")
                e = {type: e, preventDefault: function() { this.defaultPrevented = true; }};
              signal(cm, override || e.type, cm, e);
              return e_defaultPrevented(e) || e.codemirrorIgnore;
            }
          
            function signalCursorActivity(cm) {
              var arr = cm._handlers && cm._handlers.cursorActivity;
              if (!arr) return;
              var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);
              for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1)
                set.push(arr[i]);
            }
          
            function hasHandler(emitter, type) {
              var arr = emitter._handlers && emitter._handlers[type];
              return arr && arr.length > 0;
            }
          
            // Add on and off methods to a constructor's prototype, to make
            // registering events on such objects more convenient.
            function eventMixin(ctor) {
              ctor.prototype.on = function(type, f) {on(this, type, f);};
              ctor.prototype.off = function(type, f) {off(this, type, f);};
            }
          
            // MISC UTILITIES
          
            // Number of pixels added to scroller and sizer to hide scrollbar
            var scrollerGap = 30;
          
            // Returned or thrown by various protocols to signal 'I'm not
            // handling this'.
            var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
          
            // Reused option objects for setSelection & friends
            var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"};
          
            function Delayed() {this.id = null;}
            Delayed.prototype.set = function(ms, f) {
              clearTimeout(this.id);
              this.id = setTimeout(f, ms);
            };
          
            // Counts the column offset in a string, taking tabs into account.
            // Used mostly to find indentation.
            var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) {
              if (end == null) {
                end = string.search(/[^\s\u00a0]/);
                if (end == -1) end = string.length;
              }
              for (var i = startIndex || 0, n = startValue || 0;;) {
                var nextTab = string.indexOf("\t", i);
                if (nextTab < 0 || nextTab >= end)
                  return n + (end - i);
                n += nextTab - i;
                n += tabSize - (n % tabSize);
                i = nextTab + 1;
              }
            };
          
            // The inverse of countColumn -- find the offset that corresponds to
            // a particular column.
            function findColumn(string, goal, tabSize) {
              for (var pos = 0, col = 0;;) {
                var nextTab = string.indexOf("\t", pos);
                if (nextTab == -1) nextTab = string.length;
                var skipped = nextTab - pos;
                if (nextTab == string.length || col + skipped >= goal)
                  return pos + Math.min(skipped, goal - col);
                col += nextTab - pos;
                col += tabSize - (col % tabSize);
                pos = nextTab + 1;
                if (col >= goal) return pos;
              }
            }
          
            var spaceStrs = [""];
            function spaceStr(n) {
              while (spaceStrs.length <= n)
                spaceStrs.push(lst(spaceStrs) + " ");
              return spaceStrs[n];
            }
          
            function lst(arr) { return arr[arr.length-1]; }
          
            var selectInput = function(node) { node.select(); };
            if (ios) // Mobile Safari apparently has a bug where select() is broken.
              selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; };
            else if (ie) // Suppress mysterious IE10 errors
              selectInput = function(node) { try { node.select(); } catch(_e) {} };
          
            function indexOf(array, elt) {
              for (var i = 0; i < array.length; ++i)
                if (array[i] == elt) return i;
              return -1;
            }
            function map(array, f) {
              var out = [];
              for (var i = 0; i < array.length; i++) out[i] = f(array[i], i);
              return out;
            }
          
            function nothing() {}
          
            function createObj(base, props) {
              var inst;
              if (Object.create) {
                inst = Object.create(base);
              } else {
                nothing.prototype = base;
                inst = new nothing();
              }
              if (props) copyObj(props, inst);
              return inst;
            };
          
            function copyObj(obj, target, overwrite) {
              if (!target) target = {};
              for (var prop in obj)
                if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
                  target[prop] = obj[prop];
              return target;
            }
          
            function bind(f) {
              var args = Array.prototype.slice.call(arguments, 1);
              return function(){return f.apply(null, args);};
            }
          
            var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
            var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
              return /\w/.test(ch) || ch > "\x80" &&
                (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
            };
            function isWordChar(ch, helper) {
              if (!helper) return isWordCharBasic(ch);
              if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true;
              return helper.test(ch);
            }
          
            function isEmpty(obj) {
              for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
              return true;
            }
          
            // Extending unicode characters. A series of a non-extending char +
            // any number of extending chars is treated as a single unit as far
            // as editing and measuring is concerned. This is not fully correct,
            // since some scripts/fonts/browsers also treat other configurations
            // of code points as a group.
            var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;
            function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); }
          
            // DOM UTILITIES
          
            function elt(tag, content, className, style) {
              var e = document.createElement(tag);
              if (className) e.className = className;
              if (style) e.style.cssText = style;
              if (typeof content == "string") e.appendChild(document.createTextNode(content));
              else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
              return e;
            }
          
            var range;
            if (document.createRange) range = function(node, start, end, endNode) {
              var r = document.createRange();
              r.setEnd(endNode || node, end);
              r.setStart(node, start);
              return r;
            };
            else range = function(node, start, end) {
              var r = document.body.createTextRange();
              try { r.moveToElementText(node.parentNode); }
              catch(e) { return r; }
              r.collapse(true);
              r.moveEnd("character", end);
              r.moveStart("character", start);
              return r;
            };
          
            function removeChildren(e) {
              for (var count = e.childNodes.length; count > 0; --count)
                e.removeChild(e.firstChild);
              return e;
            }
          
            function removeChildrenAndAdd(parent, e) {
              return removeChildren(parent).appendChild(e);
            }
          
            var contains = CodeMirror.contains = function(parent, child) {
              if (child.nodeType == 3) // Android browser always returns false when child is a textnode
                child = child.parentNode;
              if (parent.contains)
                return parent.contains(child);
              do {
                if (child.nodeType == 11) child = child.host;
                if (child == parent) return true;
              } while (child = child.parentNode);
            };
          
            function activeElt() { return document.activeElement; }
            // Older versions of IE throws unspecified error when touching
            // document.activeElement in some cases (during loading, in iframe)
            if (ie && ie_version < 11) activeElt = function() {
              try { return document.activeElement; }
              catch(e) { return document.body; }
            };
          
            function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); }
            var rmClass = CodeMirror.rmClass = function(node, cls) {
              var current = node.className;
              var match = classTest(cls).exec(current);
              if (match) {
                var after = current.slice(match.index + match[0].length);
                node.className = current.slice(0, match.index) + (after ? match[1] + after : "");
              }
            };
            var addClass = CodeMirror.addClass = function(node, cls) {
              var current = node.className;
              if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls;
            };
            function joinClasses(a, b) {
              var as = a.split(" ");
              for (var i = 0; i < as.length; i++)
                if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i];
              return b;
            }
          
            // WINDOW-WIDE EVENTS
          
            // These must be handled carefully, because naively registering a
            // handler for each editor will cause the editors to never be
            // garbage collected.
          
            function forEachCodeMirror(f) {
              if (!document.body.getElementsByClassName) return;
              var byClass = document.body.getElementsByClassName("CodeMirror");
              for (var i = 0; i < byClass.length; i++) {
                var cm = byClass[i].CodeMirror;
                if (cm) f(cm);
              }
            }
          
            var globalsRegistered = false;
            function ensureGlobalHandlers() {
              if (globalsRegistered) return;
              registerGlobalHandlers();
              globalsRegistered = true;
            }
            function registerGlobalHandlers() {
              // When the window resizes, we need to refresh active editors.
              var resizeTimer;
              on(window, "resize", function() {
                if (resizeTimer == null) resizeTimer = setTimeout(function() {
                  resizeTimer = null;
                  forEachCodeMirror(onResize);
                }, 100);
              });
              // When the window loses focus, we want to show the editor as blurred
              on(window, "blur", function() {
                forEachCodeMirror(onBlur);
              });
            }
          
            // FEATURE DETECTION
          
            // Detect drag-and-drop
            var dragAndDrop = function() {
              // There is *some* kind of drag-and-drop support in IE6-8, but I
              // couldn't get it to work yet.
              if (ie && ie_version < 9) return false;
              var div = elt('div');
              return "draggable" in div || "dragDrop" in div;
            }();
          
            var zwspSupported;
            function zeroWidthElement(measure) {
              if (zwspSupported == null) {
                var test = elt("span", "\u200b");
                removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
                if (measure.firstChild.offsetHeight != 0)
                  zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8);
              }
              var node = zwspSupported ? elt("span", "\u200b") :
                elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
              node.setAttribute("cm-text", "");
              return node;
            }
          
            // Feature-detect IE's crummy client rect reporting for bidi text
            var badBidiRects;
            function hasBadBidiRects(measure) {
              if (badBidiRects != null) return badBidiRects;
              var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
              var r0 = range(txt, 0, 1).getBoundingClientRect();
              if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780)
              var r1 = range(txt, 1, 2).getBoundingClientRect();
              return badBidiRects = (r1.right - r0.right < 3);
            }
          
            // See if "".split is the broken IE version, if so, provide an
            // alternative way to split lines.
            var splitLines = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
              var pos = 0, result = [], l = string.length;
              while (pos <= l) {
                var nl = string.indexOf("\n", pos);
                if (nl == -1) nl = string.length;
                var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
                var rt = line.indexOf("\r");
                if (rt != -1) {
                  result.push(line.slice(0, rt));
                  pos += rt + 1;
                } else {
                  result.push(line);
                  pos = nl + 1;
                }
              }
              return result;
            } : function(string){return string.split(/\r\n?|\n/);};
          
            var hasSelection = window.getSelection ? function(te) {
              try { return te.selectionStart != te.selectionEnd; }
              catch(e) { return false; }
            } : function(te) {
              try {var range = te.ownerDocument.selection.createRange();}
              catch(e) {}
              if (!range || range.parentElement() != te) return false;
              return range.compareEndPoints("StartToEnd", range) != 0;
            };
          
            var hasCopyEvent = (function() {
              var e = elt("div");
              if ("oncopy" in e) return true;
              e.setAttribute("oncopy", "return;");
              return typeof e.oncopy == "function";
            })();
          
            var badZoomedRects = null;
            function hasBadZoomedRects(measure) {
              if (badZoomedRects != null) return badZoomedRects;
              var node = removeChildrenAndAdd(measure, elt("span", "x"));
              var normal = node.getBoundingClientRect();
              var fromRange = range(node, 0, 1).getBoundingClientRect();
              return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1;
            }
          
            // KEY NAMES
          
            var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
                            19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
                            36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
                            46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", 107: "=", 109: "-", 127: "Delete",
                            173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
                            221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
                            63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"};
            CodeMirror.keyNames = keyNames;
            (function() {
              // Number keys
              for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i);
              // Alphabetic keys
              for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
              // Function keys
              for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
            })();
          
            // BIDI HELPERS
          
            function iterateBidiSections(order, from, to, f) {
              if (!order) return f(from, to, "ltr");
              var found = false;
              for (var i = 0; i < order.length; ++i) {
                var part = order[i];
                if (part.from < to && part.to > from || from == to && part.to == from) {
                  f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
                  found = true;
                }
              }
              if (!found) f(from, to, "ltr");
            }
          
            function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
            function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
          
            function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
            function lineRight(line) {
              var order = getOrder(line);
              if (!order) return line.text.length;
              return bidiRight(lst(order));
            }
          
            function lineStart(cm, lineN) {
              var line = getLine(cm.doc, lineN);
              var visual = visualLine(line);
              if (visual != line) lineN = lineNo(visual);
              var order = getOrder(visual);
              var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
              return Pos(lineN, ch);
            }
            function lineEnd(cm, lineN) {
              var merged, line = getLine(cm.doc, lineN);
              while (merged = collapsedSpanAtEnd(line)) {
                line = merged.find(1, true).line;
                lineN = null;
              }
              var order = getOrder(line);
              var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
              return Pos(lineN == null ? lineNo(line) : lineN, ch);
            }
            function lineStartSmart(cm, pos) {
              var start = lineStart(cm, pos.line);
              var line = getLine(cm.doc, start.line);
              var order = getOrder(line);
              if (!order || order[0].level == 0) {
                var firstNonWS = Math.max(0, line.text.search(/\S/));
                var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;
                return Pos(start.line, inWS ? 0 : firstNonWS);
              }
              return start;
            }
          
            function compareBidiLevel(order, a, b) {
              var linedir = order[0].level;
              if (a == linedir) return true;
              if (b == linedir) return false;
              return a < b;
            }
            var bidiOther;
            function getBidiPartAt(order, pos) {
              bidiOther = null;
              for (var i = 0, found; i < order.length; ++i) {
                var cur = order[i];
                if (cur.from < pos && cur.to > pos) return i;
                if ((cur.from == pos || cur.to == pos)) {
                  if (found == null) {
                    found = i;
                  } else if (compareBidiLevel(order, cur.level, order[found].level)) {
                    if (cur.from != cur.to) bidiOther = found;
                    return i;
                  } else {
                    if (cur.from != cur.to) bidiOther = i;
                    return found;
                  }
                }
              }
              return found;
            }
          
            function moveInLine(line, pos, dir, byUnit) {
              if (!byUnit) return pos + dir;
              do pos += dir;
              while (pos > 0 && isExtendingChar(line.text.charAt(pos)));
              return pos;
            }
          
            // This is needed in order to move 'visually' through bi-directional
            // text -- i.e., pressing left should make the cursor go left, even
            // when in RTL text. The tricky part is the 'jumps', where RTL and
            // LTR text touch each other. This often requires the cursor offset
            // to move more than one unit, in order to visually move one unit.
            function moveVisually(line, start, dir, byUnit) {
              var bidi = getOrder(line);
              if (!bidi) return moveLogically(line, start, dir, byUnit);
              var pos = getBidiPartAt(bidi, start), part = bidi[pos];
              var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
          
              for (;;) {
                if (target > part.from && target < part.to) return target;
                if (target == part.from || target == part.to) {
                  if (getBidiPartAt(bidi, target) == pos) return target;
                  part = bidi[pos += dir];
                  return (dir > 0) == part.level % 2 ? part.to : part.from;
                } else {
                  part = bidi[pos += dir];
                  if (!part) return null;
                  if ((dir > 0) == part.level % 2)
                    target = moveInLine(line, part.to, -1, byUnit);
                  else
                    target = moveInLine(line, part.from, 1, byUnit);
                }
              }
            }
          
            function moveLogically(line, start, dir, byUnit) {
              var target = start + dir;
              if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir;
              return target < 0 || target > line.text.length ? null : target;
            }
          
            // Bidirectional ordering algorithm
            // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
            // that this (partially) implements.
          
            // One-char codes used for character types:
            // L (L):   Left-to-Right
            // R (R):   Right-to-Left
            // r (AL):  Right-to-Left Arabic
            // 1 (EN):  European Number
            // + (ES):  European Number Separator
            // % (ET):  European Number Terminator
            // n (AN):  Arabic Number
            // , (CS):  Common Number Separator
            // m (NSM): Non-Spacing Mark
            // b (BN):  Boundary Neutral
            // s (B):   Paragraph Separator
            // t (S):   Segment Separator
            // w (WS):  Whitespace
            // N (ON):  Other Neutrals
          
            // Returns null if characters are ordered as they appear
            // (left-to-right), or an array of sections ({from, to, level}
            // objects) in the order in which they occur visually.
            var bidiOrdering = (function() {
              // Character types for codepoints 0 to 0xff
              var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";
              // Character types for codepoints 0x600 to 0x6ff
              var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm";
              function charType(code) {
                if (code <= 0xf7) return lowTypes.charAt(code);
                else if (0x590 <= code && code <= 0x5f4) return "R";
                else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600);
                else if (0x6ee <= code && code <= 0x8ac) return "r";
                else if (0x2000 <= code && code <= 0x200b) return "w";
                else if (code == 0x200c) return "b";
                else return "L";
              }
          
              var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
              var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
              // Browsers seem to always treat the boundaries of block elements as being L.
              var outerType = "L";
          
              function BidiSpan(level, from, to) {
                this.level = level;
                this.from = from; this.to = to;
              }
          
              return function(str) {
                if (!bidiRE.test(str)) return false;
                var len = str.length, types = [];
                for (var i = 0, type; i < len; ++i)
                  types.push(type = charType(str.charCodeAt(i)));
          
                // W1. Examine each non-spacing mark (NSM) in the level run, and
                // change the type of the NSM to the type of the previous
                // character. If the NSM is at the start of the level run, it will
                // get the type of sor.
                for (var i = 0, prev = outerType; i < len; ++i) {
                  var type = types[i];
                  if (type == "m") types[i] = prev;
                  else prev = type;
                }
          
                // W2. Search backwards from each instance of a European number
                // until the first strong type (R, L, AL, or sor) is found. If an
                // AL is found, change the type of the European number to Arabic
                // number.
                // W3. Change all ALs to R.
                for (var i = 0, cur = outerType; i < len; ++i) {
                  var type = types[i];
                  if (type == "1" && cur == "r") types[i] = "n";
                  else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
                }
          
                // W4. A single European separator between two European numbers
                // changes to a European number. A single common separator between
                // two numbers of the same type changes to that type.
                for (var i = 1, prev = types[0]; i < len - 1; ++i) {
                  var type = types[i];
                  if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
                  else if (type == "," && prev == types[i+1] &&
                           (prev == "1" || prev == "n")) types[i] = prev;
                  prev = type;
                }
          
                // W5. A sequence of European terminators adjacent to European
                // numbers changes to all European numbers.
                // W6. Otherwise, separators and terminators change to Other
                // Neutral.
                for (var i = 0; i < len; ++i) {
                  var type = types[i];
                  if (type == ",") types[i] = "N";
                  else if (type == "%") {
                    for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
                    var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N";
                    for (var j = i; j < end; ++j) types[j] = replace;
                    i = end - 1;
                  }
                }
          
                // W7. Search backwards from each instance of a European number
                // until the first strong type (R, L, or sor) is found. If an L is
                // found, then change the type of the European number to L.
                for (var i = 0, cur = outerType; i < len; ++i) {
                  var type = types[i];
                  if (cur == "L" && type == "1") types[i] = "L";
                  else if (isStrong.test(type)) cur = type;
                }
          
                // N1. A sequence of neutrals takes the direction of the
                // surrounding strong text if the text on both sides has the same
                // direction. European and Arabic numbers act as if they were R in
                // terms of their influence on neutrals. Start-of-level-run (sor)
                // and end-of-level-run (eor) are used at level run boundaries.
                // N2. Any remaining neutrals take the embedding direction.
                for (var i = 0; i < len; ++i) {
                  if (isNeutral.test(types[i])) {
                    for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
                    var before = (i ? types[i-1] : outerType) == "L";
                    var after = (end < len ? types[end] : outerType) == "L";
                    var replace = before || after ? "L" : "R";
                    for (var j = i; j < end; ++j) types[j] = replace;
                    i = end - 1;
                  }
                }
          
                // Here we depart from the documented algorithm, in order to avoid
                // building up an actual levels array. Since there are only three
                // levels (0, 1, 2) in an implementation that doesn't take
                // explicit embedding into account, we can build up the order on
                // the fly, without following the level-based algorithm.
                var order = [], m;
                for (var i = 0; i < len;) {
                  if (countsAsLeft.test(types[i])) {
                    var start = i;
                    for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
                    order.push(new BidiSpan(0, start, i));
                  } else {
                    var pos = i, at = order.length;
                    for (++i; i < len && types[i] != "L"; ++i) {}
                    for (var j = pos; j < i;) {
                      if (countsAsNum.test(types[j])) {
                        if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j));
                        var nstart = j;
                        for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
                        order.splice(at, 0, new BidiSpan(2, nstart, j));
                        pos = j;
                      } else ++j;
                    }
                    if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i));
                  }
                }
                if (order[0].level == 1 && (m = str.match(/^\s+/))) {
                  order[0].from = m[0].length;
                  order.unshift(new BidiSpan(0, 0, m[0].length));
                }
                if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
                  lst(order).to -= m[0].length;
                  order.push(new BidiSpan(0, len - m[0].length, len));
                }
                if (order[0].level == 2)
                  order.unshift(new BidiSpan(1, order[0].to, order[0].to));
                if (order[0].level != lst(order).level)
                  order.push(new BidiSpan(order[0].level, len, len));
          
                return order;
              };
            })();
          
            // THE END
          
            CodeMirror.version = "5.2.1";
          
            return CodeMirror;
          });
          
      • mode
        • apl
          • apl.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("apl", function() {
              var builtInOps = {
                ".": "innerProduct",
                "\\": "scan",
                "/": "reduce",
                "⌿": "reduce1Axis",
                "⍀": "scan1Axis",
                "¨": "each",
                "⍣": "power"
              };
              var builtInFuncs = {
                "+": ["conjugate", "add"],
                "−": ["negate", "subtract"],
                "×": ["signOf", "multiply"],
                "÷": ["reciprocal", "divide"],
                "⌈": ["ceiling", "greaterOf"],
                "⌊": ["floor", "lesserOf"],
                "∣": ["absolute", "residue"],
                "⍳": ["indexGenerate", "indexOf"],
                "?": ["roll", "deal"],
                "⋆": ["exponentiate", "toThePowerOf"],
                "⍟": ["naturalLog", "logToTheBase"],
                "○": ["piTimes", "circularFuncs"],
                "!": ["factorial", "binomial"],
                "⌹": ["matrixInverse", "matrixDivide"],
                "<": [null, "lessThan"],
                "≤": [null, "lessThanOrEqual"],
                "=": [null, "equals"],
                ">": [null, "greaterThan"],
                "≥": [null, "greaterThanOrEqual"],
                "≠": [null, "notEqual"],
                "≡": ["depth", "match"],
                "≢": [null, "notMatch"],
                "∈": ["enlist", "membership"],
                "⍷": [null, "find"],
                "∪": ["unique", "union"],
                "∩": [null, "intersection"],
                "∼": ["not", "without"],
                "∨": [null, "or"],
                "∧": [null, "and"],
                "⍱": [null, "nor"],
                "⍲": [null, "nand"],
                "⍴": ["shapeOf", "reshape"],
                ",": ["ravel", "catenate"],
                "⍪": [null, "firstAxisCatenate"],
                "⌽": ["reverse", "rotate"],
                "⊖": ["axis1Reverse", "axis1Rotate"],
                "⍉": ["transpose", null],
                "↑": ["first", "take"],
                "↓": [null, "drop"],
                "⊂": ["enclose", "partitionWithAxis"],
                "⊃": ["diclose", "pick"],
                "⌷": [null, "index"],
                "⍋": ["gradeUp", null],
                "⍒": ["gradeDown", null],
                "⊤": ["encode", null],
                "⊥": ["decode", null],
                "⍕": ["format", "formatByExample"],
                "⍎": ["execute", null],
                "⊣": ["stop", "left"],
                "⊢": ["pass", "right"]
              };
            
              var isOperator = /[\.\/⌿⍀¨⍣]/;
              var isNiladic = /⍬/;
              var isFunction = /[\+−×÷⌈⌊∣⍳\?⋆⍟○!⌹<≤=>≥≠≡≢∈⍷∪∩∼∨∧⍱⍲⍴,⍪⌽⊖⍉↑↓⊂⊃⌷⍋⍒⊤⊥⍕⍎⊣⊢]/;
              var isArrow = /←/;
              var isComment = /[⍝#].*$/;
            
              var stringEater = function(type) {
                var prev;
                prev = false;
                return function(c) {
                  prev = c;
                  if (c === type) {
                    return prev === "\\";
                  }
                  return true;
                };
              };
              return {
                startState: function() {
                  return {
                    prev: false,
                    func: false,
                    op: false,
                    string: false,
                    escape: false
                  };
                },
                token: function(stream, state) {
                  var ch, funcName;
                  if (stream.eatSpace()) {
                    return null;
                  }
                  ch = stream.next();
                  if (ch === '"' || ch === "'") {
                    stream.eatWhile(stringEater(ch));
                    stream.next();
                    state.prev = true;
                    return "string";
                  }
                  if (/[\[{\(]/.test(ch)) {
                    state.prev = false;
                    return null;
                  }
                  if (/[\]}\)]/.test(ch)) {
                    state.prev = true;
                    return null;
                  }
                  if (isNiladic.test(ch)) {
                    state.prev = false;
                    return "niladic";
                  }
                  if (/[¯\d]/.test(ch)) {
                    if (state.func) {
                      state.func = false;
                      state.prev = false;
                    } else {
                      state.prev = true;
                    }
                    stream.eatWhile(/[\w\.]/);
                    return "number";
                  }
                  if (isOperator.test(ch)) {
                    return "operator apl-" + builtInOps[ch];
                  }
                  if (isArrow.test(ch)) {
                    return "apl-arrow";
                  }
                  if (isFunction.test(ch)) {
                    funcName = "apl-";
                    if (builtInFuncs[ch] != null) {
                      if (state.prev) {
                        funcName += builtInFuncs[ch][1];
                      } else {
                        funcName += builtInFuncs[ch][0];
                      }
                    }
                    state.func = true;
                    state.prev = false;
                    return "function " + funcName;
                  }
                  if (isComment.test(ch)) {
                    stream.skipToEnd();
                    return "comment";
                  }
                  if (ch === "∘" && stream.peek() === ".") {
                    stream.next();
                    return "function jot-dot";
                  }
                  stream.eatWhile(/[\w\$_]/);
                  state.prev = true;
                  return "keyword";
                }
              };
            });
            
            CodeMirror.defineMIME("text/apl", "apl");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: APL mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="./apl.js"></script>
            <style>
            	.CodeMirror { border: 2px inset #dee; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">APL</a>
              </ul>
            </div>
            
            <article>
            <h2>APL mode</h2>
            <form><textarea id="code" name="code">
            ⍝ Conway's game of life
            
            ⍝ This example was inspired by the impressive demo at
            ⍝ http://www.youtube.com/watch?v=a9xAKttWgP4
            
            ⍝ Create a matrix:
            ⍝     0 1 1
            ⍝     1 1 0
            ⍝     0 1 0
            creature ← (3 3 ⍴ ⍳ 9) ∈ 1 2 3 4 7   ⍝ Original creature from demo
            creature ← (3 3 ⍴ ⍳ 9) ∈ 1 3 6 7 8   ⍝ Glider
            
            ⍝ Place the creature on a larger board, near the centre
            board ← ¯1 ⊖ ¯2 ⌽ 5 7 ↑ creature
            
            ⍝ A function to move from one generation to the next
            life ← {∨/ 1 ⍵ ∧ 3 4 = ⊂+/ +⌿ 1 0 ¯1 ∘.⊖ 1 0 ¯1 ⌽¨ ⊂⍵}
            
            ⍝ Compute n-th generation and format it as a
            ⍝ character matrix
            gen ← {' #'[(life ⍣ ⍵) board]}
            
            ⍝ Show first three generations
            (gen 1) (gen 2) (gen 3)
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/apl"
                  });
                </script>
            
                <p>Simple mode that tries to handle APL as well as it can.</p>
                <p>It attempts to label functions/operators based upon
                monadic/dyadic usage (but this is far from fully fleshed out).
                This means there are meaningful classnames so hover states can
                have popups etc.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/apl</code> (APL code)</p>
              </article>
            
        • asciiarmor
          • asciiarmor.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              function errorIfNotEmpty(stream) {
                var nonWS = stream.match(/^\s*\S/);
                stream.skipToEnd();
                return nonWS ? "error" : null;
              }
            
              CodeMirror.defineMode("asciiarmor", function() {
                return {
                  token: function(stream, state) {
                    var m;
                    if (state.state == "top") {
                      if (stream.sol() && (m = stream.match(/^-----BEGIN (.*)?-----\s*$/))) {
                        state.state = "headers";
                        state.type = m[1];
                        return "tag";
                      }
                      return errorIfNotEmpty(stream);
                    } else if (state.state == "headers") {
                      if (stream.sol() && stream.match(/^\w+:/)) {
                        state.state = "header";
                        return "atom";
                      } else {
                        var result = errorIfNotEmpty(stream);
                        if (result) state.state = "body";
                        return result;
                      }
                    } else if (state.state == "header") {
                      stream.skipToEnd();
                      state.state = "headers";
                      return "string";
                    } else if (state.state == "body") {
                      if (stream.sol() && (m = stream.match(/^-----END (.*)?-----\s*$/))) {
                        if (m[1] != state.type) return "error";
                        state.state = "end";
                        return "tag";
                      } else {
                        if (stream.eatWhile(/[A-Za-z0-9+\/=]/)) {
                          return null;
                        } else {
                          stream.next();
                          return "error";
                        }
                      }
                    } else if (state.state == "end") {
                      return errorIfNotEmpty(stream);
                    }
                  },
                  blankLine: function(state) {
                    if (state.state == "headers") state.state = "body";
                  },
                  startState: function() {
                    return {state: "top", type: null};
                  }
                };
              });
            
              CodeMirror.defineMIME("application/pgp", "asciiarmor");
              CodeMirror.defineMIME("application/pgp-keys", "asciiarmor");
              CodeMirror.defineMIME("application/pgp-signature", "asciiarmor");
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: ASCII Armor (PGP) mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="asciiarmor.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">ASCII Armor</a>
              </ul>
            </div>
            
            <article>
            <h2>ASCII Armor (PGP) mode</h2>
            <form><textarea id="code" name="code">
            -----BEGIN PGP MESSAGE-----
            Version: OpenPrivacy 0.99
            
            yDgBO22WxBHv7O8X7O/jygAEzol56iUKiXmV+XmpCtmpqQUKiQrFqclFqUDBovzS
            vBSFjNSiVHsuAA==
            =njUN
            -----END PGP MESSAGE-----
            </textarea></form>
            
            <script>
            var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
              lineNumbers: true
            });
            </script>
            
            <p><strong>MIME types
            defined:</strong> <code>application/pgp</code>, <code>application/pgp-keys</code>, <code>application/pgp-signature</code></p>
            
            </article>
            
        • asn.1
          • asn.1.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("asn.1", function(config, parserConfig) {
                var indentUnit = config.indentUnit,
                    keywords = parserConfig.keywords || {},
                    cmipVerbs = parserConfig.cmipVerbs || {},
                    compareTypes = parserConfig.compareTypes || {},
                    status = parserConfig.status || {},
                    tags = parserConfig.tags || {},
                    storage = parserConfig.storage || {},
                    modifier = parserConfig.modifier || {},
                    accessTypes = parserConfig.accessTypes|| {},
                    multiLineStrings = parserConfig.multiLineStrings,
                    indentStatements = parserConfig.indentStatements !== false;
                var isOperatorChar = /[\|\^]/;
                var curPunc;
            
                function tokenBase(stream, state) {
                  var ch = stream.next();
                  if (ch == '"' || ch == "'") {
                    state.tokenize = tokenString(ch);
                    return state.tokenize(stream, state);
                  }
                  if (/[\[\]\(\){}:=,;]/.test(ch)) {
                    curPunc = ch;
                    return "punctuation";
                  }
                  if (ch == "-"){
                    if (stream.eat("-")) {
                      stream.skipToEnd();
                      return "comment";
                    }
                  }
                  if (/\d/.test(ch)) {
                    stream.eatWhile(/[\w\.]/);
                    return "number";
                  }
                  if (isOperatorChar.test(ch)) {
                    stream.eatWhile(isOperatorChar);
                    return "operator";
                  }
            
                  stream.eatWhile(/[\w\-]/);
                  var cur = stream.current();
                  if (keywords.propertyIsEnumerable(cur)) return "keyword";
                  if (cmipVerbs.propertyIsEnumerable(cur)) return "variable cmipVerbs";
                  if (compareTypes.propertyIsEnumerable(cur)) return "atom compareTypes";
                  if (status.propertyIsEnumerable(cur)) return "comment status";
                  if (tags.propertyIsEnumerable(cur)) return "variable-3 tags";
                  if (storage.propertyIsEnumerable(cur)) return "builtin storage";
                  if (modifier.propertyIsEnumerable(cur)) return "string-2 modifier";
                  if (accessTypes.propertyIsEnumerable(cur)) return "atom accessTypes";
            
                  return "variable";
                }
            
                function tokenString(quote) {
                  return function(stream, state) {
                    var escaped = false, next, end = false;
                    while ((next = stream.next()) != null) {
                      if (next == quote && !escaped){
                        var afterNext = stream.peek();
                        //look if the character if the quote is like the B in '10100010'B
                        if (afterNext){
                          afterNext = afterNext.toLowerCase();
                          if(afterNext == "b" || afterNext == "h" || afterNext == "o")
                            stream.next();
                        }
                        end = true; break;
                      }
                      escaped = !escaped && next == "\\";
                    }
                    if (end || !(escaped || multiLineStrings))
                      state.tokenize = null;
                    return "string";
                  };
                }
            
                function Context(indented, column, type, align, prev) {
                  this.indented = indented;
                  this.column = column;
                  this.type = type;
                  this.align = align;
                  this.prev = prev;
                }
                function pushContext(state, col, type) {
                  var indent = state.indented;
                  if (state.context && state.context.type == "statement")
                    indent = state.context.indented;
                  return state.context = new Context(indent, col, type, null, state.context);
                }
                function popContext(state) {
                  var t = state.context.type;
                  if (t == ")" || t == "]" || t == "}")
                    state.indented = state.context.indented;
                  return state.context = state.context.prev;
                }
            
                //Interface
                return {
                  startState: function(basecolumn) {
                    return {
                      tokenize: null,
                      context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
                      indented: 0,
                      startOfLine: true
                    };
                  },
            
                  token: function(stream, state) {
                    var ctx = state.context;
                    if (stream.sol()) {
                      if (ctx.align == null) ctx.align = false;
                      state.indented = stream.indentation();
                      state.startOfLine = true;
                    }
                    if (stream.eatSpace()) return null;
                    curPunc = null;
                    var style = (state.tokenize || tokenBase)(stream, state);
                    if (style == "comment") return style;
                    if (ctx.align == null) ctx.align = true;
            
                    if ((curPunc == ";" || curPunc == ":" || curPunc == ",")
                        && ctx.type == "statement"){
                      popContext(state);
                    }
                    else if (curPunc == "{") pushContext(state, stream.column(), "}");
                    else if (curPunc == "[") pushContext(state, stream.column(), "]");
                    else if (curPunc == "(") pushContext(state, stream.column(), ")");
                    else if (curPunc == "}") {
                      while (ctx.type == "statement") ctx = popContext(state);
                      if (ctx.type == "}") ctx = popContext(state);
                      while (ctx.type == "statement") ctx = popContext(state);
                    }
                    else if (curPunc == ctx.type) popContext(state);
                    else if (indentStatements && (((ctx.type == "}" || ctx.type == "top")
                        && curPunc != ';') || (ctx.type == "statement"
                        && curPunc == "newstatement")))
                      pushContext(state, stream.column(), "statement");
            
                    state.startOfLine = false;
                    return style;
                  },
            
                  electricChars: "{}",
                  lineComment: "--",
                  fold: "brace"
                };
              });
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              CodeMirror.defineMIME("text/x-ttcn-asn", {
                name: "asn.1",
                keywords: words("DEFINITIONS OBJECTS IF DERIVED INFORMATION ACTION" +
                " REPLY ANY NAMED CHARACTERIZED BEHAVIOUR REGISTERED" +
                " WITH AS IDENTIFIED CONSTRAINED BY PRESENT BEGIN" +
                " IMPORTS FROM UNITS SYNTAX MIN-ACCESS MAX-ACCESS" +
                " MINACCESS MAXACCESS REVISION STATUS DESCRIPTION" +
                " SEQUENCE SET COMPONENTS OF CHOICE DistinguishedName" +
                " ENUMERATED SIZE MODULE END INDEX AUGMENTS EXTENSIBILITY" +
                " IMPLIED EXPORTS"),
                cmipVerbs: words("ACTIONS ADD GET NOTIFICATIONS REPLACE REMOVE"),
                compareTypes: words("OPTIONAL DEFAULT MANAGED MODULE-TYPE MODULE_IDENTITY" +
                " MODULE-COMPLIANCE OBJECT-TYPE OBJECT-IDENTITY" +
                " OBJECT-COMPLIANCE MODE CONFIRMED CONDITIONAL" +
                " SUBORDINATE SUPERIOR CLASS TRUE FALSE NULL" +
                " TEXTUAL-CONVENTION"),
                status: words("current deprecated mandatory obsolete"),
                tags: words("APPLICATION AUTOMATIC EXPLICIT IMPLICIT PRIVATE TAGS" +
                " UNIVERSAL"),
                storage: words("BOOLEAN INTEGER OBJECT IDENTIFIER BIT OCTET STRING" +
                " UTCTime InterfaceIndex IANAifType CMIP-Attribute" +
                " REAL PACKAGE PACKAGES IpAddress PhysAddress" +
                " NetworkAddress BITS BMPString TimeStamp TimeTicks" +
                " TruthValue RowStatus DisplayString GeneralString" +
                " GraphicString IA5String NumericString" +
                " PrintableString SnmpAdminAtring TeletexString" +
                " UTF8String VideotexString VisibleString StringStore" +
                " ISO646String T61String UniversalString Unsigned32" +
                " Integer32 Gauge Gauge32 Counter Counter32 Counter64"),
                modifier: words("ATTRIBUTE ATTRIBUTES MANDATORY-GROUP MANDATORY-GROUPS" +
                " GROUP GROUPS ELEMENTS EQUALITY ORDERING SUBSTRINGS" +
                " DEFINED"),
                accessTypes: words("not-accessible accessible-for-notify read-only" +
                " read-create read-write"),
                multiLineStrings: true
              });
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: ASN.1 mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="asn.1.js"></script>
            <style type="text/css">
                .CodeMirror {
                    border-top: 1px solid black;
                    border-bottom: 1px solid black;
                }
            </style>
            <div id=nav>
                <a href="http://codemirror.net"><h1>CodeMirror</h1>
                    <img id=logo src="../../doc/logo.png">
                </a>
            
                <ul>
                    <li><a href="../../index.html">Home</a>
                    <li><a href="../../doc/manual.html">Manual</a>
                    <li><a href="https://github.com/codemirror/codemirror">Code</a>
                </ul>
                <ul>
                    <li><a href="../index.html">Language modes</a>
                    <li><a class=active href="http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One">ASN.1</a>
                </ul>
            </div>
            <article>
                <h2>ASN.1 example</h2>
                <div>
                    <textarea id="ttcn-asn-code">
             --
             -- Sample ASN.1 Code
             --
             MyModule DEFINITIONS ::=
             BEGIN
            
             MyTypes ::= SEQUENCE {
                 myObjectId   OBJECT IDENTIFIER,
                 mySeqOf      SEQUENCE OF MyInt,
                 myBitString  BIT STRING {
                                     muxToken(0),
                                     modemToken(1)
                              }
             }
            
             MyInt ::= INTEGER (0..65535)
            
             END
                    </textarea>
                </div>
            
                <script>
                    var ttcnEditor = CodeMirror.fromTextArea(document.getElementById("ttcn-asn-code"), {
                        lineNumbers: true,
                        matchBrackets: true,
                        mode: "text/x-ttcn-asn"
                    });
                    ttcnEditor.setSize(400, 400);
                    var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
                    CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
                </script>
                <br/>
                <p><strong>Language:</strong> Abstract Syntax Notation One
                    (<a href="http://www.itu.int/en/ITU-T/asn1/Pages/introduction.aspx">ASN.1</a>)
                </p>
                <p><strong>MIME types defined:</strong> <code>text/x-ttcn-asn</code></p>
            
                <br/>
                <p>The development of this mode has been sponsored by <a href="http://www.ericsson.com/">Ericsson
                </a>.</p>
                <p>Coded by Asmelash Tsegay Gebretsadkan </p>
                </article>
            </article>
            
            
        • asterisk
          • asterisk.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*
             * =====================================================================================
             *
             *       Filename:  mode/asterisk/asterisk.js
             *
             *    Description:  CodeMirror mode for Asterisk dialplan
             *
             *        Created:  05/17/2012 09:20:25 PM
             *       Revision:  none
             *
             *         Author:  Stas Kobzar (stas@modulis.ca),
             *        Company:  Modulis.ca Inc.
             *
             * =====================================================================================
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("asterisk", function() {
              var atoms    = ["exten", "same", "include","ignorepat","switch"],
                  dpcmd    = ["#include","#exec"],
                  apps     = [
                              "addqueuemember","adsiprog","aelsub","agentlogin","agentmonitoroutgoing","agi",
                              "alarmreceiver","amd","answer","authenticate","background","backgrounddetect",
                              "bridge","busy","callcompletioncancel","callcompletionrequest","celgenuserevent",
                              "changemonitor","chanisavail","channelredirect","chanspy","clearhash","confbridge",
                              "congestion","continuewhile","controlplayback","dahdiacceptr2call","dahdibarge",
                              "dahdiras","dahdiscan","dahdisendcallreroutingfacility","dahdisendkeypadfacility",
                              "datetime","dbdel","dbdeltree","deadagi","dial","dictate","directory","disa",
                              "dumpchan","eagi","echo","endwhile","exec","execif","execiftime","exitwhile","extenspy",
                              "externalivr","festival","flash","followme","forkcdr","getcpeid","gosub","gosubif",
                              "goto","gotoif","gotoiftime","hangup","iax2provision","ices","importvar","incomplete",
                              "ivrdemo","jabberjoin","jabberleave","jabbersend","jabbersendgroup","jabberstatus",
                              "jack","log","macro","macroexclusive","macroexit","macroif","mailboxexists","meetme",
                              "meetmeadmin","meetmechanneladmin","meetmecount","milliwatt","minivmaccmess","minivmdelete",
                              "minivmgreet","minivmmwi","minivmnotify","minivmrecord","mixmonitor","monitor","morsecode",
                              "mp3player","mset","musiconhold","nbscat","nocdr","noop","odbc","odbc","odbcfinish",
                              "originate","ospauth","ospfinish","osplookup","ospnext","page","park","parkandannounce",
                              "parkedcall","pausemonitor","pausequeuemember","pickup","pickupchan","playback","playtones",
                              "privacymanager","proceeding","progress","queue","queuelog","raiseexception","read","readexten",
                              "readfile","receivefax","receivefax","receivefax","record","removequeuemember",
                              "resetcdr","retrydial","return","ringing","sayalpha","saycountedadj","saycountednoun",
                              "saycountpl","saydigits","saynumber","sayphonetic","sayunixtime","senddtmf","sendfax",
                              "sendfax","sendfax","sendimage","sendtext","sendurl","set","setamaflags",
                              "setcallerpres","setmusiconhold","sipaddheader","sipdtmfmode","sipremoveheader","skel",
                              "slastation","slatrunk","sms","softhangup","speechactivategrammar","speechbackground",
                              "speechcreate","speechdeactivategrammar","speechdestroy","speechloadgrammar","speechprocessingsound",
                              "speechstart","speechunloadgrammar","stackpop","startmusiconhold","stopmixmonitor","stopmonitor",
                              "stopmusiconhold","stopplaytones","system","testclient","testserver","transfer","tryexec",
                              "trysystem","unpausemonitor","unpausequeuemember","userevent","verbose","vmauthenticate",
                              "vmsayname","voicemail","voicemailmain","wait","waitexten","waitfornoise","waitforring",
                              "waitforsilence","waitmusiconhold","waituntil","while","zapateller"
                             ];
            
              function basicToken(stream,state){
                var cur = '';
                var ch = stream.next();
                // comment
                if(ch == ";") {
                  stream.skipToEnd();
                  return "comment";
                }
                // context
                if(ch == '[') {
                  stream.skipTo(']');
                  stream.eat(']');
                  return "header";
                }
                // string
                if(ch == '"') {
                  stream.skipTo('"');
                  return "string";
                }
                if(ch == "'") {
                  stream.skipTo("'");
                  return "string-2";
                }
                // dialplan commands
                if(ch == '#') {
                  stream.eatWhile(/\w/);
                  cur = stream.current();
                  if(dpcmd.indexOf(cur) !== -1) {
                    stream.skipToEnd();
                    return "strong";
                  }
                }
                // application args
                if(ch == '$'){
                  var ch1 = stream.peek();
                  if(ch1 == '{'){
                    stream.skipTo('}');
                    stream.eat('}');
                    return "variable-3";
                  }
                }
                // extension
                stream.eatWhile(/\w/);
                cur = stream.current();
                if(atoms.indexOf(cur) !== -1) {
                  state.extenStart = true;
                  switch(cur) {
                    case 'same': state.extenSame = true; break;
                    case 'include':
                    case 'switch':
                    case 'ignorepat':
                      state.extenInclude = true;break;
                    default:break;
                  }
                  return "atom";
                }
              }
            
              return {
                startState: function() {
                  return {
                    extenStart: false,
                    extenSame:  false,
                    extenInclude: false,
                    extenExten: false,
                    extenPriority: false,
                    extenApplication: false
                  };
                },
                token: function(stream, state) {
            
                  var cur = '';
                  if(stream.eatSpace()) return null;
                  // extension started
                  if(state.extenStart){
                    stream.eatWhile(/[^\s]/);
                    cur = stream.current();
                    if(/^=>?$/.test(cur)){
                      state.extenExten = true;
                      state.extenStart = false;
                      return "strong";
                    } else {
                      state.extenStart = false;
                      stream.skipToEnd();
                      return "error";
                    }
                  } else if(state.extenExten) {
                    // set exten and priority
                    state.extenExten = false;
                    state.extenPriority = true;
                    stream.eatWhile(/[^,]/);
                    if(state.extenInclude) {
                      stream.skipToEnd();
                      state.extenPriority = false;
                      state.extenInclude = false;
                    }
                    if(state.extenSame) {
                      state.extenPriority = false;
                      state.extenSame = false;
                      state.extenApplication = true;
                    }
                    return "tag";
                  } else if(state.extenPriority) {
                    state.extenPriority = false;
                    state.extenApplication = true;
                    stream.next(); // get comma
                    if(state.extenSame) return null;
                    stream.eatWhile(/[^,]/);
                    return "number";
                  } else if(state.extenApplication) {
                    stream.eatWhile(/,/);
                    cur = stream.current();
                    if(cur === ',') return null;
                    stream.eatWhile(/\w/);
                    cur = stream.current().toLowerCase();
                    state.extenApplication = false;
                    if(apps.indexOf(cur) !== -1){
                      return "def strong";
                    }
                  } else{
                    return basicToken(stream,state);
                  }
            
                  return null;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-asterisk", "asterisk");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Asterisk dialplan mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="asterisk.js"></script>
            <style>
                  .CodeMirror {border: 1px solid #999;}
                  .cm-s-default span.cm-arrow { color: red; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Asterisk dialplan</a>
              </ul>
            </div>
            
            <article>
            <h2>Asterisk dialplan mode</h2>
            <form><textarea id="code" name="code">
            ; extensions.conf - the Asterisk dial plan
            ;
            
            [general]
            ;
            ; If static is set to no, or omitted, then the pbx_config will rewrite
            ; this file when extensions are modified.  Remember that all comments
            ; made in the file will be lost when that happens.
            static=yes
            
            #include "/etc/asterisk/additional_general.conf
            
            [iaxprovider]
            switch => IAX2/user:[key]@myserver/mycontext
            
            [dynamic]
            #exec /usr/bin/dynamic-peers.pl
            
            [trunkint]
            ;
            ; International long distance through trunk
            ;
            exten => _9011.,1,Macro(dundi-e164,${EXTEN:4})
            exten => _9011.,n,Dial(${GLOBAL(TRUNK)}/${FILTER(0-9,${EXTEN:${GLOBAL(TRUNKMSD)}})})
            
            [local]
            ;
            ; Master context for local, toll-free, and iaxtel calls only
            ;
            ignorepat => 9
            include => default
            
            [demo]
            include => stdexten
            ;
            ; We start with what to do when a call first comes in.
            ;
            exten => s,1,Wait(1)			; Wait a second, just for fun
            same  => n,Answer			; Answer the line
            same  => n,Set(TIMEOUT(digit)=5)	; Set Digit Timeout to 5 seconds
            same  => n,Set(TIMEOUT(response)=10)	; Set Response Timeout to 10 seconds
            same  => n(restart),BackGround(demo-congrats)	; Play a congratulatory message
            same  => n(instruct),BackGround(demo-instruct)	; Play some instructions
            same  => n,WaitExten			; Wait for an extension to be dialed.
            
            exten => 2,1,BackGround(demo-moreinfo)	; Give some more information.
            exten => 2,n,Goto(s,instruct)
            
            exten => 3,1,Set(LANGUAGE()=fr)		; Set language to french
            exten => 3,n,Goto(s,restart)		; Start with the congratulations
            
            exten => 1000,1,Goto(default,s,1)
            ;
            ; We also create an example user, 1234, who is on the console and has
            ; voicemail, etc.
            ;
            exten => 1234,1,Playback(transfer,skip)		; "Please hold while..."
            					; (but skip if channel is not up)
            exten => 1234,n,Gosub(${EXTEN},stdexten(${GLOBAL(CONSOLE)}))
            exten => 1234,n,Goto(default,s,1)		; exited Voicemail
            
            exten => 1235,1,Voicemail(1234,u)		; Right to voicemail
            
            exten => 1236,1,Dial(Console/dsp)		; Ring forever
            exten => 1236,n,Voicemail(1234,b)		; Unless busy
            
            ;
            ; # for when they're done with the demo
            ;
            exten => #,1,Playback(demo-thanks)	; "Thanks for trying the demo"
            exten => #,n,Hangup			; Hang them up.
            
            ;
            ; A timeout and "invalid extension rule"
            ;
            exten => t,1,Goto(#,1)			; If they take too long, give up
            exten => i,1,Playback(invalid)		; "That's not valid, try again"
            
            ;
            ; Create an extension, 500, for dialing the
            ; Asterisk demo.
            ;
            exten => 500,1,Playback(demo-abouttotry); Let them know what's going on
            exten => 500,n,Dial(IAX2/guest@pbx.digium.com/s@default)	; Call the Asterisk demo
            exten => 500,n,Playback(demo-nogo)	; Couldn't connect to the demo site
            exten => 500,n,Goto(s,6)		; Return to the start over message.
            
            ;
            ; Create an extension, 600, for evaluating echo latency.
            ;
            exten => 600,1,Playback(demo-echotest)	; Let them know what's going on
            exten => 600,n,Echo			; Do the echo test
            exten => 600,n,Playback(demo-echodone)	; Let them know it's over
            exten => 600,n,Goto(s,6)		; Start over
            
            ;
            ;	You can use the Macro Page to intercom a individual user
            exten => 76245,1,Macro(page,SIP/Grandstream1)
            ; or if your peernames are the same as extensions
            exten => _7XXX,1,Macro(page,SIP/${EXTEN})
            ;
            ;
            ; System Wide Page at extension 7999
            ;
            exten => 7999,1,Set(TIMEOUT(absolute)=60)
            exten => 7999,2,Page(Local/Grandstream1@page&Local/Xlite1@page&Local/1234@page/n,d)
            
            ; Give voicemail at extension 8500
            ;
            exten => 8500,1,VoicemailMain
            exten => 8500,n,Goto(s,6)
            
                </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/x-asterisk",
                    matchBrackets: true,
                    lineNumber: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-asterisk</code>.</p>
            
              </article>
            
        • clike
          • clike.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("clike", function(config, parserConfig) {
              var indentUnit = config.indentUnit,
                  statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
                  dontAlignCalls = parserConfig.dontAlignCalls,
                  keywords = parserConfig.keywords || {},
                  builtin = parserConfig.builtin || {},
                  blockKeywords = parserConfig.blockKeywords || {},
                  atoms = parserConfig.atoms || {},
                  hooks = parserConfig.hooks || {},
                  multiLineStrings = parserConfig.multiLineStrings,
                  indentStatements = parserConfig.indentStatements !== false,
                  indentSwitch = parserConfig.indentSwitch !== false;
              var isOperatorChar = /[+\-*&%=<>!?|\/]/;
            
              var curPunc;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (hooks[ch]) {
                  var result = hooks[ch](stream, state);
                  if (result !== false) return result;
                }
                if (ch == '"' || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return "number";
                }
                if (ch == "/") {
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment;
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                }
                if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_\xa1-\uffff]/);
                var cur = stream.current();
                if (keywords.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "keyword";
                }
                if (builtin.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "builtin";
                }
                if (atoms.propertyIsEnumerable(cur)) return "atom";
                return "variable";
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {end = true; break;}
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !(escaped || multiLineStrings))
                    state.tokenize = null;
                  return "string";
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = null;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
              function isStatement(context) {
                return context.type == "statement" || context.type == "switchstatement";
              }
              function pushContext(state, col, type) {
                var indent = state.indented;
                if (state.context && isStatement(state.context))
                  indent = state.context.indented;
                return state.context = new Context(indent, col, type, null, state.context);
              }
              function popContext(state) {
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}")
                  state.indented = state.context.indented;
                return state.context = state.context.prev;
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                  return {
                    tokenize: null,
                    context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true
                  };
                },
            
                token: function(stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                  }
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment" || style == "meta") return style;
                  if (ctx.align == null) ctx.align = true;
            
                  if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && isStatement(ctx)) popContext(state);
                  else if (curPunc == "{") pushContext(state, stream.column(), "}");
                  else if (curPunc == "[") pushContext(state, stream.column(), "]");
                  else if (curPunc == "(") pushContext(state, stream.column(), ")");
                  else if (curPunc == "}") {
                    while (isStatement(ctx)) ctx = popContext(state);
                    if (ctx.type == "}") ctx = popContext(state);
                    while (isStatement(ctx)) ctx = popContext(state);
                  }
                  else if (curPunc == ctx.type) popContext(state);
                  else if (indentStatements &&
                           (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') ||
                            (isStatement(ctx) && curPunc == "newstatement"))) {
                    var type = "statement"
                    if (curPunc == "newstatement" && indentSwitch && stream.current() == "switch")
                      type = "switchstatement"
                    pushContext(state, stream.column(), type);
                  }
                  state.startOfLine = false;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
                  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
                  if (isStatement(ctx) && firstChar == "}") ctx = ctx.prev;
                  var closing = firstChar == ctx.type;
                  var switchBlock = ctx.prev && ctx.prev.type == "switchstatement";
                  if (isStatement(ctx))
                    return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
                  if (ctx.align && (!dontAlignCalls || ctx.type != ")"))
                    return ctx.column + (closing ? 0 : 1);
                  if (ctx.type == ")" && !closing)
                    return ctx.indented + statementIndentUnit;
            
                  return ctx.indented + (closing ? 0 : indentUnit) +
                    (!closing && switchBlock && !/^(?:case|default)\b/.test(textAfter) ? indentUnit : 0);
                },
            
                electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{|\})$/ : /^\s*[{}]$/,
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                lineComment: "//",
                fold: "brace"
              };
            });
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
              var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
                "double static else struct switch extern typedef float union for unsigned " +
                "goto while enum void const signed volatile";
            
              function cppHook(stream, state) {
                if (!state.startOfLine) return false;
                for (;;) {
                  if (stream.skipTo("\\")) {
                    stream.next();
                    if (stream.eol()) {
                      state.tokenize = cppHook;
                      break;
                    }
                  } else {
                    stream.skipToEnd();
                    state.tokenize = null;
                    break;
                  }
                }
                return "meta";
              }
            
              function cpp11StringHook(stream, state) {
                stream.backUp(1);
                // Raw strings.
                if (stream.match(/(R|u8R|uR|UR|LR)/)) {
                  var match = stream.match(/"([^\s\\()]{0,16})\(/);
                  if (!match) {
                    return false;
                  }
                  state.cpp11RawStringDelim = match[1];
                  state.tokenize = tokenRawString;
                  return tokenRawString(stream, state);
                }
                // Unicode strings/chars.
                if (stream.match(/(u8|u|U|L)/)) {
                  if (stream.match(/["']/, /* eat */ false)) {
                    return "string";
                  }
                  return false;
                }
                // Ignore this hook.
                stream.next();
                return false;
              }
            
              // C#-style strings where "" escapes a quote.
              function tokenAtString(stream, state) {
                var next;
                while ((next = stream.next()) != null) {
                  if (next == '"' && !stream.eat('"')) {
                    state.tokenize = null;
                    break;
                  }
                }
                return "string";
              }
            
              // C++11 raw string literal is <prefix>"<delim>( anything )<delim>", where
              // <delim> can be a string up to 16 characters long.
              function tokenRawString(stream, state) {
                // Escape characters that have special regex meanings.
                var delim = state.cpp11RawStringDelim.replace(/[^\w\s]/g, '\\$&');
                var match = stream.match(new RegExp(".*?\\)" + delim + '"'));
                if (match)
                  state.tokenize = null;
                else
                  stream.skipToEnd();
                return "string";
              }
            
              function def(mimes, mode) {
                if (typeof mimes == "string") mimes = [mimes];
                var words = [];
                function add(obj) {
                  if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))
                    words.push(prop);
                }
                add(mode.keywords);
                add(mode.builtin);
                add(mode.atoms);
                if (words.length) {
                  mode.helperType = mimes[0];
                  CodeMirror.registerHelper("hintWords", mimes[0], words);
                }
            
                for (var i = 0; i < mimes.length; ++i)
                  CodeMirror.defineMIME(mimes[i], mode);
              }
            
              def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
                name: "clike",
                keywords: words(cKeywords),
                blockKeywords: words("case do else for if switch while struct"),
                atoms: words("null"),
                hooks: {"#": cppHook},
                modeProps: {fold: ["brace", "include"]}
              });
            
              def(["text/x-c++src", "text/x-c++hdr"], {
                name: "clike",
                keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
                                "static_cast typeid catch operator template typename class friend private " +
                                "this using const_cast inline public throw virtual delete mutable protected " +
                                "wchar_t alignas alignof constexpr decltype nullptr noexcept thread_local final " +
                                "static_assert override"),
                blockKeywords: words("catch class do else finally for if struct switch try while"),
                atoms: words("true false null"),
                hooks: {
                  "#": cppHook,
                  "u": cpp11StringHook,
                  "U": cpp11StringHook,
                  "L": cpp11StringHook,
                  "R": cpp11StringHook
                },
                modeProps: {fold: ["brace", "include"]}
              });
            
              def("text/x-java", {
                name: "clike",
                keywords: words("abstract assert boolean break byte case catch char class const continue default " +
                                "do double else enum extends final finally float for goto if implements import " +
                                "instanceof int interface long native new package private protected public " +
                                "return short static strictfp super switch synchronized this throw throws transient " +
                                "try void volatile while"),
                blockKeywords: words("catch class do else finally for if switch try while"),
                atoms: words("true false null"),
                hooks: {
                  "@": function(stream) {
                    stream.eatWhile(/[\w\$_]/);
                    return "meta";
                  }
                },
                modeProps: {fold: ["brace", "import"]}
              });
            
              def("text/x-csharp", {
                name: "clike",
                keywords: words("abstract as base break case catch checked class const continue" +
                                " default delegate do else enum event explicit extern finally fixed for" +
                                " foreach goto if implicit in interface internal is lock namespace new" +
                                " operator out override params private protected public readonly ref return sealed" +
                                " sizeof stackalloc static struct switch this throw try typeof unchecked" +
                                " unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
                                " global group into join let orderby partial remove select set value var yield"),
                blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
                builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
                                " Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
                                " UInt64 bool byte char decimal double short int long object"  +
                                " sbyte float string ushort uint ulong"),
                atoms: words("true false null"),
                hooks: {
                  "@": function(stream, state) {
                    if (stream.eat('"')) {
                      state.tokenize = tokenAtString;
                      return tokenAtString(stream, state);
                    }
                    stream.eatWhile(/[\w\$_]/);
                    return "meta";
                  }
                }
              });
            
              function tokenTripleString(stream, state) {
                var escaped = false;
                while (!stream.eol()) {
                  if (!escaped && stream.match('"""')) {
                    state.tokenize = null;
                    break;
                  }
                  escaped = stream.next() == "\\" && !escaped;
                }
                return "string";
              }
            
              def("text/x-scala", {
                name: "clike",
                keywords: words(
            
                  /* scala */
                  "abstract case catch class def do else extends false final finally for forSome if " +
                  "implicit import lazy match new null object override package private protected return " +
                  "sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
                  "<% >: # @ " +
            
                  /* package scala */
                  "assert assume require print println printf readLine readBoolean readByte readShort " +
                  "readChar readInt readLong readFloat readDouble " +
            
                  "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
                  "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
                  "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
                  "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
                  "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
            
                  /* package java.lang */
                  "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
                  "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
                  "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
                  "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
                ),
                multiLineStrings: true,
                blockKeywords: words("catch class do else finally for forSome if match switch try while"),
                atoms: words("true false null"),
                indentStatements: false,
                indentSwitch: false,
                hooks: {
                  "@": function(stream) {
                    stream.eatWhile(/[\w\$_]/);
                    return "meta";
                  },
                  '"': function(stream, state) {
                    if (!stream.match('""')) return false;
                    state.tokenize = tokenTripleString;
                    return state.tokenize(stream, state);
                  },
                  "'": function(stream) {
                    stream.eatWhile(/[\w\$_\xa1-\uffff]/);
                    return "atom";
                  }
                },
                modeProps: {closeBrackets: {triples: '"'}}
              });
            
              def(["x-shader/x-vertex", "x-shader/x-fragment"], {
                name: "clike",
                keywords: words("float int bool void " +
                                "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
                                "mat2 mat3 mat4 " +
                                "sampler1D sampler2D sampler3D samplerCube " +
                                "sampler1DShadow sampler2DShadow " +
                                "const attribute uniform varying " +
                                "break continue discard return " +
                                "for while do if else struct " +
                                "in out inout"),
                blockKeywords: words("for while do if else struct"),
                builtin: words("radians degrees sin cos tan asin acos atan " +
                                "pow exp log exp2 sqrt inversesqrt " +
                                "abs sign floor ceil fract mod min max clamp mix step smoothstep " +
                                "length distance dot cross normalize ftransform faceforward " +
                                "reflect refract matrixCompMult " +
                                "lessThan lessThanEqual greaterThan greaterThanEqual " +
                                "equal notEqual any all not " +
                                "texture1D texture1DProj texture1DLod texture1DProjLod " +
                                "texture2D texture2DProj texture2DLod texture2DProjLod " +
                                "texture3D texture3DProj texture3DLod texture3DProjLod " +
                                "textureCube textureCubeLod " +
                                "shadow1D shadow2D shadow1DProj shadow2DProj " +
                                "shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " +
                                "dFdx dFdy fwidth " +
                                "noise1 noise2 noise3 noise4"),
                atoms: words("true false " +
                            "gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
                            "gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
                            "gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
                            "gl_FogCoord gl_PointCoord " +
                            "gl_Position gl_PointSize gl_ClipVertex " +
                            "gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
                            "gl_TexCoord gl_FogFragCoord " +
                            "gl_FragCoord gl_FrontFacing " +
                            "gl_FragData gl_FragDepth " +
                            "gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
                            "gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
                            "gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
                            "gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " +
                            "gl_ProjectionMatrixInverseTranspose " +
                            "gl_ModelViewProjectionMatrixInverseTranspose " +
                            "gl_TextureMatrixInverseTranspose " +
                            "gl_NormalScale gl_DepthRange gl_ClipPlane " +
                            "gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " +
                            "gl_FrontLightModelProduct gl_BackLightModelProduct " +
                            "gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " +
                            "gl_FogParameters " +
                            "gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " +
                            "gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " +
                            "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
                            "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
                            "gl_MaxDrawBuffers"),
                indentSwitch: false,
                hooks: {"#": cppHook},
                modeProps: {fold: ["brace", "include"]}
              });
            
              def("text/x-nesc", {
                name: "clike",
                keywords: words(cKeywords + "as atomic async call command component components configuration event generic " +
                                "implementation includes interface module new norace nx_struct nx_union post provides " +
                                "signal task uses abstract extends"),
                blockKeywords: words("case do else for if switch while struct"),
                atoms: words("null"),
                hooks: {"#": cppHook},
                modeProps: {fold: ["brace", "include"]}
              });
            
              def("text/x-objectivec", {
                name: "clike",
                keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " +
                                "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
                atoms: words("YES NO NULL NILL ON OFF"),
                hooks: {
                  "@": function(stream) {
                    stream.eatWhile(/[\w\$]/);
                    return "keyword";
                  },
                  "#": cppHook
                },
                modeProps: {fold: "brace"}
              });
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: C-like mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <link rel="stylesheet" href="../../addon/hint/show-hint.css">
            <script src="../../addon/hint/show-hint.js"></script>
            <script src="clike.js"></script>
            <style>.CodeMirror {border: 2px inset #dee;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">C-like</a>
              </ul>
            </div>
            
            <article>
            <h2>C-like mode</h2>
            
            <div><textarea id="c-code">
            /* C demo code */
            
            #include <zmq.h>
            #include <pthread.h>
            #include <semaphore.h>
            #include <time.h>
            #include <stdio.h>
            #include <fcntl.h>
            #include <malloc.h>
            
            typedef struct {
              void* arg_socket;
              zmq_msg_t* arg_msg;
              char* arg_string;
              unsigned long arg_len;
              int arg_int, arg_command;
            
              int signal_fd;
              int pad;
              void* context;
              sem_t sem;
            } acl_zmq_context;
            
            #define p(X) (context->arg_##X)
            
            void* zmq_thread(void* context_pointer) {
              acl_zmq_context* context = (acl_zmq_context*)context_pointer;
              char ok = 'K', err = 'X';
              int res;
            
              while (1) {
                while ((res = sem_wait(&amp;context->sem)) == EINTR);
                if (res) {write(context->signal_fd, &amp;err, 1); goto cleanup;}
                switch(p(command)) {
                case 0: goto cleanup;
                case 1: p(socket) = zmq_socket(context->context, p(int)); break;
                case 2: p(int) = zmq_close(p(socket)); break;
                case 3: p(int) = zmq_bind(p(socket), p(string)); break;
                case 4: p(int) = zmq_connect(p(socket), p(string)); break;
                case 5: p(int) = zmq_getsockopt(p(socket), p(int), (void*)p(string), &amp;p(len)); break;
                case 6: p(int) = zmq_setsockopt(p(socket), p(int), (void*)p(string), p(len)); break;
                case 7: p(int) = zmq_send(p(socket), p(msg), p(int)); break;
                case 8: p(int) = zmq_recv(p(socket), p(msg), p(int)); break;
                case 9: p(int) = zmq_poll(p(socket), p(int), p(len)); break;
                }
                p(command) = errno;
                write(context->signal_fd, &amp;ok, 1);
              }
             cleanup:
              close(context->signal_fd);
              free(context_pointer);
              return 0;
            }
            
            void* zmq_thread_init(void* zmq_context, int signal_fd) {
              acl_zmq_context* context = malloc(sizeof(acl_zmq_context));
              pthread_t thread;
            
              context->context = zmq_context;
              context->signal_fd = signal_fd;
              sem_init(&amp;context->sem, 1, 0);
              pthread_create(&amp;thread, 0, &amp;zmq_thread, context);
              pthread_detach(thread);
              return context;
            }
            </textarea></div>
            
            <h2>C++ example</h2>
            
            <div><textarea id="cpp-code">
            #include <iostream>
            #include "mystuff/util.h"
            
            namespace {
            enum Enum {
              VAL1, VAL2, VAL3
            };
            
            char32_t unicode_string = U"\U0010FFFF";
            string raw_string = R"delim(anything
            you
            want)delim";
            
            int Helper(const MyType& param) {
              return 0;
            }
            } // namespace
            
            class ForwardDec;
            
            template <class T, class V>
            class Class : public BaseClass {
              const MyType<T, V> member_;
            
             public:
              const MyType<T, V>& Method() const {
                return member_;
              }
            
              void Method2(MyType<T, V>* value);
            }
            
            template <class T, class V>
            void Class::Method2(MyType<T, V>* value) {
              std::out << 1 >> method();
              value->Method3(member_);
              member_ = value;
            }
            </textarea></div>
            
            <h2>Objective-C example</h2>
            
            <div><textarea id="objectivec-code">
            /*
            This is a longer comment
            That spans two lines
            */
            
            #import <Test/Test.h>
            @implementation YourAppDelegate
            
            // This is a one-line comment
            
            - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
              char myString[] = "This is a C character array";
              int test = 5;
              return YES;
            }
            </textarea></div>
            
            <h2>Java example</h2>
            
            <div><textarea id="java-code">
            import com.demo.util.MyType;
            import com.demo.util.MyInterface;
            
            public enum Enum {
              VAL1, VAL2, VAL3
            }
            
            public class Class<T, V> implements MyInterface {
              public static final MyType<T, V> member;
              
              private class InnerClass {
                public int zero() {
                  return 0;
                }
              }
            
              @Override
              public MyType method() {
                return member;
              }
            
              public void method2(MyType<T, V> value) {
                method();
                value.method3();
                member = value;
              }
            }
            </textarea></div>
            
            <h2>Scala example</h2>
            
            <div><textarea id="scala-code">
            object FilterTest extends App {
              def filter(xs: List[Int], threshold: Int) = {
                def process(ys: List[Int]): List[Int] =
                  if (ys.isEmpty) ys
                  else if (ys.head < threshold) ys.head :: process(ys.tail)
                  else process(ys.tail)
                process(xs)
              }
              println(filter(List(1, 9, 2, 8, 3, 7, 4), 5))
            }
            </textarea></div>
            
                <script>
                  var cEditor = CodeMirror.fromTextArea(document.getElementById("c-code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-csrc"
                  });
                  var cppEditor = CodeMirror.fromTextArea(document.getElementById("cpp-code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-c++src"
                  });
                  var javaEditor = CodeMirror.fromTextArea(document.getElementById("java-code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-java"
                  });
                  var objectivecEditor = CodeMirror.fromTextArea(document.getElementById("objectivec-code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-objectivec"
                  });
                  var scalaEditor = CodeMirror.fromTextArea(document.getElementById("scala-code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-scala"
                  });
                  var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
                  CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
                </script>
            
                <p>Simple mode that tries to handle C-like languages as well as it
                can. Takes two configuration parameters: <code>keywords</code>, an
                object whose property names are the keywords in the language,
                and <code>useCPP</code>, which determines whether C preprocessor
                directives are recognized.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-csrc</code>
                (C), <code>text/x-c++src</code> (C++), <code>text/x-java</code>
                (Java), <code>text/x-csharp</code> (C#),
                <code>text/x-objectivec</code> (Objective-C),
                <code>text/x-scala</code> (Scala), <code>text/x-vertex</code>
                and <code>x-shader/x-fragment</code> (shader programs).</p>
            </article>
            
          • scala.html
            <!doctype html>
            
            <title>CodeMirror: Scala mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/ambiance.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="clike.js"></script>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Scala</a>
              </ul>
            </div>
            
            <article>
            <h2>Scala mode</h2>
            <form>
            <textarea id="code" name="code">
            
              /*                     __                                               *\
              **     ________ ___   / /  ___     Scala API                            **
              **    / __/ __// _ | / /  / _ |    (c) 2003-2011, LAMP/EPFL             **
              **  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
              ** /____/\___/_/ |_/____/_/ | |                                         **
              **                          |/                                          **
              \*                                                                      */
            
              package scala.collection
            
              import generic._
              import mutable.{ Builder, ListBuffer }
              import annotation.{tailrec, migration, bridge}
              import annotation.unchecked.{ uncheckedVariance => uV }
              import parallel.ParIterable
            
              /** A template trait for traversable collections of type `Traversable[A]`.
               *  
               *  $traversableInfo
               *  @define mutability
               *  @define traversableInfo
               *  This is a base trait of all kinds of $mutability Scala collections. It
               *  implements the behavior common to all collections, in terms of a method
               *  `foreach` with signature:
               * {{{
               *     def foreach[U](f: Elem => U): Unit
               * }}}
               *  Collection classes mixing in this trait provide a concrete 
               *  `foreach` method which traverses all the
               *  elements contained in the collection, applying a given function to each.
               *  They also need to provide a method `newBuilder`
               *  which creates a builder for collections of the same kind.
               *  
               *  A traversable class might or might not have two properties: strictness
               *  and orderedness. Neither is represented as a type.
               *  
               *  The instances of a strict collection class have all their elements
               *  computed before they can be used as values. By contrast, instances of
               *  a non-strict collection class may defer computation of some of their
               *  elements until after the instance is available as a value.
               *  A typical example of a non-strict collection class is a
               *  <a href="../immutable/Stream.html" target="ContentFrame">
               *  `scala.collection.immutable.Stream`</a>.
               *  A more general class of examples are `TraversableViews`.
               *  
               *  If a collection is an instance of an ordered collection class, traversing
               *  its elements with `foreach` will always visit elements in the
               *  same order, even for different runs of the program. If the class is not
               *  ordered, `foreach` can visit elements in different orders for
               *  different runs (but it will keep the same order in the same run).'
               * 
               *  A typical example of a collection class which is not ordered is a
               *  `HashMap` of objects. The traversal order for hash maps will
               *  depend on the hash codes of its elements, and these hash codes might
               *  differ from one run to the next. By contrast, a `LinkedHashMap`
               *  is ordered because it's `foreach` method visits elements in the
               *  order they were inserted into the `HashMap`.
               *
               *  @author Martin Odersky
               *  @version 2.8
               *  @since   2.8
               *  @tparam A    the element type of the collection
               *  @tparam Repr the type of the actual collection containing the elements.
               *
               *  @define Coll Traversable
               *  @define coll traversable collection
               */
              trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr] 
                                                  with FilterMonadic[A, Repr]
                                                  with TraversableOnce[A]
                                                  with GenTraversableLike[A, Repr]
                                                  with Parallelizable[A, ParIterable[A]]
              {
                self =>
            
                import Traversable.breaks._
            
                /** The type implementing this traversable */
                protected type Self = Repr
            
                /** The collection of type $coll underlying this `TraversableLike` object.
                 *  By default this is implemented as the `TraversableLike` object itself,
                 *  but this can be overridden.
                 */
                def repr: Repr = this.asInstanceOf[Repr]
            
                /** The underlying collection seen as an instance of `$Coll`.
                 *  By default this is implemented as the current collection object itself,
                 *  but this can be overridden.
                 */
                protected[this] def thisCollection: Traversable[A] = this.asInstanceOf[Traversable[A]]
            
                /** A conversion from collections of type `Repr` to `$Coll` objects.
                 *  By default this is implemented as just a cast, but this can be overridden.
                 */
                protected[this] def toCollection(repr: Repr): Traversable[A] = repr.asInstanceOf[Traversable[A]]
            
                /** Creates a new builder for this collection type.
                 */
                protected[this] def newBuilder: Builder[A, Repr]
            
                protected[this] def parCombiner = ParIterable.newCombiner[A]
            
                /** Applies a function `f` to all elements of this $coll.
                 *  
                 *    Note: this method underlies the implementation of most other bulk operations.
                 *    It's important to implement this method in an efficient way.
                 *  
                 *
                 *  @param  f   the function that is applied for its side-effect to every element.
                 *              The result of function `f` is discarded.
                 *              
                 *  @tparam  U  the type parameter describing the result of function `f`. 
                 *              This result will always be ignored. Typically `U` is `Unit`,
                 *              but this is not necessary.
                 *
                 *  @usecase def foreach(f: A => Unit): Unit
                 */
                def foreach[U](f: A => U): Unit
            
                /** Tests whether this $coll is empty.
                 *
                 *  @return    `true` if the $coll contain no elements, `false` otherwise.
                 */
                def isEmpty: Boolean = {
                  var result = true
                  breakable {
                    for (x <- this) {
                      result = false
                      break
                    }
                  }
                  result
                }
            
                /** Tests whether this $coll is known to have a finite size.
                 *  All strict collections are known to have finite size. For a non-strict collection
                 *  such as `Stream`, the predicate returns `true` if all elements have been computed.
                 *  It returns `false` if the stream is not yet evaluated to the end.
                 *
                 *  Note: many collection methods will not work on collections of infinite sizes. 
                 *
                 *  @return  `true` if this collection is known to have finite size, `false` otherwise.
                 */
                def hasDefiniteSize = true
            
                def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  if (that.isInstanceOf[IndexedSeqLike[_, _]]) b.sizeHint(this, that.seq.size)
                  b ++= thisCollection
                  b ++= that.seq
                  b.result
                }
            
                @bridge
                def ++[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =
                  ++(that: GenTraversableOnce[B])(bf)
            
                /** Concatenates this $coll with the elements of a traversable collection.
                 *  It differs from ++ in that the right operand determines the type of the
                 *  resulting collection rather than the left one.
                 * 
                 *  @param that   the traversable to append.
                 *  @tparam B     the element type of the returned collection. 
                 *  @tparam That  $thatinfo
                 *  @param bf     $bfinfo
                 *  @return       a new collection of type `That` which contains all elements
                 *                of this $coll followed by all elements of `that`.
                 * 
                 *  @usecase def ++:[B](that: TraversableOnce[B]): $Coll[B]
                 *  
                 *  @return       a new $coll which contains all elements of this $coll
                 *                followed by all elements of `that`.
                 */
                def ++:[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  if (that.isInstanceOf[IndexedSeqLike[_, _]]) b.sizeHint(this, that.size)
                  b ++= that
                  b ++= thisCollection
                  b.result
                }
            
                /** This overload exists because: for the implementation of ++: we should reuse
                 *  that of ++ because many collections override it with more efficient versions.
                 *  Since TraversableOnce has no '++' method, we have to implement that directly,
                 *  but Traversable and down can use the overload.
                 */
                def ++:[B >: A, That](that: Traversable[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =
                  (that ++ seq)(breakOut)
            
                def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  b.sizeHint(this) 
                  for (x <- this) b += f(x)
                  b.result
                }
            
                def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  for (x <- this) b ++= f(x).seq
                  b.result
                }
            
                /** Selects all elements of this $coll which satisfy a predicate.
                 *
                 *  @param p     the predicate used to test elements.
                 *  @return      a new $coll consisting of all elements of this $coll that satisfy the given
                 *               predicate `p`. The order of the elements is preserved.
                 */
                def filter(p: A => Boolean): Repr = {
                  val b = newBuilder
                  for (x <- this) 
                    if (p(x)) b += x
                  b.result
                }
            
                /** Selects all elements of this $coll which do not satisfy a predicate.
                 *
                 *  @param p     the predicate used to test elements.
                 *  @return      a new $coll consisting of all elements of this $coll that do not satisfy the given
                 *               predicate `p`. The order of the elements is preserved.
                 */
                def filterNot(p: A => Boolean): Repr = filter(!p(_))
            
                def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  for (x <- this) if (pf.isDefinedAt(x)) b += pf(x)
                  b.result
                }
            
                /** Builds a new collection by applying an option-valued function to all
                 *  elements of this $coll on which the function is defined.
                 *
                 *  @param f      the option-valued function which filters and maps the $coll.
                 *  @tparam B     the element type of the returned collection.
                 *  @tparam That  $thatinfo
                 *  @param bf     $bfinfo
                 *  @return       a new collection of type `That` resulting from applying the option-valued function
                 *                `f` to each element and collecting all defined results.
                 *                The order of the elements is preserved.
                 *
                 *  @usecase def filterMap[B](f: A => Option[B]): $Coll[B]
                 *  
                 *  @param pf     the partial function which filters and maps the $coll.
                 *  @return       a new $coll resulting from applying the given option-valued function
                 *                `f` to each element and collecting all defined results.
                 *                The order of the elements is preserved.
                def filterMap[B, That](f: A => Option[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  for (x <- this) 
                    f(x) match {
                      case Some(y) => b += y
                      case _ =>
                    }
                  b.result
                }
                 */
            
                /** Partitions this $coll in two ${coll}s according to a predicate.
                 *
                 *  @param p the predicate on which to partition.
                 *  @return  a pair of ${coll}s: the first $coll consists of all elements that 
                 *           satisfy the predicate `p` and the second $coll consists of all elements
                 *           that don't. The relative order of the elements in the resulting ${coll}s
                 *           is the same as in the original $coll.
                 */
                def partition(p: A => Boolean): (Repr, Repr) = {
                  val l, r = newBuilder
                  for (x <- this) (if (p(x)) l else r) += x
                  (l.result, r.result)
                }
            
                def groupBy[K](f: A => K): immutable.Map[K, Repr] = {
                  val m = mutable.Map.empty[K, Builder[A, Repr]]
                  for (elem <- this) {
                    val key = f(elem)
                    val bldr = m.getOrElseUpdate(key, newBuilder)
                    bldr += elem
                  }
                  val b = immutable.Map.newBuilder[K, Repr]
                  for ((k, v) <- m)
                    b += ((k, v.result))
            
                  b.result
                }
            
                /** Tests whether a predicate holds for all elements of this $coll.
                 *
                 *  $mayNotTerminateInf
                 *
                 *  @param   p     the predicate used to test elements.
                 *  @return        `true` if the given predicate `p` holds for all elements
                 *                 of this $coll, otherwise `false`.
                 */
                def forall(p: A => Boolean): Boolean = {
                  var result = true
                  breakable {
                    for (x <- this)
                      if (!p(x)) { result = false; break }
                  }
                  result
                }
            
                /** Tests whether a predicate holds for some of the elements of this $coll.
                 *
                 *  $mayNotTerminateInf
                 *
                 *  @param   p     the predicate used to test elements.
                 *  @return        `true` if the given predicate `p` holds for some of the
                 *                 elements of this $coll, otherwise `false`.
                 */
                def exists(p: A => Boolean): Boolean = {
                  var result = false
                  breakable {
                    for (x <- this)
                      if (p(x)) { result = true; break }
                  }
                  result
                }
            
                /** Finds the first element of the $coll satisfying a predicate, if any.
                 * 
                 *  $mayNotTerminateInf
                 *  $orderDependent
                 *
                 *  @param p    the predicate used to test elements.
                 *  @return     an option value containing the first element in the $coll
                 *              that satisfies `p`, or `None` if none exists.
                 */
                def find(p: A => Boolean): Option[A] = {
                  var result: Option[A] = None
                  breakable {
                    for (x <- this)
                      if (p(x)) { result = Some(x); break }
                  }
                  result
                }
            
                def scan[B >: A, That](z: B)(op: (B, B) => B)(implicit cbf: CanBuildFrom[Repr, B, That]): That = scanLeft(z)(op)
            
                def scanLeft[B, That](z: B)(op: (B, A) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  val b = bf(repr)
                  b.sizeHint(this, 1)
                  var acc = z
                  b += acc
                  for (x <- this) { acc = op(acc, x); b += acc }
                  b.result
                }
            
                @migration(2, 9,
                  "This scanRight definition has changed in 2.9.\n" +
                  "The previous behavior can be reproduced with scanRight.reverse."
                )
                def scanRight[B, That](z: B)(op: (A, B) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                  var scanned = List(z)
                  var acc = z
                  for (x <- reversed) {
                    acc = op(x, acc)
                    scanned ::= acc
                  }
                  val b = bf(repr)
                  for (elem <- scanned) b += elem
                  b.result
                }
            
                /** Selects the first element of this $coll.
                 *  $orderDependent
                 *  @return  the first element of this $coll.
                 *  @throws `NoSuchElementException` if the $coll is empty.
                 */
                def head: A = {
                  var result: () => A = () => throw new NoSuchElementException
                  breakable {
                    for (x <- this) {
                      result = () => x
                      break
                    }
                  }
                  result()
                }
            
                /** Optionally selects the first element.
                 *  $orderDependent
                 *  @return  the first element of this $coll if it is nonempty, `None` if it is empty.
                 */
                def headOption: Option[A] = if (isEmpty) None else Some(head)
            
                /** Selects all elements except the first.
                 *  $orderDependent
                 *  @return  a $coll consisting of all elements of this $coll
                 *           except the first one.
                 *  @throws `UnsupportedOperationException` if the $coll is empty.
                 */ 
                override def tail: Repr = {
                  if (isEmpty) throw new UnsupportedOperationException("empty.tail")
                  drop(1)
                }
            
                /** Selects the last element.
                  * $orderDependent
                  * @return The last element of this $coll.
                  * @throws NoSuchElementException If the $coll is empty.
                  */
                def last: A = {
                  var lst = head
                  for (x <- this)
                    lst = x
                  lst
                }
            
                /** Optionally selects the last element.
                 *  $orderDependent
                 *  @return  the last element of this $coll$ if it is nonempty, `None` if it is empty.
                 */
                def lastOption: Option[A] = if (isEmpty) None else Some(last)
            
                /** Selects all elements except the last.
                 *  $orderDependent
                 *  @return  a $coll consisting of all elements of this $coll
                 *           except the last one.
                 *  @throws `UnsupportedOperationException` if the $coll is empty.
                 */
                def init: Repr = {
                  if (isEmpty) throw new UnsupportedOperationException("empty.init")
                  var lst = head
                  var follow = false
                  val b = newBuilder
                  b.sizeHint(this, -1)
                  for (x <- this.seq) {
                    if (follow) b += lst
                    else follow = true
                    lst = x
                  }
                  b.result
                }
            
                def take(n: Int): Repr = slice(0, n)
            
                def drop(n: Int): Repr = 
                  if (n <= 0) {
                    val b = newBuilder
                    b.sizeHint(this)
                    b ++= thisCollection result
                  }
                  else sliceWithKnownDelta(n, Int.MaxValue, -n)
            
                def slice(from: Int, until: Int): Repr = sliceWithKnownBound(math.max(from, 0), until)
            
                // Precondition: from >= 0, until > 0, builder already configured for building.
                private[this] def sliceInternal(from: Int, until: Int, b: Builder[A, Repr]): Repr = {
                  var i = 0
                  breakable {
                    for (x <- this.seq) {
                      if (i >= from) b += x
                      i += 1
                      if (i >= until) break
                    }
                  }
                  b.result
                }
                // Precondition: from >= 0
                private[scala] def sliceWithKnownDelta(from: Int, until: Int, delta: Int): Repr = {
                  val b = newBuilder
                  if (until <= from) b.result
                  else {
                    b.sizeHint(this, delta)
                    sliceInternal(from, until, b)
                  }
                }
                // Precondition: from >= 0
                private[scala] def sliceWithKnownBound(from: Int, until: Int): Repr = {
                  val b = newBuilder
                  if (until <= from) b.result
                  else {
                    b.sizeHintBounded(until - from, this)      
                    sliceInternal(from, until, b)
                  }
                }
            
                def takeWhile(p: A => Boolean): Repr = {
                  val b = newBuilder
                  breakable {
                    for (x <- this) {
                      if (!p(x)) break
                      b += x
                    }
                  }
                  b.result
                }
            
                def dropWhile(p: A => Boolean): Repr = {
                  val b = newBuilder
                  var go = false
                  for (x <- this) {
                    if (!p(x)) go = true
                    if (go) b += x
                  }
                  b.result
                }
            
                def span(p: A => Boolean): (Repr, Repr) = {
                  val l, r = newBuilder
                  var toLeft = true
                  for (x <- this) {
                    toLeft = toLeft && p(x)
                    (if (toLeft) l else r) += x
                  }
                  (l.result, r.result)
                }
            
                def splitAt(n: Int): (Repr, Repr) = {
                  val l, r = newBuilder
                  l.sizeHintBounded(n, this)
                  if (n >= 0) r.sizeHint(this, -n)
                  var i = 0
                  for (x <- this) {
                    (if (i < n) l else r) += x
                    i += 1
                  }
                  (l.result, r.result)
                }
            
                /** Iterates over the tails of this $coll. The first value will be this
                 *  $coll and the final one will be an empty $coll, with the intervening
                 *  values the results of successive applications of `tail`.
                 *
                 *  @return   an iterator over all the tails of this $coll
                 *  @example  `List(1,2,3).tails = Iterator(List(1,2,3), List(2,3), List(3), Nil)`
                 */  
                def tails: Iterator[Repr] = iterateUntilEmpty(_.tail)
            
                /** Iterates over the inits of this $coll. The first value will be this
                 *  $coll and the final one will be an empty $coll, with the intervening
                 *  values the results of successive applications of `init`.
                 *
                 *  @return  an iterator over all the inits of this $coll
                 *  @example  `List(1,2,3).inits = Iterator(List(1,2,3), List(1,2), List(1), Nil)`
                 */
                def inits: Iterator[Repr] = iterateUntilEmpty(_.init)
            
                /** Copies elements of this $coll to an array.
                 *  Fills the given array `xs` with at most `len` elements of
                 *  this $coll, starting at position `start`.
                 *  Copying will stop once either the end of the current $coll is reached,
                 *  or the end of the array is reached, or `len` elements have been copied.
                 *
                 *  $willNotTerminateInf
                 * 
                 *  @param  xs     the array to fill.
                 *  @param  start  the starting index.
                 *  @param  len    the maximal number of elements to copy.
                 *  @tparam B      the type of the elements of the array. 
                 * 
                 *
                 *  @usecase def copyToArray(xs: Array[A], start: Int, len: Int): Unit
                 */
                def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
                  var i = start
                  val end = (start + len) min xs.length
                  breakable {
                    for (x <- this) {
                      if (i >= end) break
                      xs(i) = x
                      i += 1
                    }
                  }
                }
            
                def toTraversable: Traversable[A] = thisCollection
                def toIterator: Iterator[A] = toStream.iterator
                def toStream: Stream[A] = toBuffer.toStream
            
                /** Converts this $coll to a string.
                 *
                 *  @return   a string representation of this collection. By default this
                 *            string consists of the `stringPrefix` of this $coll,
                 *            followed by all elements separated by commas and enclosed in parentheses.
                 */
                override def toString = mkString(stringPrefix + "(", ", ", ")")
            
                /** Defines the prefix of this object's `toString` representation.
                 *
                 *  @return  a string representation which starts the result of `toString`
                 *           applied to this $coll. By default the string prefix is the
                 *           simple name of the collection class $coll.
                 */
                def stringPrefix : String = {
                  var string = repr.asInstanceOf[AnyRef].getClass.getName
                  val idx1 = string.lastIndexOf('.' : Int)
                  if (idx1 != -1) string = string.substring(idx1 + 1)
                  val idx2 = string.indexOf('$')
                  if (idx2 != -1) string = string.substring(0, idx2)
                  string
                }
            
                /** Creates a non-strict view of this $coll.
                 * 
                 *  @return a non-strict view of this $coll.
                 */
                def view = new TraversableView[A, Repr] {
                  protected lazy val underlying = self.repr
                  override def foreach[U](f: A => U) = self foreach f
                }
            
                /** Creates a non-strict view of a slice of this $coll.
                 *
                 *  Note: the difference between `view` and `slice` is that `view` produces
                 *        a view of the current $coll, whereas `slice` produces a new $coll.
                 * 
                 *  Note: `view(from, to)` is equivalent to `view.slice(from, to)`
                 *  $orderDependent
                 * 
                 *  @param from   the index of the first element of the view
                 *  @param until  the index of the element following the view
                 *  @return a non-strict view of a slice of this $coll, starting at index `from`
                 *  and extending up to (but not including) index `until`.
                 */
                def view(from: Int, until: Int): TraversableView[A, Repr] = view.slice(from, until)
            
                /** Creates a non-strict filter of this $coll.
                 *
                 *  Note: the difference between `c filter p` and `c withFilter p` is that
                 *        the former creates a new collection, whereas the latter only
                 *        restricts the domain of subsequent `map`, `flatMap`, `foreach`,
                 *        and `withFilter` operations.
                 *  $orderDependent
                 * 
                 *  @param p   the predicate used to test elements.
                 *  @return    an object of class `WithFilter`, which supports
                 *             `map`, `flatMap`, `foreach`, and `withFilter` operations.
                 *             All these operations apply to those elements of this $coll which
                 *             satisfy the predicate `p`.
                 */
                def withFilter(p: A => Boolean): FilterMonadic[A, Repr] = new WithFilter(p)
            
                /** A class supporting filtered operations. Instances of this class are
                 *  returned by method `withFilter`.
                 */
                class WithFilter(p: A => Boolean) extends FilterMonadic[A, Repr] {
            
                  /** Builds a new collection by applying a function to all elements of the
                   *  outer $coll containing this `WithFilter` instance that satisfy predicate `p`.
                   *
                   *  @param f      the function to apply to each element.
                   *  @tparam B     the element type of the returned collection.
                   *  @tparam That  $thatinfo
                   *  @param bf     $bfinfo
                   *  @return       a new collection of type `That` resulting from applying
                   *                the given function `f` to each element of the outer $coll
                   *                that satisfies predicate `p` and collecting the results.
                   *
                   *  @usecase def map[B](f: A => B): $Coll[B] 
                   *  
                   *  @return       a new $coll resulting from applying the given function
                   *                `f` to each element of the outer $coll that satisfies
                   *                predicate `p` and collecting the results.
                   */
                  def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                    val b = bf(repr)
                    for (x <- self) 
                      if (p(x)) b += f(x)
                    b.result
                  }
            
                  /** Builds a new collection by applying a function to all elements of the
                   *  outer $coll containing this `WithFilter` instance that satisfy
                   *  predicate `p` and concatenating the results. 
                   *
                   *  @param f      the function to apply to each element.
                   *  @tparam B     the element type of the returned collection.
                   *  @tparam That  $thatinfo
                   *  @param bf     $bfinfo
                   *  @return       a new collection of type `That` resulting from applying
                   *                the given collection-valued function `f` to each element
                   *                of the outer $coll that satisfies predicate `p` and
                   *                concatenating the results.
                   *
                   *  @usecase def flatMap[B](f: A => TraversableOnce[B]): $Coll[B]
                   * 
                   *  @return       a new $coll resulting from applying the given collection-valued function
                   *                `f` to each element of the outer $coll that satisfies predicate `p` and concatenating the results.
                   */
                  def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
                    val b = bf(repr)
                    for (x <- self) 
                      if (p(x)) b ++= f(x).seq
                    b.result
                  }
            
                  /** Applies a function `f` to all elements of the outer $coll containing
                   *  this `WithFilter` instance that satisfy predicate `p`.
                   *
                   *  @param  f   the function that is applied for its side-effect to every element.
                   *              The result of function `f` is discarded.
                   *              
                   *  @tparam  U  the type parameter describing the result of function `f`. 
                   *              This result will always be ignored. Typically `U` is `Unit`,
                   *              but this is not necessary.
                   *
                   *  @usecase def foreach(f: A => Unit): Unit
                   */   
                  def foreach[U](f: A => U): Unit = 
                    for (x <- self) 
                      if (p(x)) f(x)
            
                  /** Further refines the filter for this $coll.
                   *
                   *  @param q   the predicate used to test elements.
                   *  @return    an object of class `WithFilter`, which supports
                   *             `map`, `flatMap`, `foreach`, and `withFilter` operations.
                   *             All these operations apply to those elements of this $coll which
                   *             satisfy the predicate `q` in addition to the predicate `p`.
                   */
                  def withFilter(q: A => Boolean): WithFilter = 
                    new WithFilter(x => p(x) && q(x))
                }
            
                // A helper for tails and inits.
                private def iterateUntilEmpty(f: Traversable[A @uV] => Traversable[A @uV]): Iterator[Repr] = {
                  val it = Iterator.iterate(thisCollection)(f) takeWhile (x => !x.isEmpty)
                  it ++ Iterator(Nil) map (newBuilder ++= _ result)
                }
              }
            
            
            </textarea>
            </form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    theme: "ambiance",
                    mode: "text/x-scala"
                  });
                </script>
              </article>
            
        • clojure
          • clojure.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Author: Hans Engel
             * Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun)
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("clojure", function (options) {
                var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2",
                    ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword", VAR = "variable";
                var INDENT_WORD_SKIP = options.indentUnit || 2;
                var NORMAL_INDENT_UNIT = options.indentUnit || 2;
            
                function makeKeywords(str) {
                    var obj = {}, words = str.split(" ");
                    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                    return obj;
                }
            
                var atoms = makeKeywords("true false nil");
            
                var keywords = makeKeywords(
                  "defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle");
            
                var builtins = makeKeywords(
                    "* *' *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* *compile-path* *compiler-options* *data-readers* *e *err* *file* *flush-on-newline* *fn-loader* *in* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *unchecked-math* *use-context-classloader* *verbose-defrecords* *warn-on-reflection* + +' - -' -> ->> ->ArrayChunk ->Vec ->VecNode ->VecSeq -cache-protocol-fn -reset-methods .. / < <= = == > >= EMPTY-NODE accessor aclone add-classpath add-watch agent agent-error agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint biginteger binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* bound? butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec dec' decimal? declare default-data-readers definline definterface defmacro defmethod defmulti defn defn- defonce defprotocol defrecord defstruct deftype delay delay? deliver denominator deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq error-handler error-mode eval even? every-pred every? ex-data ex-info extend extend-protocol extend-type extenders extends? false? ffirst file-seq filter filterv find find-keyword find-ns find-protocol-impl find-protocol-method find-var first flatten float float-array float? floats flush fn fn? fnext fnil for force format frequencies future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator group-by hash hash-combine hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc inc' init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt keep keep-indexed key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map-indexed map? mapcat mapv max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod munge name namespace namespace-munge neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext nthrest num number? numerator object-array odd? or parents partial partition partition-all partition-by pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-dup print-method print-simple print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int rand-nth range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string realized? reduce reduce-kv reductions ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure reify release-pending-sends rem remove remove-all-methods remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest restart-agent resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-error-handler! set-error-mode! set-validator! set? short short-array shorts shuffle shutdown-agents slurp some some-fn sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-symbol? spit split-at split-with str string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync take take-last take-nth take-while test the-ns thread-bound? time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-add-int unchecked-byte unchecked-char unchecked-dec unchecked-dec-int unchecked-divide-int unchecked-double unchecked-float unchecked-inc unchecked-inc-int unchecked-int unchecked-long unchecked-multiply unchecked-multiply-int unchecked-negate unchecked-negate-int unchecked-remainder-int unchecked-short unchecked-subtract unchecked-subtract-int underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector-of vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision with-redefs with-redefs-fn xml-seq zero? zipmap *default-data-reader-fn* as-> cond-> cond->> reduced reduced? send-via set-agent-send-executor! set-agent-send-off-executor! some-> some->>");
            
                var indentKeys = makeKeywords(
                    // Built-ins
                    "ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type try catch " +
            
                    // Binding forms
                    "let letfn binding loop for doseq dotimes when-let if-let " +
            
                    // Data structures
                    "defstruct struct-map assoc " +
            
                    // clojure.test
                    "testing deftest " +
            
                    // contrib
                    "handler-case handle dotrace deftrace");
            
                var tests = {
                    digit: /\d/,
                    digit_or_colon: /[\d:]/,
                    hex: /[0-9a-f]/i,
                    sign: /[+-]/,
                    exponent: /e/i,
                    keyword_char: /[^\s\(\[\;\)\]]/,
                    symbol: /[\w*+!\-\._?:<>\/\xa1-\uffff]/
                };
            
                function stateStack(indent, type, prev) { // represents a state stack object
                    this.indent = indent;
                    this.type = type;
                    this.prev = prev;
                }
            
                function pushStack(state, indent, type) {
                    state.indentStack = new stateStack(indent, type, state.indentStack);
                }
            
                function popStack(state) {
                    state.indentStack = state.indentStack.prev;
                }
            
                function isNumber(ch, stream){
                    // hex
                    if ( ch === '0' && stream.eat(/x/i) ) {
                        stream.eatWhile(tests.hex);
                        return true;
                    }
            
                    // leading sign
                    if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) {
                      stream.eat(tests.sign);
                      ch = stream.next();
                    }
            
                    if ( tests.digit.test(ch) ) {
                        stream.eat(ch);
                        stream.eatWhile(tests.digit);
            
                        if ( '.' == stream.peek() ) {
                            stream.eat('.');
                            stream.eatWhile(tests.digit);
                        }
            
                        if ( stream.eat(tests.exponent) ) {
                            stream.eat(tests.sign);
                            stream.eatWhile(tests.digit);
                        }
            
                        return true;
                    }
            
                    return false;
                }
            
                // Eat character that starts after backslash \
                function eatCharacter(stream) {
                    var first = stream.next();
                    // Read special literals: backspace, newline, space, return.
                    // Just read all lowercase letters.
                    if (first && first.match(/[a-z]/) && stream.match(/[a-z]+/, true)) {
                        return;
                    }
                    // Read unicode character: \u1000 \uA0a1
                    if (first === "u") {
                        stream.match(/[0-9a-z]{4}/i, true);
                    }
                }
            
                return {
                    startState: function () {
                        return {
                            indentStack: null,
                            indentation: 0,
                            mode: false
                        };
                    },
            
                    token: function (stream, state) {
                        if (state.indentStack == null && stream.sol()) {
                            // update indentation, but only if indentStack is empty
                            state.indentation = stream.indentation();
                        }
            
                        // skip spaces
                        if (stream.eatSpace()) {
                            return null;
                        }
                        var returnType = null;
            
                        switch(state.mode){
                            case "string": // multi-line string parsing mode
                                var next, escaped = false;
                                while ((next = stream.next()) != null) {
                                    if (next == "\"" && !escaped) {
            
                                        state.mode = false;
                                        break;
                                    }
                                    escaped = !escaped && next == "\\";
                                }
                                returnType = STRING; // continue on in string mode
                                break;
                            default: // default parsing mode
                                var ch = stream.next();
            
                                if (ch == "\"") {
                                    state.mode = "string";
                                    returnType = STRING;
                                } else if (ch == "\\") {
                                    eatCharacter(stream);
                                    returnType = CHARACTER;
                                } else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) {
                                    returnType = ATOM;
                                } else if (ch == ";") { // comment
                                    stream.skipToEnd(); // rest of the line is a comment
                                    returnType = COMMENT;
                                } else if (isNumber(ch,stream)){
                                    returnType = NUMBER;
                                } else if (ch == "(" || ch == "[" || ch == "{" ) {
                                    var keyWord = '', indentTemp = stream.column(), letter;
                                    /**
                                    Either
                                    (indent-word ..
                                    (non-indent-word ..
                                    (;something else, bracket, etc.
                                    */
            
                                    if (ch == "(") while ((letter = stream.eat(tests.keyword_char)) != null) {
                                        keyWord += letter;
                                    }
            
                                    if (keyWord.length > 0 && (indentKeys.propertyIsEnumerable(keyWord) ||
                                                               /^(?:def|with)/.test(keyWord))) { // indent-word
                                        pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
                                    } else { // non-indent word
                                        // we continue eating the spaces
                                        stream.eatSpace();
                                        if (stream.eol() || stream.peek() == ";") {
                                            // nothing significant after
                                            // we restart indentation the user defined spaces after
                                            pushStack(state, indentTemp + NORMAL_INDENT_UNIT, ch);
                                        } else {
                                            pushStack(state, indentTemp + stream.current().length, ch); // else we match
                                        }
                                    }
                                    stream.backUp(stream.current().length - 1); // undo all the eating
            
                                    returnType = BRACKET;
                                } else if (ch == ")" || ch == "]" || ch == "}") {
                                    returnType = BRACKET;
                                    if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : (ch == "]" ? "[" :"{"))) {
                                        popStack(state);
                                    }
                                } else if ( ch == ":" ) {
                                    stream.eatWhile(tests.symbol);
                                    return ATOM;
                                } else {
                                    stream.eatWhile(tests.symbol);
            
                                    if (keywords && keywords.propertyIsEnumerable(stream.current())) {
                                        returnType = KEYWORD;
                                    } else if (builtins && builtins.propertyIsEnumerable(stream.current())) {
                                        returnType = BUILTIN;
                                    } else if (atoms && atoms.propertyIsEnumerable(stream.current())) {
                                        returnType = ATOM;
                                    } else {
                                      returnType = VAR;
                                    }
                                }
                        }
            
                        return returnType;
                    },
            
                    indent: function (state) {
                        if (state.indentStack == null) return state.indentation;
                        return state.indentStack.indent;
                    },
            
                    closeBrackets: {pairs: "()[]{}\"\""},
                    lineComment: ";;"
                };
            });
            
            CodeMirror.defineMIME("text/x-clojure", "clojure");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Clojure mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="clojure.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Clojure</a>
              </ul>
            </div>
            
            <article>
            <h2>Clojure mode</h2>
            <form><textarea id="code" name="code">
            ; Conway's Game of Life, based on the work of:
            ;; Laurent Petit https://gist.github.com/1200343
            ;; Christophe Grand http://clj-me.cgrand.net/2011/08/19/conways-game-of-life
            
            (ns ^{:doc "Conway's Game of Life."}
             game-of-life)
            
            ;; Core game of life's algorithm functions
            
            (defn neighbours
              "Given a cell's coordinates, returns the coordinates of its neighbours."
              [[x y]]
              (for [dx [-1 0 1] dy (if (zero? dx) [-1 1] [-1 0 1])]
                [(+ dx x) (+ dy y)]))
            
            (defn step
              "Given a set of living cells, computes the new set of living cells."
              [cells]
              (set (for [[cell n] (frequencies (mapcat neighbours cells))
                         :when (or (= n 3) (and (= n 2) (cells cell)))]
                     cell)))
            
            ;; Utility methods for displaying game on a text terminal
            
            (defn print-board
              "Prints a board on *out*, representing a step in the game."
              [board w h]
              (doseq [x (range (inc w)) y (range (inc h))]
                (if (= y 0) (print "\n"))
                (print (if (board [x y]) "[X]" " . "))))
            
            (defn display-grids
              "Prints a squence of boards on *out*, representing several steps."
              [grids w h]
              (doseq [board grids]
                (print-board board w h)
                (print "\n")))
            
            ;; Launches an example board
            
            (def
              ^{:doc "board represents the initial set of living cells"}
               board #{[2 1] [2 2] [2 3]})
            
            (display-grids (take 3 (iterate step board)) 5 5)
            
            ;; Let's play with characters
            (println \1 \a \# \\
                     \" \( \newline
                     \} \" \space
                     \tab \return \backspace
                     \u1000 \uAaAa \u9F9F)
            
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-clojure</code>.</p>
            
              </article>
            
        • cmake
          • cmake.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object")
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd)
                define(["../../lib/codemirror"], mod);
              else
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("cmake", function () {
              var variable_regex = /({)?[a-zA-Z0-9_]+(})?/;
            
              function tokenString(stream, state) {
                var current, prev, found_var = false;
                while (!stream.eol() && (current = stream.next()) != state.pending) {
                  if (current === '$' && prev != '\\' && state.pending == '"') {
                    found_var = true;
                    break;
                  }
                  prev = current;
                }
                if (found_var) {
                  stream.backUp(1);
                }
                if (current == state.pending) {
                  state.continueString = false;
                } else {
                  state.continueString = true;
                }
                return "string";
              }
            
              function tokenize(stream, state) {
                var ch = stream.next();
            
                // Have we found a variable?
                if (ch === '$') {
                  if (stream.match(variable_regex)) {
                    return 'variable-2';
                  }
                  return 'variable';
                }
                // Should we still be looking for the end of a string?
                if (state.continueString) {
                  // If so, go through the loop again
                  stream.backUp(1);
                  return tokenString(stream, state);
                }
                // Do we just have a function on our hands?
                // In 'cmake_minimum_required (VERSION 2.8.8)', 'cmake_minimum_required' is matched
                if (stream.match(/(\s+)?\w+\(/) || stream.match(/(\s+)?\w+\ \(/)) {
                  stream.backUp(1);
                  return 'def';
                }
                if (ch == "#") {
                  stream.skipToEnd();
                  return "comment";
                }
                // Have we found a string?
                if (ch == "'" || ch == '"') {
                  // Store the type (single or double)
                  state.pending = ch;
                  // Perform the looping function to find the end
                  return tokenString(stream, state);
                }
                if (ch == '(' || ch == ')') {
                  return 'bracket';
                }
                if (ch.match(/[0-9]/)) {
                  return 'number';
                }
                stream.eatWhile(/[\w-]/);
                return null;
              }
              return {
                startState: function () {
                  var state = {};
                  state.inDefinition = false;
                  state.inInclude = false;
                  state.continueString = false;
                  state.pending = false;
                  return state;
                },
                token: function (stream, state) {
                  if (stream.eatSpace()) return null;
                  return tokenize(stream, state);
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-cmake", "cmake");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: CMake mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="cmake.js"></script>
            <style>
                  .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                  .cm-s-default span.cm-arrow { color: red; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">CMake</a>
              </ul>
            </div>
            
            <article>
            <h2>CMake mode</h2>
            <form><textarea id="code" name="code">
            # vim: syntax=cmake
            if(NOT CMAKE_BUILD_TYPE)
                # default to Release build for GCC builds
                set(CMAKE_BUILD_TYPE Release CACHE STRING
                    "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel."
                    FORCE)
            endif()
            message(STATUS "cmake version ${CMAKE_VERSION}")
            if(POLICY CMP0025)
                cmake_policy(SET CMP0025 OLD) # report Apple's Clang as just Clang
            endif()
            if(POLICY CMP0042)
                cmake_policy(SET CMP0042 NEW) # MACOSX_RPATH
            endif()
            
            project (x265)
            cmake_minimum_required (VERSION 2.8.8) # OBJECT libraries require 2.8.8
            include(CheckIncludeFiles)
            include(CheckFunctionExists)
            include(CheckSymbolExists)
            include(CheckCXXCompilerFlag)
            
            # X265_BUILD must be incremented each time the public API is changed
            set(X265_BUILD 48)
            configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
                           "${PROJECT_BINARY_DIR}/x265.def")
            configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
                           "${PROJECT_BINARY_DIR}/x265_config.h")
            
            SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}")
            
            # System architecture detection
            string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" SYSPROC)
            set(X86_ALIASES x86 i386 i686 x86_64 amd64)
            list(FIND X86_ALIASES "${SYSPROC}" X86MATCH)
            if("${SYSPROC}" STREQUAL "" OR X86MATCH GREATER "-1")
                message(STATUS "Detected x86 target processor")
                set(X86 1)
                add_definitions(-DX265_ARCH_X86=1)
                if("${CMAKE_SIZEOF_VOID_P}" MATCHES 8)
                    set(X64 1)
                    add_definitions(-DX86_64=1)
                endif()
            elseif(${SYSPROC} STREQUAL "armv6l")
                message(STATUS "Detected ARM target processor")
                set(ARM 1)
                add_definitions(-DX265_ARCH_ARM=1 -DHAVE_ARMV6=1)
            else()
                message(STATUS "CMAKE_SYSTEM_PROCESSOR value `${CMAKE_SYSTEM_PROCESSOR}` is unknown")
                message(STATUS "Please add this value near ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE}")
            endif()
            
            if(UNIX)
                list(APPEND PLATFORM_LIBS pthread)
                find_library(LIBRT rt)
                if(LIBRT)
                    list(APPEND PLATFORM_LIBS rt)
                endif()
                find_package(Numa)
                if(NUMA_FOUND)
                    list(APPEND CMAKE_REQUIRED_LIBRARIES ${NUMA_LIBRARY})
                    check_symbol_exists(numa_node_of_cpu numa.h NUMA_V2)
                    if(NUMA_V2)
                        add_definitions(-DHAVE_LIBNUMA)
                        message(STATUS "libnuma found, building with support for NUMA nodes")
                        list(APPEND PLATFORM_LIBS ${NUMA_LIBRARY})
                        link_directories(${NUMA_LIBRARY_DIR})
                        include_directories(${NUMA_INCLUDE_DIR})
                    endif()
                endif()
                mark_as_advanced(LIBRT NUMA_FOUND)
            endif(UNIX)
            
            if(X64 AND NOT WIN32)
                option(ENABLE_PIC "Enable Position Independent Code" ON)
            else()
                option(ENABLE_PIC "Enable Position Independent Code" OFF)
            endif(X64 AND NOT WIN32)
            
            # Compiler detection
            if(CMAKE_GENERATOR STREQUAL "Xcode")
              set(XCODE 1)
            endif()
            if (APPLE)
              add_definitions(-DMACOS)
            endif()
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/x-cmake",
                    matchBrackets: true,
                    indentUnit: 4
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-cmake</code>.</p>
            
              </article>
            
        • cobol
          • cobol.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Author: Gautam Mehta
             * Branched from CodeMirror's Scheme mode
             */
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("cobol", function () {
              var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
                  ATOM = "atom", NUMBER = "number", KEYWORD = "keyword", MODTAG = "header",
                  COBOLLINENUM = "def", PERIOD = "link";
              function makeKeywords(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
              var atoms = makeKeywords("TRUE FALSE ZEROES ZEROS ZERO SPACES SPACE LOW-VALUE LOW-VALUES ");
              var keywords = makeKeywords(
                  "ACCEPT ACCESS ACQUIRE ADD ADDRESS " +
                  "ADVANCING AFTER ALIAS ALL ALPHABET " +
                  "ALPHABETIC ALPHABETIC-LOWER ALPHABETIC-UPPER ALPHANUMERIC ALPHANUMERIC-EDITED " +
                  "ALSO ALTER ALTERNATE AND ANY " +
                  "ARE AREA AREAS ARITHMETIC ASCENDING " +
                  "ASSIGN AT ATTRIBUTE AUTHOR AUTO " +
                  "AUTO-SKIP AUTOMATIC B-AND B-EXOR B-LESS " +
                  "B-NOT B-OR BACKGROUND-COLOR BACKGROUND-COLOUR BEEP " +
                  "BEFORE BELL BINARY BIT BITS " +
                  "BLANK BLINK BLOCK BOOLEAN BOTTOM " +
                  "BY CALL CANCEL CD CF " +
                  "CH CHARACTER CHARACTERS CLASS CLOCK-UNITS " +
                  "CLOSE COBOL CODE CODE-SET COL " +
                  "COLLATING COLUMN COMMA COMMIT COMMITMENT " +
                  "COMMON COMMUNICATION COMP COMP-0 COMP-1 " +
                  "COMP-2 COMP-3 COMP-4 COMP-5 COMP-6 " +
                  "COMP-7 COMP-8 COMP-9 COMPUTATIONAL COMPUTATIONAL-0 " +
                  "COMPUTATIONAL-1 COMPUTATIONAL-2 COMPUTATIONAL-3 COMPUTATIONAL-4 COMPUTATIONAL-5 " +
                  "COMPUTATIONAL-6 COMPUTATIONAL-7 COMPUTATIONAL-8 COMPUTATIONAL-9 COMPUTE " +
                  "CONFIGURATION CONNECT CONSOLE CONTAINED CONTAINS " +
                  "CONTENT CONTINUE CONTROL CONTROL-AREA CONTROLS " +
                  "CONVERTING COPY CORR CORRESPONDING COUNT " +
                  "CRT CRT-UNDER CURRENCY CURRENT CURSOR " +
                  "DATA DATE DATE-COMPILED DATE-WRITTEN DAY " +
                  "DAY-OF-WEEK DB DB-ACCESS-CONTROL-KEY DB-DATA-NAME DB-EXCEPTION " +
                  "DB-FORMAT-NAME DB-RECORD-NAME DB-SET-NAME DB-STATUS DBCS " +
                  "DBCS-EDITED DE DEBUG-CONTENTS DEBUG-ITEM DEBUG-LINE " +
                  "DEBUG-NAME DEBUG-SUB-1 DEBUG-SUB-2 DEBUG-SUB-3 DEBUGGING " +
                  "DECIMAL-POINT DECLARATIVES DEFAULT DELETE DELIMITED " +
                  "DELIMITER DEPENDING DESCENDING DESCRIBED DESTINATION " +
                  "DETAIL DISABLE DISCONNECT DISPLAY DISPLAY-1 " +
                  "DISPLAY-2 DISPLAY-3 DISPLAY-4 DISPLAY-5 DISPLAY-6 " +
                  "DISPLAY-7 DISPLAY-8 DISPLAY-9 DIVIDE DIVISION " +
                  "DOWN DROP DUPLICATE DUPLICATES DYNAMIC " +
                  "EBCDIC EGI EJECT ELSE EMI " +
                  "EMPTY EMPTY-CHECK ENABLE END END. END-ACCEPT END-ACCEPT. " +
                  "END-ADD END-CALL END-COMPUTE END-DELETE END-DISPLAY " +
                  "END-DIVIDE END-EVALUATE END-IF END-INVOKE END-MULTIPLY " +
                  "END-OF-PAGE END-PERFORM END-READ END-RECEIVE END-RETURN " +
                  "END-REWRITE END-SEARCH END-START END-STRING END-SUBTRACT " +
                  "END-UNSTRING END-WRITE END-XML ENTER ENTRY " +
                  "ENVIRONMENT EOP EQUAL EQUALS ERASE " +
                  "ERROR ESI EVALUATE EVERY EXCEEDS " +
                  "EXCEPTION EXCLUSIVE EXIT EXTEND EXTERNAL " +
                  "EXTERNALLY-DESCRIBED-KEY FD FETCH FILE FILE-CONTROL " +
                  "FILE-STREAM FILES FILLER FINAL FIND " +
                  "FINISH FIRST FOOTING FOR FOREGROUND-COLOR " +
                  "FOREGROUND-COLOUR FORMAT FREE FROM FULL " +
                  "FUNCTION GENERATE GET GIVING GLOBAL " +
                  "GO GOBACK GREATER GROUP HEADING " +
                  "HIGH-VALUE HIGH-VALUES HIGHLIGHT I-O I-O-CONTROL " +
                  "ID IDENTIFICATION IF IN INDEX " +
                  "INDEX-1 INDEX-2 INDEX-3 INDEX-4 INDEX-5 " +
                  "INDEX-6 INDEX-7 INDEX-8 INDEX-9 INDEXED " +
                  "INDIC INDICATE INDICATOR INDICATORS INITIAL " +
                  "INITIALIZE INITIATE INPUT INPUT-OUTPUT INSPECT " +
                  "INSTALLATION INTO INVALID INVOKE IS " +
                  "JUST JUSTIFIED KANJI KEEP KEY " +
                  "LABEL LAST LD LEADING LEFT " +
                  "LEFT-JUSTIFY LENGTH LENGTH-CHECK LESS LIBRARY " +
                  "LIKE LIMIT LIMITS LINAGE LINAGE-COUNTER " +
                  "LINE LINE-COUNTER LINES LINKAGE LOCAL-STORAGE " +
                  "LOCALE LOCALLY LOCK " +
                  "MEMBER MEMORY MERGE MESSAGE METACLASS " +
                  "MODE MODIFIED MODIFY MODULES MOVE " +
                  "MULTIPLE MULTIPLY NATIONAL NATIVE NEGATIVE " +
                  "NEXT NO NO-ECHO NONE NOT " +
                  "NULL NULL-KEY-MAP NULL-MAP NULLS NUMBER " +
                  "NUMERIC NUMERIC-EDITED OBJECT OBJECT-COMPUTER OCCURS " +
                  "OF OFF OMITTED ON ONLY " +
                  "OPEN OPTIONAL OR ORDER ORGANIZATION " +
                  "OTHER OUTPUT OVERFLOW OWNER PACKED-DECIMAL " +
                  "PADDING PAGE PAGE-COUNTER PARSE PERFORM " +
                  "PF PH PIC PICTURE PLUS " +
                  "POINTER POSITION POSITIVE PREFIX PRESENT " +
                  "PRINTING PRIOR PROCEDURE PROCEDURE-POINTER PROCEDURES " +
                  "PROCEED PROCESS PROCESSING PROGRAM PROGRAM-ID " +
                  "PROMPT PROTECTED PURGE QUEUE QUOTE " +
                  "QUOTES RANDOM RD READ READY " +
                  "REALM RECEIVE RECONNECT RECORD RECORD-NAME " +
                  "RECORDS RECURSIVE REDEFINES REEL REFERENCE " +
                  "REFERENCE-MONITOR REFERENCES RELATION RELATIVE RELEASE " +
                  "REMAINDER REMOVAL RENAMES REPEATED REPLACE " +
                  "REPLACING REPORT REPORTING REPORTS REPOSITORY " +
                  "REQUIRED RERUN RESERVE RESET RETAINING " +
                  "RETRIEVAL RETURN RETURN-CODE RETURNING REVERSE-VIDEO " +
                  "REVERSED REWIND REWRITE RF RH " +
                  "RIGHT RIGHT-JUSTIFY ROLLBACK ROLLING ROUNDED " +
                  "RUN SAME SCREEN SD SEARCH " +
                  "SECTION SECURE SECURITY SEGMENT SEGMENT-LIMIT " +
                  "SELECT SEND SENTENCE SEPARATE SEQUENCE " +
                  "SEQUENTIAL SET SHARED SIGN SIZE " +
                  "SKIP1 SKIP2 SKIP3 SORT SORT-MERGE " +
                  "SORT-RETURN SOURCE SOURCE-COMPUTER SPACE-FILL " +
                  "SPECIAL-NAMES STANDARD STANDARD-1 STANDARD-2 " +
                  "START STARTING STATUS STOP STORE " +
                  "STRING SUB-QUEUE-1 SUB-QUEUE-2 SUB-QUEUE-3 SUB-SCHEMA " +
                  "SUBFILE SUBSTITUTE SUBTRACT SUM SUPPRESS " +
                  "SYMBOLIC SYNC SYNCHRONIZED SYSIN SYSOUT " +
                  "TABLE TALLYING TAPE TENANT TERMINAL " +
                  "TERMINATE TEST TEXT THAN THEN " +
                  "THROUGH THRU TIME TIMES TITLE " +
                  "TO TOP TRAILING TRAILING-SIGN TRANSACTION " +
                  "TYPE TYPEDEF UNDERLINE UNEQUAL UNIT " +
                  "UNSTRING UNTIL UP UPDATE UPON " +
                  "USAGE USAGE-MODE USE USING VALID " +
                  "VALIDATE VALUE VALUES VARYING VLR " +
                  "WAIT WHEN WHEN-COMPILED WITH WITHIN " +
                  "WORDS WORKING-STORAGE WRITE XML XML-CODE " +
                  "XML-EVENT XML-NTEXT XML-TEXT ZERO ZERO-FILL " );
            
              var builtins = makeKeywords("- * ** / + < <= = > >= ");
              var tests = {
                digit: /\d/,
                digit_or_colon: /[\d:]/,
                hex: /[0-9a-f]/i,
                sign: /[+-]/,
                exponent: /e/i,
                keyword_char: /[^\s\(\[\;\)\]]/,
                symbol: /[\w*+\-]/
              };
              function isNumber(ch, stream){
                // hex
                if ( ch === '0' && stream.eat(/x/i) ) {
                  stream.eatWhile(tests.hex);
                  return true;
                }
                // leading sign
                if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) {
                  stream.eat(tests.sign);
                  ch = stream.next();
                }
                if ( tests.digit.test(ch) ) {
                  stream.eat(ch);
                  stream.eatWhile(tests.digit);
                  if ( '.' == stream.peek()) {
                    stream.eat('.');
                    stream.eatWhile(tests.digit);
                  }
                  if ( stream.eat(tests.exponent) ) {
                    stream.eat(tests.sign);
                    stream.eatWhile(tests.digit);
                  }
                  return true;
                }
                return false;
              }
              return {
                startState: function () {
                  return {
                    indentStack: null,
                    indentation: 0,
                    mode: false
                  };
                },
                token: function (stream, state) {
                  if (state.indentStack == null && stream.sol()) {
                    // update indentation, but only if indentStack is empty
                    state.indentation = 6 ; //stream.indentation();
                  }
                  // skip spaces
                  if (stream.eatSpace()) {
                    return null;
                  }
                  var returnType = null;
                  switch(state.mode){
                  case "string": // multi-line string parsing mode
                    var next = false;
                    while ((next = stream.next()) != null) {
                      if (next == "\"" || next == "\'") {
                        state.mode = false;
                        break;
                      }
                    }
                    returnType = STRING; // continue on in string mode
                    break;
                  default: // default parsing mode
                    var ch = stream.next();
                    var col = stream.column();
                    if (col >= 0 && col <= 5) {
                      returnType = COBOLLINENUM;
                    } else if (col >= 72 && col <= 79) {
                      stream.skipToEnd();
                      returnType = MODTAG;
                    } else if (ch == "*" && col == 6) { // comment
                      stream.skipToEnd(); // rest of the line is a comment
                      returnType = COMMENT;
                    } else if (ch == "\"" || ch == "\'") {
                      state.mode = "string";
                      returnType = STRING;
                    } else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) {
                      returnType = ATOM;
                    } else if (ch == ".") {
                      returnType = PERIOD;
                    } else if (isNumber(ch,stream)){
                      returnType = NUMBER;
                    } else {
                      if (stream.current().match(tests.symbol)) {
                        while (col < 71) {
                          if (stream.eat(tests.symbol) === undefined) {
                            break;
                          } else {
                            col++;
                          }
                        }
                      }
                      if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {
                        returnType = KEYWORD;
                      } else if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) {
                        returnType = BUILTIN;
                      } else if (atoms && atoms.propertyIsEnumerable(stream.current().toUpperCase())) {
                        returnType = ATOM;
                      } else returnType = null;
                    }
                  }
                  return returnType;
                },
                indent: function (state) {
                  if (state.indentStack == null) return state.indentation;
                  return state.indentStack.indent;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-cobol", "cobol");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: COBOL mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/neat.css">
            <link rel="stylesheet" href="../../theme/elegant.css">
            <link rel="stylesheet" href="../../theme/erlang-dark.css">
            <link rel="stylesheet" href="../../theme/night.css">
            <link rel="stylesheet" href="../../theme/monokai.css">
            <link rel="stylesheet" href="../../theme/cobalt.css">
            <link rel="stylesheet" href="../../theme/eclipse.css">
            <link rel="stylesheet" href="../../theme/rubyblue.css">
            <link rel="stylesheet" href="../../theme/lesser-dark.css">
            <link rel="stylesheet" href="../../theme/xq-dark.css">
            <link rel="stylesheet" href="../../theme/xq-light.css">
            <link rel="stylesheet" href="../../theme/ambiance.css">
            <link rel="stylesheet" href="../../theme/blackboard.css">
            <link rel="stylesheet" href="../../theme/vibrant-ink.css">
            <link rel="stylesheet" href="../../theme/solarized.css">
            <link rel="stylesheet" href="../../theme/twilight.css">
            <link rel="stylesheet" href="../../theme/midnight.css">
            <link rel="stylesheet" href="../../addon/dialog/dialog.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="cobol.js"></script>
            <script src="../../addon/selection/active-line.js"></script>
            <script src="../../addon/search/search.js"></script>
            <script src="../../addon/dialog/dialog.js"></script>
            <script src="../../addon/search/searchcursor.js"></script>
            <style>
                    .CodeMirror {
                      border: 1px solid #eee;
                      font-size : 20px;
                      height : auto !important;
                    }
                    .CodeMirror-activeline-background {background: #555555 !important;}
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">COBOL</a>
              </ul>
            </div>
            
            <article>
            <h2>COBOL mode</h2>
            
                <p> Select Theme <select onchange="selectTheme()" id="selectTheme">
                    <option>default</option>
                    <option>ambiance</option>
                    <option>blackboard</option>
                    <option>cobalt</option>
                    <option>eclipse</option>
                    <option>elegant</option>
                    <option>erlang-dark</option>
                    <option>lesser-dark</option>
                    <option>midnight</option>
                    <option>monokai</option>
                    <option>neat</option>
                    <option>night</option>
                    <option>rubyblue</option>
                    <option>solarized dark</option>
                    <option>solarized light</option>
                    <option selected>twilight</option>
                    <option>vibrant-ink</option>
                    <option>xq-dark</option>
                    <option>xq-light</option>
                </select>    Select Font Size <select onchange="selectFontsize()" id="selectFontSize">
                      <option value="13px">13px</option>
                      <option value="14px">14px</option>
                      <option value="16px">16px</option>
                      <option value="18px">18px</option>
                      <option value="20px" selected="selected">20px</option>
                      <option value="24px">24px</option>
                      <option value="26px">26px</option>
                      <option value="28px">28px</option>
                      <option value="30px">30px</option>
                      <option value="32px">32px</option>
                      <option value="34px">34px</option>
                      <option value="36px">36px</option>
                    </select>
            <label for="checkBoxReadOnly">Read-only</label>
            <input type="checkbox" id="checkBoxReadOnly" onchange="selectReadOnly()">
            <label for="id_tabToIndentSpace">Insert Spaces on Tab</label>
            <input type="checkbox" id="id_tabToIndentSpace" onchange="tabToIndentSpace()">
            </p>
            <textarea id="code" name="code">
            ---------1---------2---------3---------4---------5---------6---------7---------8
            12345678911234567892123456789312345678941234567895123456789612345678971234567898
            000010 IDENTIFICATION DIVISION.                                        MODTGHERE
            000020 PROGRAM-ID.       SAMPLE.
            000030 AUTHOR.           TEST SAM. 
            000040 DATE-WRITTEN.     5 February 2013
            000041
            000042* A sample program just to show the form.
            000043* The program copies its input to the output,
            000044* and counts the number of records.
            000045* At the end this number is printed.
            000046
            000050 ENVIRONMENT DIVISION.
            000060 INPUT-OUTPUT SECTION.
            000070 FILE-CONTROL.
            000080     SELECT STUDENT-FILE     ASSIGN TO SYSIN
            000090         ORGANIZATION IS LINE SEQUENTIAL.
            000100     SELECT PRINT-FILE       ASSIGN TO SYSOUT
            000110         ORGANIZATION IS LINE SEQUENTIAL.
            000120
            000130 DATA DIVISION.
            000140 FILE SECTION.
            000150 FD  STUDENT-FILE
            000160     RECORD CONTAINS 43 CHARACTERS
            000170     DATA RECORD IS STUDENT-IN.
            000180 01  STUDENT-IN              PIC X(43).
            000190
            000200 FD  PRINT-FILE
            000210     RECORD CONTAINS 80 CHARACTERS
            000220     DATA RECORD IS PRINT-LINE.
            000230 01  PRINT-LINE              PIC X(80).
            000240
            000250 WORKING-STORAGE SECTION.
            000260 01  DATA-REMAINS-SWITCH     PIC X(2)      VALUE SPACES.
            000261 01  RECORDS-WRITTEN         PIC 99.
            000270
            000280 01  DETAIL-LINE.
            000290     05  FILLER              PIC X(7)      VALUE SPACES.
            000300     05  RECORD-IMAGE        PIC X(43).
            000310     05  FILLER              PIC X(30)     VALUE SPACES.
            000311 
            000312 01  SUMMARY-LINE.
            000313     05  FILLER              PIC X(7)      VALUE SPACES.
            000314     05  TOTAL-READ          PIC 99.
            000315     05  FILLER              PIC X         VALUE SPACE.
            000316     05  FILLER              PIC X(17)     
            000317                 VALUE  'Records were read'.
            000318     05  FILLER              PIC X(53)     VALUE SPACES.
            000319
            000320 PROCEDURE DIVISION.
            000321
            000330 PREPARE-SENIOR-REPORT.
            000340     OPEN INPUT  STUDENT-FILE
            000350          OUTPUT PRINT-FILE.
            000351     MOVE ZERO TO RECORDS-WRITTEN.
            000360     READ STUDENT-FILE
            000370         AT END MOVE 'NO' TO DATA-REMAINS-SWITCH
            000380     END-READ.
            000390     PERFORM PROCESS-RECORDS
            000410         UNTIL DATA-REMAINS-SWITCH = 'NO'.
            000411     PERFORM PRINT-SUMMARY.
            000420     CLOSE STUDENT-FILE
            000430           PRINT-FILE.
            000440     STOP RUN.
            000450
            000460 PROCESS-RECORDS.
            000470     MOVE STUDENT-IN TO RECORD-IMAGE.
            000480     MOVE DETAIL-LINE TO PRINT-LINE.
            000490     WRITE PRINT-LINE.
            000500     ADD 1 TO RECORDS-WRITTEN.
            000510     READ STUDENT-FILE
            000520         AT END MOVE 'NO' TO DATA-REMAINS-SWITCH
            000530     END-READ. 
            000540
            000550 PRINT-SUMMARY.
            000560     MOVE RECORDS-WRITTEN TO TOTAL-READ.
            000570     MOVE SUMMARY-LINE TO PRINT-LINE.
            000571     WRITE PRINT-LINE. 
            000572
            000580
            </textarea>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-cobol",
                    theme : "twilight",
                    styleActiveLine: true,
                    showCursorWhenSelecting : true,  
                  });
                  function selectTheme() {
                    var themeInput = document.getElementById("selectTheme");
                    var theme = themeInput.options[themeInput.selectedIndex].innerHTML;
                    editor.setOption("theme", theme);
                  }
                  function selectFontsize() {
                    var fontSizeInput = document.getElementById("selectFontSize");
                    var fontSize = fontSizeInput.options[fontSizeInput.selectedIndex].innerHTML;
                    editor.getWrapperElement().style.fontSize = fontSize;
                    editor.refresh();
                  }
                  function selectReadOnly() {
                    editor.setOption("readOnly", document.getElementById("checkBoxReadOnly").checked);
                  }
                  function tabToIndentSpace() {
                    if (document.getElementById("id_tabToIndentSpace").checked) {
                        editor.setOption("extraKeys", {Tab: function(cm) { cm.replaceSelection("    ", "end"); }});
                    } else {
                        editor.setOption("extraKeys", {Tab: function(cm) { cm.replaceSelection("    ", "end"); }});
                    }
                  }
                </script>
              </article>
            
        • coffeescript
          • coffeescript.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Link to the project's GitHub page:
             * https://github.com/pickhardt/coffeescript-codemirror-mode
             */
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("coffeescript", function(conf, parserConf) {
              var ERRORCLASS = "error";
            
              function wordRegexp(words) {
                return new RegExp("^((" + words.join(")|(") + "))\\b");
              }
            
              var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/;
              var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/;
              var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/;
              var properties = /^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*/;
            
              var wordOperators = wordRegexp(["and", "or", "not",
                                              "is", "isnt", "in",
                                              "instanceof", "typeof"]);
              var indentKeywords = ["for", "while", "loop", "if", "unless", "else",
                                    "switch", "try", "catch", "finally", "class"];
              var commonKeywords = ["break", "by", "continue", "debugger", "delete",
                                    "do", "in", "of", "new", "return", "then",
                                    "this", "@", "throw", "when", "until", "extends"];
            
              var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
            
              indentKeywords = wordRegexp(indentKeywords);
            
            
              var stringPrefixes = /^('{3}|\"{3}|['\"])/;
              var regexPrefixes = /^(\/{3}|\/)/;
              var commonConstants = ["Infinity", "NaN", "undefined", "null", "true", "false", "on", "off", "yes", "no"];
              var constants = wordRegexp(commonConstants);
            
              // Tokenizers
              function tokenBase(stream, state) {
                // Handle scope changes
                if (stream.sol()) {
                  if (state.scope.align === null) state.scope.align = false;
                  var scopeOffset = state.scope.offset;
                  if (stream.eatSpace()) {
                    var lineOffset = stream.indentation();
                    if (lineOffset > scopeOffset && state.scope.type == "coffee") {
                      return "indent";
                    } else if (lineOffset < scopeOffset) {
                      return "dedent";
                    }
                    return null;
                  } else {
                    if (scopeOffset > 0) {
                      dedent(stream, state);
                    }
                  }
                }
                if (stream.eatSpace()) {
                  return null;
                }
            
                var ch = stream.peek();
            
                // Handle docco title comment (single line)
                if (stream.match("####")) {
                  stream.skipToEnd();
                  return "comment";
                }
            
                // Handle multi line comments
                if (stream.match("###")) {
                  state.tokenize = longComment;
                  return state.tokenize(stream, state);
                }
            
                // Single line comment
                if (ch === "#") {
                  stream.skipToEnd();
                  return "comment";
                }
            
                // Handle number literals
                if (stream.match(/^-?[0-9\.]/, false)) {
                  var floatLiteral = false;
                  // Floats
                  if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
                    floatLiteral = true;
                  }
                  if (stream.match(/^-?\d+\.\d*/)) {
                    floatLiteral = true;
                  }
                  if (stream.match(/^-?\.\d+/)) {
                    floatLiteral = true;
                  }
            
                  if (floatLiteral) {
                    // prevent from getting extra . on 1..
                    if (stream.peek() == "."){
                      stream.backUp(1);
                    }
                    return "number";
                  }
                  // Integers
                  var intLiteral = false;
                  // Hex
                  if (stream.match(/^-?0x[0-9a-f]+/i)) {
                    intLiteral = true;
                  }
                  // Decimal
                  if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
                    intLiteral = true;
                  }
                  // Zero by itself with no other piece of number.
                  if (stream.match(/^-?0(?![\dx])/i)) {
                    intLiteral = true;
                  }
                  if (intLiteral) {
                    return "number";
                  }
                }
            
                // Handle strings
                if (stream.match(stringPrefixes)) {
                  state.tokenize = tokenFactory(stream.current(), false, "string");
                  return state.tokenize(stream, state);
                }
                // Handle regex literals
                if (stream.match(regexPrefixes)) {
                  if (stream.current() != "/" || stream.match(/^.*\//, false)) { // prevent highlight of division
                    state.tokenize = tokenFactory(stream.current(), true, "string-2");
                    return state.tokenize(stream, state);
                  } else {
                    stream.backUp(1);
                  }
                }
            
                // Handle operators and delimiters
                if (stream.match(operators) || stream.match(wordOperators)) {
                  return "operator";
                }
                if (stream.match(delimiters)) {
                  return "punctuation";
                }
            
                if (stream.match(constants)) {
                  return "atom";
                }
            
                if (stream.match(keywords)) {
                  return "keyword";
                }
            
                if (stream.match(identifiers)) {
                  return "variable";
                }
            
                if (stream.match(properties)) {
                  return "property";
                }
            
                // Handle non-detected items
                stream.next();
                return ERRORCLASS;
              }
            
              function tokenFactory(delimiter, singleline, outclass) {
                return function(stream, state) {
                  while (!stream.eol()) {
                    stream.eatWhile(/[^'"\/\\]/);
                    if (stream.eat("\\")) {
                      stream.next();
                      if (singleline && stream.eol()) {
                        return outclass;
                      }
                    } else if (stream.match(delimiter)) {
                      state.tokenize = tokenBase;
                      return outclass;
                    } else {
                      stream.eat(/['"\/]/);
                    }
                  }
                  if (singleline) {
                    if (parserConf.singleLineStringErrors) {
                      outclass = ERRORCLASS;
                    } else {
                      state.tokenize = tokenBase;
                    }
                  }
                  return outclass;
                };
              }
            
              function longComment(stream, state) {
                while (!stream.eol()) {
                  stream.eatWhile(/[^#]/);
                  if (stream.match("###")) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  stream.eatWhile("#");
                }
                return "comment";
              }
            
              function indent(stream, state, type) {
                type = type || "coffee";
                var offset = 0, align = false, alignOffset = null;
                for (var scope = state.scope; scope; scope = scope.prev) {
                  if (scope.type === "coffee" || scope.type == "}") {
                    offset = scope.offset + conf.indentUnit;
                    break;
                  }
                }
                if (type !== "coffee") {
                  align = null;
                  alignOffset = stream.column() + stream.current().length;
                } else if (state.scope.align) {
                  state.scope.align = false;
                }
                state.scope = {
                  offset: offset,
                  type: type,
                  prev: state.scope,
                  align: align,
                  alignOffset: alignOffset
                };
              }
            
              function dedent(stream, state) {
                if (!state.scope.prev) return;
                if (state.scope.type === "coffee") {
                  var _indent = stream.indentation();
                  var matched = false;
                  for (var scope = state.scope; scope; scope = scope.prev) {
                    if (_indent === scope.offset) {
                      matched = true;
                      break;
                    }
                  }
                  if (!matched) {
                    return true;
                  }
                  while (state.scope.prev && state.scope.offset !== _indent) {
                    state.scope = state.scope.prev;
                  }
                  return false;
                } else {
                  state.scope = state.scope.prev;
                  return false;
                }
              }
            
              function tokenLexer(stream, state) {
                var style = state.tokenize(stream, state);
                var current = stream.current();
            
                // Handle "." connected identifiers
                if (current === ".") {
                  style = state.tokenize(stream, state);
                  current = stream.current();
                  if (/^\.[\w$]+$/.test(current)) {
                    return "variable";
                  } else {
                    return ERRORCLASS;
                  }
                }
            
                // Handle scope changes.
                if (current === "return") {
                  state.dedent = true;
                }
                if (((current === "->" || current === "=>") &&
                     !state.lambda &&
                     !stream.peek())
                    || style === "indent") {
                  indent(stream, state);
                }
                var delimiter_index = "[({".indexOf(current);
                if (delimiter_index !== -1) {
                  indent(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
                }
                if (indentKeywords.exec(current)){
                  indent(stream, state);
                }
                if (current == "then"){
                  dedent(stream, state);
                }
            
            
                if (style === "dedent") {
                  if (dedent(stream, state)) {
                    return ERRORCLASS;
                  }
                }
                delimiter_index = "])}".indexOf(current);
                if (delimiter_index !== -1) {
                  while (state.scope.type == "coffee" && state.scope.prev)
                    state.scope = state.scope.prev;
                  if (state.scope.type == current)
                    state.scope = state.scope.prev;
                }
                if (state.dedent && stream.eol()) {
                  if (state.scope.type == "coffee" && state.scope.prev)
                    state.scope = state.scope.prev;
                  state.dedent = false;
                }
            
                return style;
              }
            
              var external = {
                startState: function(basecolumn) {
                  return {
                    tokenize: tokenBase,
                    scope: {offset:basecolumn || 0, type:"coffee", prev: null, align: false},
                    lastToken: null,
                    lambda: false,
                    dedent: 0
                  };
                },
            
                token: function(stream, state) {
                  var fillAlign = state.scope.align === null && state.scope;
                  if (fillAlign && stream.sol()) fillAlign.align = false;
            
                  var style = tokenLexer(stream, state);
                  if (fillAlign && style && style != "comment") fillAlign.align = true;
            
                  state.lastToken = {style:style, content: stream.current()};
            
                  if (stream.eol() && stream.lambda) {
                    state.lambda = false;
                  }
            
                  return style;
                },
            
                indent: function(state, text) {
                  if (state.tokenize != tokenBase) return 0;
                  var scope = state.scope;
                  var closer = text && "])}".indexOf(text.charAt(0)) > -1;
                  if (closer) while (scope.type == "coffee" && scope.prev) scope = scope.prev;
                  var closes = closer && scope.type === text.charAt(0);
                  if (scope.align)
                    return scope.alignOffset - (closes ? 1 : 0);
                  else
                    return (closes ? scope.prev : scope).offset;
                },
            
                lineComment: "#",
                fold: "indent"
              };
              return external;
            });
            
            CodeMirror.defineMIME("text/x-coffeescript", "coffeescript");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: CoffeeScript mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="coffeescript.js"></script>
            <style>.CodeMirror {border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">CoffeeScript</a>
              </ul>
            </div>
            
            <article>
            <h2>CoffeeScript mode</h2>
            <form><textarea id="code" name="code">
            # CoffeeScript mode for CodeMirror
            # Copyright (c) 2011 Jeff Pickhardt, released under
            # the MIT License.
            #
            # Modified from the Python CodeMirror mode, which also is 
            # under the MIT License Copyright (c) 2010 Timothy Farrell.
            #
            # The following script, Underscore.coffee, is used to 
            # demonstrate CoffeeScript mode for CodeMirror.
            #
            # To download CoffeeScript mode for CodeMirror, go to:
            # https://github.com/pickhardt/coffeescript-codemirror-mode
            
            # **Underscore.coffee
            # (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.**
            # Underscore is freely distributable under the terms of the
            # [MIT license](http://en.wikipedia.org/wiki/MIT_License).
            # Portions of Underscore are inspired by or borrowed from
            # [Prototype.js](http://prototypejs.org/api), Oliver Steele's
            # [Functional](http://osteele.com), and John Resig's
            # [Micro-Templating](http://ejohn.org).
            # For all details and documentation:
            # http://documentcloud.github.com/underscore/
            
            
            # Baseline setup
            # --------------
            
            # Establish the root object, `window` in the browser, or `global` on the server.
            root = this
            
            
            # Save the previous value of the `_` variable.
            previousUnderscore = root._
            
            ### Multiline
                comment
            ###
            
            # Establish the object that gets thrown to break out of a loop iteration.
            # `StopIteration` is SOP on Mozilla.
            breaker = if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
            
            
            #### Docco style single line comment (title)
            
            
            # Helper function to escape **RegExp** contents, because JS doesn't have one.
            escapeRegExp = (string) -> string.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1')
            
            
            # Save bytes in the minified (but not gzipped) version:
            ArrayProto = Array.prototype
            ObjProto = Object.prototype
            
            
            # Create quick reference variables for speed access to core prototypes.
            slice = ArrayProto.slice
            unshift = ArrayProto.unshift
            toString = ObjProto.toString
            hasOwnProperty = ObjProto.hasOwnProperty
            propertyIsEnumerable = ObjProto.propertyIsEnumerable
            
            
            # All **ECMA5** native implementations we hope to use are declared here.
            nativeForEach = ArrayProto.forEach
            nativeMap = ArrayProto.map
            nativeReduce = ArrayProto.reduce
            nativeReduceRight = ArrayProto.reduceRight
            nativeFilter = ArrayProto.filter
            nativeEvery = ArrayProto.every
            nativeSome = ArrayProto.some
            nativeIndexOf = ArrayProto.indexOf
            nativeLastIndexOf = ArrayProto.lastIndexOf
            nativeIsArray = Array.isArray
            nativeKeys = Object.keys
            
            
            # Create a safe reference to the Underscore object for use below.
            _ = (obj) -> new wrapper(obj)
            
            
            # Export the Underscore object for **CommonJS**.
            if typeof(exports) != 'undefined' then exports._ = _
            
            
            # Export Underscore to global scope.
            root._ = _
            
            
            # Current version.
            _.VERSION = '1.1.0'
            
            
            # Collection Functions
            # --------------------
            
            # The cornerstone, an **each** implementation.
            # Handles objects implementing **forEach**, arrays, and raw objects.
            _.each = (obj, iterator, context) ->
              try
                if nativeForEach and obj.forEach is nativeForEach
                  obj.forEach iterator, context
                else if _.isNumber obj.length
                  iterator.call context, obj[i], i, obj for i in [0...obj.length]
                else
                  iterator.call context, val, key, obj for own key, val of obj
              catch e
                throw e if e isnt breaker
              obj
            
            
            # Return the results of applying the iterator to each element. Use JavaScript
            # 1.6's version of **map**, if possible.
            _.map = (obj, iterator, context) ->
              return obj.map(iterator, context) if nativeMap and obj.map is nativeMap
              results = []
              _.each obj, (value, index, list) ->
                results.push iterator.call context, value, index, list
              results
            
            
            # **Reduce** builds up a single result from a list of values. Also known as
            # **inject**, or **foldl**. Uses JavaScript 1.8's version of **reduce**, if possible.
            _.reduce = (obj, iterator, memo, context) ->
              if nativeReduce and obj.reduce is nativeReduce
                iterator = _.bind iterator, context if context
                return obj.reduce iterator, memo
              _.each obj, (value, index, list) ->
                memo = iterator.call context, memo, value, index, list
              memo
            
            
            # The right-associative version of **reduce**, also known as **foldr**. Uses
            # JavaScript 1.8's version of **reduceRight**, if available.
            _.reduceRight = (obj, iterator, memo, context) ->
              if nativeReduceRight and obj.reduceRight is nativeReduceRight
                iterator = _.bind iterator, context if context
                return obj.reduceRight iterator, memo
              reversed = _.clone(_.toArray(obj)).reverse()
              _.reduce reversed, iterator, memo, context
            
            
            # Return the first value which passes a truth test.
            _.detect = (obj, iterator, context) ->
              result = null
              _.each obj, (value, index, list) ->
                if iterator.call context, value, index, list
                  result = value
                  _.breakLoop()
              result
            
            
            # Return all the elements that pass a truth test. Use JavaScript 1.6's
            # **filter**, if it exists.
            _.filter = (obj, iterator, context) ->
              return obj.filter iterator, context if nativeFilter and obj.filter is nativeFilter
              results = []
              _.each obj, (value, index, list) ->
                results.push value if iterator.call context, value, index, list
              results
            
            
            # Return all the elements for which a truth test fails.
            _.reject = (obj, iterator, context) ->
              results = []
              _.each obj, (value, index, list) ->
                results.push value if not iterator.call context, value, index, list
              results
            
            
            # Determine whether all of the elements match a truth test. Delegate to
            # JavaScript 1.6's **every**, if it is present.
            _.every = (obj, iterator, context) ->
              iterator ||= _.identity
              return obj.every iterator, context if nativeEvery and obj.every is nativeEvery
              result = true
              _.each obj, (value, index, list) ->
                _.breakLoop() unless (result = result and iterator.call(context, value, index, list))
              result
            
            
            # Determine if at least one element in the object matches a truth test. Use
            # JavaScript 1.6's **some**, if it exists.
            _.some = (obj, iterator, context) ->
              iterator ||= _.identity
              return obj.some iterator, context if nativeSome and obj.some is nativeSome
              result = false
              _.each obj, (value, index, list) ->
                _.breakLoop() if (result = iterator.call(context, value, index, list))
              result
            
            
            # Determine if a given value is included in the array or object,
            # based on `===`.
            _.include = (obj, target) ->
              return _.indexOf(obj, target) isnt -1 if nativeIndexOf and obj.indexOf is nativeIndexOf
              return true for own key, val of obj when val is target
              false
            
            
            # Invoke a method with arguments on every item in a collection.
            _.invoke = (obj, method) ->
              args = _.rest arguments, 2
              (if method then val[method] else val).apply(val, args) for val in obj
            
            
            # Convenience version of a common use case of **map**: fetching a property.
            _.pluck = (obj, key) ->
              _.map(obj, (val) -> val[key])
            
            
            # Return the maximum item or (item-based computation).
            _.max = (obj, iterator, context) ->
              return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)
              result = computed: -Infinity
              _.each obj, (value, index, list) ->
                computed = if iterator then iterator.call(context, value, index, list) else value
                computed >= result.computed and (result = {value: value, computed: computed})
              result.value
            
            
            # Return the minimum element (or element-based computation).
            _.min = (obj, iterator, context) ->
              return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)
              result = computed: Infinity
              _.each obj, (value, index, list) ->
                computed = if iterator then iterator.call(context, value, index, list) else value
                computed < result.computed and (result = {value: value, computed: computed})
              result.value
            
            
            # Sort the object's values by a criterion produced by an iterator.
            _.sortBy = (obj, iterator, context) ->
              _.pluck(((_.map obj, (value, index, list) ->
                {value: value, criteria: iterator.call(context, value, index, list)}
              ).sort((left, right) ->
                a = left.criteria; b = right.criteria
                if a < b then -1 else if a > b then 1 else 0
              )), 'value')
            
            
            # Use a comparator function to figure out at what index an object should
            # be inserted so as to maintain order. Uses binary search.
            _.sortedIndex = (array, obj, iterator) ->
              iterator ||= _.identity
              low = 0
              high = array.length
              while low < high
                mid = (low + high) >> 1
                if iterator(array[mid]) < iterator(obj) then low = mid + 1 else high = mid
              low
            
            
            # Convert anything iterable into a real, live array.
            _.toArray = (iterable) ->
              return [] if (!iterable)
              return iterable.toArray() if (iterable.toArray)
              return iterable if (_.isArray(iterable))
              return slice.call(iterable) if (_.isArguments(iterable))
              _.values(iterable)
            
            
            # Return the number of elements in an object.
            _.size = (obj) -> _.toArray(obj).length
            
            
            # Array Functions
            # ---------------
            
            # Get the first element of an array. Passing `n` will return the first N
            # values in the array. Aliased as **head**. The `guard` check allows it to work
            # with **map**.
            _.first = (array, n, guard) ->
              if n and not guard then slice.call(array, 0, n) else array[0]
            
            
            # Returns everything but the first entry of the array. Aliased as **tail**.
            # Especially useful on the arguments object. Passing an `index` will return
            # the rest of the values in the array from that index onward. The `guard`
            # check allows it to work with **map**.
            _.rest = (array, index, guard) ->
              slice.call(array, if _.isUndefined(index) or guard then 1 else index)
            
            
            # Get the last element of an array.
            _.last = (array) -> array[array.length - 1]
            
            
            # Trim out all falsy values from an array.
            _.compact = (array) -> item for item in array when item
            
            
            # Return a completely flattened version of an array.
            _.flatten = (array) ->
              _.reduce array, (memo, value) ->
                return memo.concat(_.flatten(value)) if _.isArray value
                memo.push value
                memo
              , []
            
            
            # Return a version of the array that does not contain the specified value(s).
            _.without = (array) ->
              values = _.rest arguments
              val for val in _.toArray(array) when not _.include values, val
            
            
            # Produce a duplicate-free version of the array. If the array has already
            # been sorted, you have the option of using a faster algorithm.
            _.uniq = (array, isSorted) ->
              memo = []
              for el, i in _.toArray array
                memo.push el if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
              memo
            
            
            # Produce an array that contains every item shared between all the
            # passed-in arrays.
            _.intersect = (array) ->
              rest = _.rest arguments
              _.select _.uniq(array), (item) ->
                _.all rest, (other) ->
                  _.indexOf(other, item) >= 0
            
            
            # Zip together multiple lists into a single array -- elements that share
            # an index go together.
            _.zip = ->
              length = _.max _.pluck arguments, 'length'
              results = new Array length
              for i in [0...length]
                results[i] = _.pluck arguments, String i
              results
            
            
            # If the browser doesn't supply us with **indexOf** (I'm looking at you, MSIE),
            # we need this function. Return the position of the first occurrence of an
            # item in an array, or -1 if the item is not included in the array.
            _.indexOf = (array, item) ->
              return array.indexOf item if nativeIndexOf and array.indexOf is nativeIndexOf
              i = 0; l = array.length
              while l - i
                if array[i] is item then return i else i++
              -1
            
            
            # Provide JavaScript 1.6's **lastIndexOf**, delegating to the native function,
            # if possible.
            _.lastIndexOf = (array, item) ->
              return array.lastIndexOf(item) if nativeLastIndexOf and array.lastIndexOf is nativeLastIndexOf
              i = array.length
              while i
                if array[i] is item then return i else i--
              -1
            
            
            # Generate an integer Array containing an arithmetic progression. A port of
            # [the native Python **range** function](http://docs.python.org/library/functions.html#range).
            _.range = (start, stop, step) ->
              a = arguments
              solo = a.length <= 1
              i = start = if solo then 0 else a[0]
              stop = if solo then a[0] else a[1]
              step = a[2] or 1
              len = Math.ceil((stop - start) / step)
              return [] if len <= 0
              range = new Array len
              idx = 0
              loop
                return range if (if step > 0 then i - stop else stop - i) >= 0
                range[idx] = i
                idx++
                i+= step
            
            
            # Function Functions
            # ------------------
            
            # Create a function bound to a given object (assigning `this`, and arguments,
            # optionally). Binding with arguments is also known as **curry**.
            _.bind = (func, obj) ->
              args = _.rest arguments, 2
              -> func.apply obj or root, args.concat arguments
            
            
            # Bind all of an object's methods to that object. Useful for ensuring that
            # all callbacks defined on an object belong to it.
            _.bindAll = (obj) ->
              funcs = if arguments.length > 1 then _.rest(arguments) else _.functions(obj)
              _.each funcs, (f) -> obj[f] = _.bind obj[f], obj
              obj
            
            
            # Delays a function for the given number of milliseconds, and then calls
            # it with the arguments supplied.
            _.delay = (func, wait) ->
              args = _.rest arguments, 2
              setTimeout((-> func.apply(func, args)), wait)
            
            
            # Memoize an expensive function by storing its results.
            _.memoize = (func, hasher) ->
              memo = {}
              hasher or= _.identity
              ->
                key = hasher.apply this, arguments
                return memo[key] if key of memo
                memo[key] = func.apply this, arguments
            
            
            # Defers a function, scheduling it to run after the current call stack has
            # cleared.
            _.defer = (func) ->
              _.delay.apply _, [func, 1].concat _.rest arguments
            
            
            # Returns the first function passed as an argument to the second,
            # allowing you to adjust arguments, run code before and after, and
            # conditionally execute the original function.
            _.wrap = (func, wrapper) ->
              -> wrapper.apply wrapper, [func].concat arguments
            
            
            # Returns a function that is the composition of a list of functions, each
            # consuming the return value of the function that follows.
            _.compose = ->
              funcs = arguments
              ->
                args = arguments
                for i in [funcs.length - 1..0] by -1
                  args = [funcs[i].apply(this, args)]
                args[0]
            
            
            # Object Functions
            # ----------------
            
            # Retrieve the names of an object's properties.
            _.keys = nativeKeys or (obj) ->
              return _.range 0, obj.length if _.isArray(obj)
              key for key, val of obj
            
            
            # Retrieve the values of an object's properties.
            _.values = (obj) ->
              _.map obj, _.identity
            
            
            # Return a sorted list of the function names available in Underscore.
            _.functions = (obj) ->
              _.filter(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()
            
            
            # Extend a given object with all of the properties in a source object.
            _.extend = (obj) ->
              for source in _.rest(arguments)
                obj[key] = val for key, val of source
              obj
            
            
            # Create a (shallow-cloned) duplicate of an object.
            _.clone = (obj) ->
              return obj.slice 0 if _.isArray obj
              _.extend {}, obj
            
            
            # Invokes interceptor with the obj, and then returns obj.
            # The primary purpose of this method is to "tap into" a method chain,
            # in order to perform operations on intermediate results within
             the chain.
            _.tap = (obj, interceptor) ->
              interceptor obj
              obj
            
            
            # Perform a deep comparison to check if two objects are equal.
            _.isEqual = (a, b) ->
              # Check object identity.
              return true if a is b
              # Different types?
              atype = typeof(a); btype = typeof(b)
              return false if atype isnt btype
              # Basic equality test (watch out for coercions).
              return true if `a == b`
              # One is falsy and the other truthy.
              return false if (!a and b) or (a and !b)
              # One of them implements an `isEqual()`?
              return a.isEqual(b) if a.isEqual
              # Check dates' integer values.
              return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
              # Both are NaN?
              return false if _.isNaN(a) and _.isNaN(b)
              # Compare regular expressions.
              if _.isRegExp(a) and _.isRegExp(b)
                return a.source is b.source and
                       a.global is b.global and
                       a.ignoreCase is b.ignoreCase and
                       a.multiline is b.multiline
              # If a is not an object by this point, we can't handle it.
              return false if atype isnt 'object'
              # Check for different array lengths before comparing contents.
              return false if a.length and (a.length isnt b.length)
              # Nothing else worked, deep compare the contents.
              aKeys = _.keys(a); bKeys = _.keys(b)
              # Different object sizes?
              return false if aKeys.length isnt bKeys.length
              # Recursive comparison of contents.
              return false for key, val of a when !(key of b) or !_.isEqual(val, b[key])
              true
            
            
            # Is a given array or object empty?
            _.isEmpty = (obj) ->
              return obj.length is 0 if _.isArray(obj) or _.isString(obj)
              return false for own key of obj
              true
            
            
            # Is a given value a DOM element?
            _.isElement = (obj) -> obj and obj.nodeType is 1
            
            
            # Is a given value an array?
            _.isArray = nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift and not obj.callee)
            
            
            # Is a given variable an arguments object?
            _.isArguments = (obj) -> obj and obj.callee
            
            
            # Is the given value a function?
            _.isFunction = (obj) -> !!(obj and obj.constructor and obj.call and obj.apply)
            
            
            # Is the given value a string?
            _.isString = (obj) -> !!(obj is '' or (obj and obj.charCodeAt and obj.substr))
            
            
            # Is a given value a number?
            _.isNumber = (obj) -> (obj is +obj) or toString.call(obj) is '[object Number]'
            
            
            # Is a given value a boolean?
            _.isBoolean = (obj) -> obj is true or obj is false
            
            
            # Is a given value a Date?
            _.isDate = (obj) -> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)
            
            
            # Is the given value a regular expression?
            _.isRegExp = (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))
            
            
            # Is the given value NaN -- this one is interesting. `NaN != NaN`, and
            # `isNaN(undefined) == true`, so we make sure it's a number first.
            _.isNaN = (obj) -> _.isNumber(obj) and window.isNaN(obj)
            
            
            # Is a given value equal to null?
            _.isNull = (obj) -> obj is null
            
            
            # Is a given variable undefined?
            _.isUndefined = (obj) -> typeof obj is 'undefined'
            
            
            # Utility Functions
            # -----------------
            
            # Run Underscore.js in noConflict mode, returning the `_` variable to its
            # previous owner. Returns a reference to the Underscore object.
            _.noConflict = ->
              root._ = previousUnderscore
              this
            
            
            # Keep the identity function around for default iterators.
            _.identity = (value) -> value
            
            
            # Run a function `n` times.
            _.times = (n, iterator, context) ->
              iterator.call context, i for i in [0...n]
            
            
            # Break out of the middle of an iteration.
            _.breakLoop = -> throw breaker
            
            
            # Add your own custom functions to the Underscore object, ensuring that
            # they're correctly added to the OOP wrapper as well.
            _.mixin = (obj) ->
              for name in _.functions(obj)
                addToWrapper name, _[name] = obj[name]
            
            
            # Generate a unique integer id (unique within the entire client session).
            # Useful for temporary DOM ids.
            idCounter = 0
            _.uniqueId = (prefix) ->
              (prefix or '') + idCounter++
            
            
            # By default, Underscore uses **ERB**-style template delimiters, change the
            # following template settings to use alternative delimiters.
            _.templateSettings = {
              start: '<%'
              end: '%>'
              interpolate: /<%=(.+?)%>/g
            }
            
            
            # JavaScript templating a-la **ERB**, pilfered from John Resig's
            # *Secrets of the JavaScript Ninja*, page 83.
            # Single-quote fix from Rick Strahl.
            # With alterations for arbitrary delimiters, and to preserve whitespace.
            _.template = (str, data) ->
              c = _.templateSettings
              endMatch = new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g")
              fn = new Function 'obj',
                'var p=[],print=function(){p.push.apply(p,arguments);};' +
                'with(obj||{}){p.push(\'' +
                str.replace(/\r/g, '\\r')
                   .replace(/\n/g, '\\n')
                   .replace(/\t/g, '\\t')
                   .replace(endMatch,"���")
                   .split("'").join("\\'")
                   .split("���").join("'")
                   .replace(c.interpolate, "',$1,'")
                   .split(c.start).join("');")
                   .split(c.end).join("p.push('") +
                   "');}return p.join('');"
              if data then fn(data) else fn
            
            
            # Aliases
            # -------
            
            _.forEach = _.each
            _.foldl = _.inject = _.reduce
            _.foldr = _.reduceRight
            _.select = _.filter
            _.all = _.every
            _.any = _.some
            _.contains = _.include
            _.head = _.first
            _.tail = _.rest
            _.methods = _.functions
            
            
            # Setup the OOP Wrapper
            # ---------------------
            
            # If Underscore is called as a function, it returns a wrapped object that
            # can be used OO-style. This wrapper holds altered versions of all the
            # underscore functions. Wrapped objects may be chained.
            wrapper = (obj) ->
              this._wrapped = obj
              this
            
            
            # Helper function to continue chaining intermediate results.
            result = (obj, chain) ->
              if chain then _(obj).chain() else obj
            
            
            # A method to easily add functions to the OOP wrapper.
            addToWrapper = (name, func) ->
              wrapper.prototype[name] = ->
                args = _.toArray arguments
                unshift.call args, this._wrapped
                result func.apply(_, args), this._chain
            
            
            # Add all ofthe Underscore functions to the wrapper object.
            _.mixin _
            
            
            # Add all mutator Array functions to the wrapper.
            _.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name) ->
              method = Array.prototype[name]
              wrapper.prototype[name] = ->
                method.apply(this._wrapped, arguments)
                result(this._wrapped, this._chain)
            
            
            # Add all accessor Array functions to the wrapper.
            _.each ['concat', 'join', 'slice'], (name) ->
              method = Array.prototype[name]
              wrapper.prototype[name] = ->
                result(method.apply(this._wrapped, arguments), this._chain)
            
            
            # Start chaining a wrapped Underscore object.
            wrapper::chain = ->
              this._chain = true
              this
            
            
            # Extracts the result from a wrapped and chained object.
            wrapper::value = -> this._wrapped
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-coffeescript</code>.</p>
            
                <p>The CoffeeScript mode was written by Jeff Pickhardt.</p>
            
              </article>
            
        • commonlisp
          • commonlisp.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("commonlisp", function (config) {
              var specialForm = /^(block|let*|return-from|catch|load-time-value|setq|eval-when|locally|symbol-macrolet|flet|macrolet|tagbody|function|multiple-value-call|the|go|multiple-value-prog1|throw|if|progn|unwind-protect|labels|progv|let|quote)$/;
              var assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/;
              var numLiteral = /^(?:[+\-]?(?:\d+|\d*\.\d+)(?:[efd][+\-]?\d+)?|[+\-]?\d+(?:\/[+\-]?\d+)?|#b[+\-]?[01]+|#o[+\-]?[0-7]+|#x[+\-]?[\da-f]+)/;
              var symbol = /[^\s'`,@()\[\]";]/;
              var type;
            
              function readSym(stream) {
                var ch;
                while (ch = stream.next()) {
                  if (ch == "\\") stream.next();
                  else if (!symbol.test(ch)) { stream.backUp(1); break; }
                }
                return stream.current();
              }
            
              function base(stream, state) {
                if (stream.eatSpace()) {type = "ws"; return null;}
                if (stream.match(numLiteral)) return "number";
                var ch = stream.next();
                if (ch == "\\") ch = stream.next();
            
                if (ch == '"') return (state.tokenize = inString)(stream, state);
                else if (ch == "(") { type = "open"; return "bracket"; }
                else if (ch == ")" || ch == "]") { type = "close"; return "bracket"; }
                else if (ch == ";") { stream.skipToEnd(); type = "ws"; return "comment"; }
                else if (/['`,@]/.test(ch)) return null;
                else if (ch == "|") {
                  if (stream.skipTo("|")) { stream.next(); return "symbol"; }
                  else { stream.skipToEnd(); return "error"; }
                } else if (ch == "#") {
                  var ch = stream.next();
                  if (ch == "[") { type = "open"; return "bracket"; }
                  else if (/[+\-=\.']/.test(ch)) return null;
                  else if (/\d/.test(ch) && stream.match(/^\d*#/)) return null;
                  else if (ch == "|") return (state.tokenize = inComment)(stream, state);
                  else if (ch == ":") { readSym(stream); return "meta"; }
                  else return "error";
                } else {
                  var name = readSym(stream);
                  if (name == ".") return null;
                  type = "symbol";
                  if (name == "nil" || name == "t" || name.charAt(0) == ":") return "atom";
                  if (state.lastType == "open" && (specialForm.test(name) || assumeBody.test(name))) return "keyword";
                  if (name.charAt(0) == "&") return "variable-2";
                  return "variable";
                }
              }
            
              function inString(stream, state) {
                var escaped = false, next;
                while (next = stream.next()) {
                  if (next == '"' && !escaped) { state.tokenize = base; break; }
                  escaped = !escaped && next == "\\";
                }
                return "string";
              }
            
              function inComment(stream, state) {
                var next, last;
                while (next = stream.next()) {
                  if (next == "#" && last == "|") { state.tokenize = base; break; }
                  last = next;
                }
                type = "ws";
                return "comment";
              }
            
              return {
                startState: function () {
                  return {ctx: {prev: null, start: 0, indentTo: 0}, lastType: null, tokenize: base};
                },
            
                token: function (stream, state) {
                  if (stream.sol() && typeof state.ctx.indentTo != "number")
                    state.ctx.indentTo = state.ctx.start + 1;
            
                  type = null;
                  var style = state.tokenize(stream, state);
                  if (type != "ws") {
                    if (state.ctx.indentTo == null) {
                      if (type == "symbol" && assumeBody.test(stream.current()))
                        state.ctx.indentTo = state.ctx.start + config.indentUnit;
                      else
                        state.ctx.indentTo = "next";
                    } else if (state.ctx.indentTo == "next") {
                      state.ctx.indentTo = stream.column();
                    }
                    state.lastType = type;
                  }
                  if (type == "open") state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null};
                  else if (type == "close") state.ctx = state.ctx.prev || state.ctx;
                  return style;
                },
            
                indent: function (state, _textAfter) {
                  var i = state.ctx.indentTo;
                  return typeof i == "number" ? i : state.ctx.start + 1;
                },
            
                closeBrackets: {pairs: "()[]{}\"\""},
                lineComment: ";;",
                blockCommentStart: "#|",
                blockCommentEnd: "|#"
              };
            });
            
            CodeMirror.defineMIME("text/x-common-lisp", "commonlisp");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Common Lisp mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="commonlisp.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Common Lisp</a>
              </ul>
            </div>
            
            <article>
            <h2>Common Lisp mode</h2>
            <form><textarea id="code" name="code">(in-package :cl-postgres)
            
            ;; These are used to synthesize reader and writer names for integer
            ;; reading/writing functions when the amount of bytes and the
            ;; signedness is known. Both the macro that creates the functions and
            ;; some macros that use them create names this way.
            (eval-when (:compile-toplevel :load-toplevel :execute)
              (defun integer-reader-name (bytes signed)
                (intern (with-standard-io-syntax
                          (format nil "~a~a~a~a" '#:read- (if signed "" '#:u) '#:int bytes))))
              (defun integer-writer-name (bytes signed)
                (intern (with-standard-io-syntax
                          (format nil "~a~a~a~a" '#:write- (if signed "" '#:u) '#:int bytes)))))
            
            (defmacro integer-reader (bytes)
              "Create a function to read integers from a binary stream."
              (let ((bits (* bytes 8)))
                (labels ((return-form (signed)
                           (if signed
                               `(if (logbitp ,(1- bits) result)
                                    (dpb result (byte ,(1- bits) 0) -1)
                                    result)
                               `result))
                         (generate-reader (signed)
                           `(defun ,(integer-reader-name bytes signed) (socket)
                              (declare (type stream socket)
                                       #.*optimize*)
                              ,(if (= bytes 1)
                                   `(let ((result (the (unsigned-byte 8) (read-byte socket))))
                                      (declare (type (unsigned-byte 8) result))
                                      ,(return-form signed))
                                   `(let ((result 0))
                                      (declare (type (unsigned-byte ,bits) result))
                                      ,@(loop :for byte :from (1- bytes) :downto 0
                                               :collect `(setf (ldb (byte 8 ,(* 8 byte)) result)
                                                               (the (unsigned-byte 8) (read-byte socket))))
                                      ,(return-form signed))))))
                  `(progn
            ;; This causes weird errors on SBCL in some circumstances. Disabled for now.
            ;;         (declaim (inline ,(integer-reader-name bytes t)
            ;;                          ,(integer-reader-name bytes nil)))
                     (declaim (ftype (function (t) (signed-byte ,bits))
                                     ,(integer-reader-name bytes t)))
                     ,(generate-reader t)
                     (declaim (ftype (function (t) (unsigned-byte ,bits))
                                     ,(integer-reader-name bytes nil)))
                     ,(generate-reader nil)))))
            
            (defmacro integer-writer (bytes)
              "Create a function to write integers to a binary stream."
              (let ((bits (* 8 bytes)))
                `(progn
                  (declaim (inline ,(integer-writer-name bytes t)
                                   ,(integer-writer-name bytes nil)))
                  (defun ,(integer-writer-name bytes nil) (socket value)
                    (declare (type stream socket)
                             (type (unsigned-byte ,bits) value)
                             #.*optimize*)
                    ,@(if (= bytes 1)
                          `((write-byte value socket))
                          (loop :for byte :from (1- bytes) :downto 0
                                :collect `(write-byte (ldb (byte 8 ,(* byte 8)) value)
                                           socket)))
                    (values))
                  (defun ,(integer-writer-name bytes t) (socket value)
                    (declare (type stream socket)
                             (type (signed-byte ,bits) value)
                             #.*optimize*)
                    ,@(if (= bytes 1)
                          `((write-byte (ldb (byte 8 0) value) socket))
                          (loop :for byte :from (1- bytes) :downto 0
                                :collect `(write-byte (ldb (byte 8 ,(* byte 8)) value)
                                           socket)))
                    (values)))))
            
            ;; All the instances of the above that we need.
            
            (integer-reader 1)
            (integer-reader 2)
            (integer-reader 4)
            (integer-reader 8)
            
            (integer-writer 1)
            (integer-writer 2)
            (integer-writer 4)
            
            (defun write-bytes (socket bytes)
              "Write a byte-array to a stream."
              (declare (type stream socket)
                       (type (simple-array (unsigned-byte 8)) bytes)
                       #.*optimize*)
              (write-sequence bytes socket))
            
            (defun write-str (socket string)
              "Write a null-terminated string to a stream \(encoding it when UTF-8
            support is enabled.)."
              (declare (type stream socket)
                       (type string string)
                       #.*optimize*)
              (enc-write-string string socket)
              (write-uint1 socket 0))
            
            (declaim (ftype (function (t unsigned-byte)
                                      (simple-array (unsigned-byte 8) (*)))
                            read-bytes))
            (defun read-bytes (socket length)
              "Read a byte array of the given length from a stream."
              (declare (type stream socket)
                       (type fixnum length)
                       #.*optimize*)
              (let ((result (make-array length :element-type '(unsigned-byte 8))))
                (read-sequence result socket)
                result))
            
            (declaim (ftype (function (t) string) read-str))
            (defun read-str (socket)
              "Read a null-terminated string from a stream. Takes care of encoding
            when UTF-8 support is enabled."
              (declare (type stream socket)
                       #.*optimize*)
              (enc-read-string socket :null-terminated t))
            
            (defun skip-bytes (socket length)
              "Skip a given number of bytes in a binary stream."
              (declare (type stream socket)
                       (type (unsigned-byte 32) length)
                       #.*optimize*)
              (dotimes (i length)
                (read-byte socket)))
            
            (defun skip-str (socket)
              "Skip a null-terminated string."
              (declare (type stream socket)
                       #.*optimize*)
              (loop :for char :of-type fixnum = (read-byte socket)
                    :until (zerop char)))
            
            (defun ensure-socket-is-closed (socket &amp;key abort)
              (when (open-stream-p socket)
                (handler-case
                    (close socket :abort abort)
                  (error (error)
                    (warn "Ignoring the error which happened while trying to close PostgreSQL socket: ~A" error)))))
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {lineNumbers: true});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-common-lisp</code>.</p>
            
              </article>
            
        • css
          • css.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("css", function(config, parserConfig) {
              if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
            
              var indentUnit = config.indentUnit,
                  tokenHooks = parserConfig.tokenHooks,
                  documentTypes = parserConfig.documentTypes || {},
                  mediaTypes = parserConfig.mediaTypes || {},
                  mediaFeatures = parserConfig.mediaFeatures || {},
                  propertyKeywords = parserConfig.propertyKeywords || {},
                  nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
                  fontProperties = parserConfig.fontProperties || {},
                  counterDescriptors = parserConfig.counterDescriptors || {},
                  colorKeywords = parserConfig.colorKeywords || {},
                  valueKeywords = parserConfig.valueKeywords || {},
                  allowNested = parserConfig.allowNested;
            
              var type, override;
              function ret(style, tp) { type = tp; return style; }
            
              // Tokenizers
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (tokenHooks[ch]) {
                  var result = tokenHooks[ch](stream, state);
                  if (result !== false) return result;
                }
                if (ch == "@") {
                  stream.eatWhile(/[\w\\\-]/);
                  return ret("def", stream.current());
                } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
                  return ret(null, "compare");
                } else if (ch == "\"" || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                } else if (ch == "#") {
                  stream.eatWhile(/[\w\\\-]/);
                  return ret("atom", "hash");
                } else if (ch == "!") {
                  stream.match(/^\s*\w*/);
                  return ret("keyword", "important");
                } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
                  stream.eatWhile(/[\w.%]/);
                  return ret("number", "unit");
                } else if (ch === "-") {
                  if (/[\d.]/.test(stream.peek())) {
                    stream.eatWhile(/[\w.%]/);
                    return ret("number", "unit");
                  } else if (stream.match(/^-[\w\\\-]+/)) {
                    stream.eatWhile(/[\w\\\-]/);
                    if (stream.match(/^\s*:/, false))
                      return ret("variable-2", "variable-definition");
                    return ret("variable-2", "variable");
                  } else if (stream.match(/^\w+-/)) {
                    return ret("meta", "meta");
                  }
                } else if (/[,+>*\/]/.test(ch)) {
                  return ret(null, "select-op");
                } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
                  return ret("qualifier", "qualifier");
                } else if (/[:;{}\[\]\(\)]/.test(ch)) {
                  return ret(null, ch);
                } else if ((ch == "u" && stream.match(/rl(-prefix)?\(/)) ||
                           (ch == "d" && stream.match("omain(")) ||
                           (ch == "r" && stream.match("egexp("))) {
                  stream.backUp(1);
                  state.tokenize = tokenParenthesized;
                  return ret("property", "word");
                } else if (/[\w\\\-]/.test(ch)) {
                  stream.eatWhile(/[\w\\\-]/);
                  return ret("property", "word");
                } else {
                  return ret(null, null);
                }
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped) {
                      if (quote == ")") stream.backUp(1);
                      break;
                    }
                    escaped = !escaped && ch == "\\";
                  }
                  if (ch == quote || !escaped && quote != ")") state.tokenize = null;
                  return ret("string", "string");
                };
              }
            
              function tokenParenthesized(stream, state) {
                stream.next(); // Must be '('
                if (!stream.match(/\s*[\"\')]/, false))
                  state.tokenize = tokenString(")");
                else
                  state.tokenize = null;
                return ret(null, "(");
              }
            
              // Context management
            
              function Context(type, indent, prev) {
                this.type = type;
                this.indent = indent;
                this.prev = prev;
              }
            
              function pushContext(state, stream, type) {
                state.context = new Context(type, stream.indentation() + indentUnit, state.context);
                return type;
              }
            
              function popContext(state) {
                state.context = state.context.prev;
                return state.context.type;
              }
            
              function pass(type, stream, state) {
                return states[state.context.type](type, stream, state);
              }
              function popAndPass(type, stream, state, n) {
                for (var i = n || 1; i > 0; i--)
                  state.context = state.context.prev;
                return pass(type, stream, state);
              }
            
              // Parser
            
              function wordAsValue(stream) {
                var word = stream.current().toLowerCase();
                if (valueKeywords.hasOwnProperty(word))
                  override = "atom";
                else if (colorKeywords.hasOwnProperty(word))
                  override = "keyword";
                else
                  override = "variable";
              }
            
              var states = {};
            
              states.top = function(type, stream, state) {
                if (type == "{") {
                  return pushContext(state, stream, "block");
                } else if (type == "}" && state.context.prev) {
                  return popContext(state);
                } else if (/@(media|supports|(-moz-)?document)/.test(type)) {
                  return pushContext(state, stream, "atBlock");
                } else if (/@(font-face|counter-style)/.test(type)) {
                  state.stateArg = type;
                  return "restricted_atBlock_before";
                } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
                  return "keyframes";
                } else if (type && type.charAt(0) == "@") {
                  return pushContext(state, stream, "at");
                } else if (type == "hash") {
                  override = "builtin";
                } else if (type == "word") {
                  override = "tag";
                } else if (type == "variable-definition") {
                  return "maybeprop";
                } else if (type == "interpolation") {
                  return pushContext(state, stream, "interpolation");
                } else if (type == ":") {
                  return "pseudo";
                } else if (allowNested && type == "(") {
                  return pushContext(state, stream, "parens");
                }
                return state.context.type;
              };
            
              states.block = function(type, stream, state) {
                if (type == "word") {
                  var word = stream.current().toLowerCase();
                  if (propertyKeywords.hasOwnProperty(word)) {
                    override = "property";
                    return "maybeprop";
                  } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
                    override = "string-2";
                    return "maybeprop";
                  } else if (allowNested) {
                    override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
                    return "block";
                  } else {
                    override += " error";
                    return "maybeprop";
                  }
                } else if (type == "meta") {
                  return "block";
                } else if (!allowNested && (type == "hash" || type == "qualifier")) {
                  override = "error";
                  return "block";
                } else {
                  return states.top(type, stream, state);
                }
              };
            
              states.maybeprop = function(type, stream, state) {
                if (type == ":") return pushContext(state, stream, "prop");
                return pass(type, stream, state);
              };
            
              states.prop = function(type, stream, state) {
                if (type == ";") return popContext(state);
                if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
                if (type == "}" || type == "{") return popAndPass(type, stream, state);
                if (type == "(") return pushContext(state, stream, "parens");
            
                if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) {
                  override += " error";
                } else if (type == "word") {
                  wordAsValue(stream);
                } else if (type == "interpolation") {
                  return pushContext(state, stream, "interpolation");
                }
                return "prop";
              };
            
              states.propBlock = function(type, _stream, state) {
                if (type == "}") return popContext(state);
                if (type == "word") { override = "property"; return "maybeprop"; }
                return state.context.type;
              };
            
              states.parens = function(type, stream, state) {
                if (type == "{" || type == "}") return popAndPass(type, stream, state);
                if (type == ")") return popContext(state);
                if (type == "(") return pushContext(state, stream, "parens");
                if (type == "interpolation") return pushContext(state, stream, "interpolation");
                if (type == "word") wordAsValue(stream);
                return "parens";
              };
            
              states.pseudo = function(type, stream, state) {
                if (type == "word") {
                  override = "variable-3";
                  return state.context.type;
                }
                return pass(type, stream, state);
              };
            
              states.atBlock = function(type, stream, state) {
                if (type == "(") return pushContext(state, stream, "atBlock_parens");
                if (type == "}") return popAndPass(type, stream, state);
                if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
            
                if (type == "word") {
                  var word = stream.current().toLowerCase();
                  if (word == "only" || word == "not" || word == "and" || word == "or")
                    override = "keyword";
                  else if (documentTypes.hasOwnProperty(word))
                    override = "tag";
                  else if (mediaTypes.hasOwnProperty(word))
                    override = "attribute";
                  else if (mediaFeatures.hasOwnProperty(word))
                    override = "property";
                  else if (propertyKeywords.hasOwnProperty(word))
                    override = "property";
                  else if (nonStandardPropertyKeywords.hasOwnProperty(word))
                    override = "string-2";
                  else if (valueKeywords.hasOwnProperty(word))
                    override = "atom";
                  else
                    override = "error";
                }
                return state.context.type;
              };
            
              states.atBlock_parens = function(type, stream, state) {
                if (type == ")") return popContext(state);
                if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
                return states.atBlock(type, stream, state);
              };
            
              states.restricted_atBlock_before = function(type, stream, state) {
                if (type == "{")
                  return pushContext(state, stream, "restricted_atBlock");
                if (type == "word" && state.stateArg == "@counter-style") {
                  override = "variable";
                  return "restricted_atBlock_before";
                }
                return pass(type, stream, state);
              };
            
              states.restricted_atBlock = function(type, stream, state) {
                if (type == "}") {
                  state.stateArg = null;
                  return popContext(state);
                }
                if (type == "word") {
                  if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
                      (state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
                    override = "error";
                  else
                    override = "property";
                  return "maybeprop";
                }
                return "restricted_atBlock";
              };
            
              states.keyframes = function(type, stream, state) {
                if (type == "word") { override = "variable"; return "keyframes"; }
                if (type == "{") return pushContext(state, stream, "top");
                return pass(type, stream, state);
              };
            
              states.at = function(type, stream, state) {
                if (type == ";") return popContext(state);
                if (type == "{" || type == "}") return popAndPass(type, stream, state);
                if (type == "word") override = "tag";
                else if (type == "hash") override = "builtin";
                return "at";
              };
            
              states.interpolation = function(type, stream, state) {
                if (type == "}") return popContext(state);
                if (type == "{" || type == ";") return popAndPass(type, stream, state);
                if (type == "word") override = "variable";
                else if (type != "variable" && type != "(" && type != ")") override = "error";
                return "interpolation";
              };
            
              return {
                startState: function(base) {
                  return {tokenize: null,
                          state: "top",
                          stateArg: null,
                          context: new Context("top", base || 0, null)};
                },
            
                token: function(stream, state) {
                  if (!state.tokenize && stream.eatSpace()) return null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style && typeof style == "object") {
                    type = style[1];
                    style = style[0];
                  }
                  override = style;
                  state.state = states[state.state](type, stream, state);
                  return override;
                },
            
                indent: function(state, textAfter) {
                  var cx = state.context, ch = textAfter && textAfter.charAt(0);
                  var indent = cx.indent;
                  if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
                  if (cx.prev &&
                      (ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "restricted_atBlock") ||
                       ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
                       ch == "{" && (cx.type == "at" || cx.type == "atBlock"))) {
                    indent = cx.indent - indentUnit;
                    cx = cx.prev;
                  }
                  return indent;
                },
            
                electricChars: "}",
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                fold: "brace"
              };
            });
            
              function keySet(array) {
                var keys = {};
                for (var i = 0; i < array.length; ++i) {
                  keys[array[i]] = true;
                }
                return keys;
              }
            
              var documentTypes_ = [
                "domain", "regexp", "url", "url-prefix"
              ], documentTypes = keySet(documentTypes_);
            
              var mediaTypes_ = [
                "all", "aural", "braille", "handheld", "print", "projection", "screen",
                "tty", "tv", "embossed"
              ], mediaTypes = keySet(mediaTypes_);
            
              var mediaFeatures_ = [
                "width", "min-width", "max-width", "height", "min-height", "max-height",
                "device-width", "min-device-width", "max-device-width", "device-height",
                "min-device-height", "max-device-height", "aspect-ratio",
                "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
                "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
                "max-color", "color-index", "min-color-index", "max-color-index",
                "monochrome", "min-monochrome", "max-monochrome", "resolution",
                "min-resolution", "max-resolution", "scan", "grid"
              ], mediaFeatures = keySet(mediaFeatures_);
            
              var propertyKeywords_ = [
                "align-content", "align-items", "align-self", "alignment-adjust",
                "alignment-baseline", "anchor-point", "animation", "animation-delay",
                "animation-direction", "animation-duration", "animation-fill-mode",
                "animation-iteration-count", "animation-name", "animation-play-state",
                "animation-timing-function", "appearance", "azimuth", "backface-visibility",
                "background", "background-attachment", "background-clip", "background-color",
                "background-image", "background-origin", "background-position",
                "background-repeat", "background-size", "baseline-shift", "binding",
                "bleed", "bookmark-label", "bookmark-level", "bookmark-state",
                "bookmark-target", "border", "border-bottom", "border-bottom-color",
                "border-bottom-left-radius", "border-bottom-right-radius",
                "border-bottom-style", "border-bottom-width", "border-collapse",
                "border-color", "border-image", "border-image-outset",
                "border-image-repeat", "border-image-slice", "border-image-source",
                "border-image-width", "border-left", "border-left-color",
                "border-left-style", "border-left-width", "border-radius", "border-right",
                "border-right-color", "border-right-style", "border-right-width",
                "border-spacing", "border-style", "border-top", "border-top-color",
                "border-top-left-radius", "border-top-right-radius", "border-top-style",
                "border-top-width", "border-width", "bottom", "box-decoration-break",
                "box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
                "caption-side", "clear", "clip", "color", "color-profile", "column-count",
                "column-fill", "column-gap", "column-rule", "column-rule-color",
                "column-rule-style", "column-rule-width", "column-span", "column-width",
                "columns", "content", "counter-increment", "counter-reset", "crop", "cue",
                "cue-after", "cue-before", "cursor", "direction", "display",
                "dominant-baseline", "drop-initial-after-adjust",
                "drop-initial-after-align", "drop-initial-before-adjust",
                "drop-initial-before-align", "drop-initial-size", "drop-initial-value",
                "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
                "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
                "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
                "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
                "font-stretch", "font-style", "font-synthesis", "font-variant",
                "font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
                "font-variant-ligatures", "font-variant-numeric", "font-variant-position",
                "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
                "grid-auto-position", "grid-auto-rows", "grid-column", "grid-column-end",
                "grid-column-start", "grid-row", "grid-row-end", "grid-row-start",
                "grid-template", "grid-template-areas", "grid-template-columns",
                "grid-template-rows", "hanging-punctuation", "height", "hyphens",
                "icon", "image-orientation", "image-rendering", "image-resolution",
                "inline-box-align", "justify-content", "left", "letter-spacing",
                "line-break", "line-height", "line-stacking", "line-stacking-ruby",
                "line-stacking-shift", "line-stacking-strategy", "list-style",
                "list-style-image", "list-style-position", "list-style-type", "margin",
                "margin-bottom", "margin-left", "margin-right", "margin-top",
                "marker-offset", "marks", "marquee-direction", "marquee-loop",
                "marquee-play-count", "marquee-speed", "marquee-style", "max-height",
                "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
                "nav-left", "nav-right", "nav-up", "object-fit", "object-position",
                "opacity", "order", "orphans", "outline",
                "outline-color", "outline-offset", "outline-style", "outline-width",
                "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
                "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
                "page", "page-break-after", "page-break-before", "page-break-inside",
                "page-policy", "pause", "pause-after", "pause-before", "perspective",
                "perspective-origin", "pitch", "pitch-range", "play-during", "position",
                "presentation-level", "punctuation-trim", "quotes", "region-break-after",
                "region-break-before", "region-break-inside", "region-fragment",
                "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
                "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
                "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
                "shape-outside", "size", "speak", "speak-as", "speak-header",
                "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
                "tab-size", "table-layout", "target", "target-name", "target-new",
                "target-position", "text-align", "text-align-last", "text-decoration",
                "text-decoration-color", "text-decoration-line", "text-decoration-skip",
                "text-decoration-style", "text-emphasis", "text-emphasis-color",
                "text-emphasis-position", "text-emphasis-style", "text-height",
                "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
                "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
                "text-wrap", "top", "transform", "transform-origin", "transform-style",
                "transition", "transition-delay", "transition-duration",
                "transition-property", "transition-timing-function", "unicode-bidi",
                "vertical-align", "visibility", "voice-balance", "voice-duration",
                "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
                "voice-volume", "volume", "white-space", "widows", "width", "word-break",
                "word-spacing", "word-wrap", "z-index",
                // SVG-specific
                "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
                "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
                "color-interpolation", "color-interpolation-filters",
                "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
                "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
                "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
                "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
                "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
                "glyph-orientation-vertical", "text-anchor", "writing-mode"
              ], propertyKeywords = keySet(propertyKeywords_);
            
              var nonStandardPropertyKeywords_ = [
                "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
                "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
                "scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",
                "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
                "searchfield-results-decoration", "zoom"
              ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
            
              var fontProperties_ = [
                "font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
                "font-stretch", "font-weight", "font-style"
              ], fontProperties = keySet(fontProperties_);
            
              var counterDescriptors_ = [
                "additive-symbols", "fallback", "negative", "pad", "prefix", "range",
                "speak-as", "suffix", "symbols", "system"
              ], counterDescriptors = keySet(counterDescriptors_);
            
              var colorKeywords_ = [
                "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
                "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
                "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
                "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
                "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
                "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
                "darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
                "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
                "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
                "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
                "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
                "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
                "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
                "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
                "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
                "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
                "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
                "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
                "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
                "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
                "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
                "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
                "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
                "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
                "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
                "whitesmoke", "yellow", "yellowgreen"
              ], colorKeywords = keySet(colorKeywords_);
            
              var valueKeywords_ = [
                "above", "absolute", "activeborder", "additive", "activecaption", "afar",
                "after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
                "always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
                "arabic-indic", "armenian", "asterisks", "attr", "auto", "avoid", "avoid-column", "avoid-page",
                "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
                "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
                "both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
                "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
                "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
                "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
                "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
                "col-resize", "collapse", "column", "compact", "condensed", "contain", "content",
                "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
                "cross", "crosshair", "currentcolor", "cursive", "cyclic", "dashed", "decimal",
                "decimal-leading-zero", "default", "default-button", "destination-atop",
                "destination-in", "destination-out", "destination-over", "devanagari",
                "disc", "discard", "disclosure-closed", "disclosure-open", "document",
                "dot-dash", "dot-dot-dash",
                "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
                "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
                "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
                "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
                "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
                "ethiopic-halehame-gez", "ethiopic-halehame-om-et",
                "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
                "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
                "ethiopic-numeric", "ew-resize", "expanded", "extends", "extra-condensed",
                "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "footnotes",
                "forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
                "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
                "help", "hidden", "hide", "higher", "highlight", "highlighttext",
                "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
                "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
                "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
                "inline-block", "inline-flex", "inline-table", "inset", "inside", "intrinsic", "invert",
                "italic", "japanese-formal", "japanese-informal", "justify", "kannada",
                "katakana", "katakana-iroha", "keep-all", "khmer",
                "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
                "landscape", "lao", "large", "larger", "left", "level", "lighter",
                "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
                "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
                "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
                "lower-roman", "lowercase", "ltr", "malayalam", "match", "matrix", "matrix3d",
                "media-controls-background", "media-current-time-display",
                "media-fullscreen-button", "media-mute-button", "media-play-button",
                "media-return-to-realtime-button", "media-rewind-button",
                "media-seek-back-button", "media-seek-forward-button", "media-slider",
                "media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
                "media-volume-slider-container", "media-volume-sliderthumb", "medium",
                "menu", "menulist", "menulist-button", "menulist-text",
                "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
                "mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize",
                "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
                "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
                "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
                "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
                "outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
                "painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter",
                "pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
                "progress", "push-button", "radial-gradient", "radio", "read-only",
                "read-write", "read-write-plaintext-only", "rectangle", "region",
                "relative", "repeat", "repeating-linear-gradient",
                "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
                "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
                "rotateZ", "round", "row-resize", "rtl", "run-in", "running",
                "s-resize", "sans-serif", "scale", "scale3d", "scaleX", "scaleY", "scaleZ",
                "scroll", "scrollbar", "se-resize", "searchfield",
                "searchfield-cancel-button", "searchfield-decoration",
                "searchfield-results-button", "searchfield-results-decoration",
                "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
                "simp-chinese-formal", "simp-chinese-informal", "single",
                "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
                "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
                "small", "small-caps", "small-caption", "smaller", "solid", "somali",
                "source-atop", "source-in", "source-out", "source-over", "space", "spell-out", "square",
                "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
                "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table",
                "table-caption", "table-cell", "table-column", "table-column-group",
                "table-footer-group", "table-header-group", "table-row", "table-row-group",
                "tamil",
                "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
                "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
                "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
                "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
                "trad-chinese-formal", "trad-chinese-informal",
                "translate", "translate3d", "translateX", "translateY", "translateZ",
                "transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
                "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
                "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
                "var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
                "visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
                "window", "windowframe", "windowtext", "words", "x-large", "x-small", "xor",
                "xx-large", "xx-small"
              ], valueKeywords = keySet(valueKeywords_);
            
              var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(propertyKeywords_)
                .concat(nonStandardPropertyKeywords_).concat(colorKeywords_).concat(valueKeywords_);
              CodeMirror.registerHelper("hintWords", "css", allWords);
            
              function tokenCComment(stream, state) {
                var maybeEnd = false, ch;
                while ((ch = stream.next()) != null) {
                  if (maybeEnd && ch == "/") {
                    state.tokenize = null;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return ["comment", "comment"];
              }
            
              CodeMirror.defineMIME("text/css", {
                documentTypes: documentTypes,
                mediaTypes: mediaTypes,
                mediaFeatures: mediaFeatures,
                propertyKeywords: propertyKeywords,
                nonStandardPropertyKeywords: nonStandardPropertyKeywords,
                fontProperties: fontProperties,
                counterDescriptors: counterDescriptors,
                colorKeywords: colorKeywords,
                valueKeywords: valueKeywords,
                tokenHooks: {
                  "/": function(stream, state) {
                    if (!stream.eat("*")) return false;
                    state.tokenize = tokenCComment;
                    return tokenCComment(stream, state);
                  }
                },
                name: "css"
              });
            
              CodeMirror.defineMIME("text/x-scss", {
                mediaTypes: mediaTypes,
                mediaFeatures: mediaFeatures,
                propertyKeywords: propertyKeywords,
                nonStandardPropertyKeywords: nonStandardPropertyKeywords,
                colorKeywords: colorKeywords,
                valueKeywords: valueKeywords,
                fontProperties: fontProperties,
                allowNested: true,
                tokenHooks: {
                  "/": function(stream, state) {
                    if (stream.eat("/")) {
                      stream.skipToEnd();
                      return ["comment", "comment"];
                    } else if (stream.eat("*")) {
                      state.tokenize = tokenCComment;
                      return tokenCComment(stream, state);
                    } else {
                      return ["operator", "operator"];
                    }
                  },
                  ":": function(stream) {
                    if (stream.match(/\s*\{/))
                      return [null, "{"];
                    return false;
                  },
                  "$": function(stream) {
                    stream.match(/^[\w-]+/);
                    if (stream.match(/^\s*:/, false))
                      return ["variable-2", "variable-definition"];
                    return ["variable-2", "variable"];
                  },
                  "#": function(stream) {
                    if (!stream.eat("{")) return false;
                    return [null, "interpolation"];
                  }
                },
                name: "css",
                helperType: "scss"
              });
            
              CodeMirror.defineMIME("text/x-less", {
                mediaTypes: mediaTypes,
                mediaFeatures: mediaFeatures,
                propertyKeywords: propertyKeywords,
                nonStandardPropertyKeywords: nonStandardPropertyKeywords,
                colorKeywords: colorKeywords,
                valueKeywords: valueKeywords,
                fontProperties: fontProperties,
                allowNested: true,
                tokenHooks: {
                  "/": function(stream, state) {
                    if (stream.eat("/")) {
                      stream.skipToEnd();
                      return ["comment", "comment"];
                    } else if (stream.eat("*")) {
                      state.tokenize = tokenCComment;
                      return tokenCComment(stream, state);
                    } else {
                      return ["operator", "operator"];
                    }
                  },
                  "@": function(stream) {
                    if (stream.eat("{")) return [null, "interpolation"];
                    if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
                    stream.eatWhile(/[\w\\\-]/);
                    if (stream.match(/^\s*:/, false))
                      return ["variable-2", "variable-definition"];
                    return ["variable-2", "variable"];
                  },
                  "&": function() {
                    return ["atom", "atom"];
                  }
                },
                name: "css",
                helperType: "less"
              });
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: CSS mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../addon/hint/show-hint.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="css.js"></script>
            <script src="../../addon/hint/show-hint.js"></script>
            <script src="../../addon/hint/css-hint.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">CSS</a>
              </ul>
            </div>
            
            <article>
            <h2>CSS mode</h2>
            <form><textarea id="code" name="code">
            /* Some example CSS */
            
            @import url("something.css");
            
            body {
              margin: 0;
              padding: 3em 6em;
              font-family: tahoma, arial, sans-serif;
              color: #000;
            }
            
            #navigation a {
              font-weight: bold;
              text-decoration: none !important;
            }
            
            h1 {
              font-size: 2.5em;
            }
            
            h2 {
              font-size: 1.7em;
            }
            
            h1:before, h2:before {
              content: "::";
            }
            
            code {
              font-family: courier, monospace;
              font-size: 80%;
              color: #418A8A;
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    extraKeys: {"Ctrl-Space": "autocomplete"},
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/css</code>, <code>text/x-scss</code> (<a href="scss.html">demo</a>), <code>text/x-less</code> (<a href="less.html">demo</a>).</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#css_*">normal</a>,  <a href="../../test/index.html#verbose,css_*">verbose</a>.</p>
            
              </article>
            
          • less.html
            <!doctype html>
            
            <title>CodeMirror: LESS mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="css.js"></script>
            <style>.CodeMirror {border: 1px solid #ddd; line-height: 1.2;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">LESS</a>
              </ul>
            </div>
            
            <article>
            <h2>LESS mode</h2>
            <form><textarea id="code" name="code">@media screen and (device-aspect-ratio: 16/9) { … }
            @media screen and (device-aspect-ratio: 1280/720) { … }
            @media screen and (device-aspect-ratio: 2560/1440) { … }
            
            html:lang(fr-be)
            
            tr:nth-child(2n+1) /* represents every odd row of an HTML table */
            
            img:nth-of-type(2n+1) { float: right; }
            img:nth-of-type(2n) { float: left; }
            
            body > h2:not(:first-of-type):not(:last-of-type)
            
            html|*:not(:link):not(:visited)
            *|*:not(:hover)
            p::first-line { text-transform: uppercase }
            
            @namespace foo url(http://www.example.com);
            foo|h1 { color: blue }  /* first rule */
            
            span[hello="Ocean"][goodbye="Land"]
            
            E[foo]{
              padding:65px;
            }
            
            input[type="search"]::-webkit-search-decoration,
            input[type="search"]::-webkit-search-cancel-button {
              -webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5
            }
            button::-moz-focus-inner,
            input::-moz-focus-inner { // Inner padding and border oddities in FF3/4
              padding: 0;
              border: 0;
            }
            .btn {
              // reset here as of 2.0.3 due to Recess property order
              border-color: #ccc;
              border-color: rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);
            }
            fieldset span button, fieldset span input[type="file"] {
              font-size:12px;
            	font-family:Arial, Helvetica, sans-serif;
            }
            
            .rounded-corners (@radius: 5px) {
              border-radius: @radius;
              -webkit-border-radius: @radius;
              -moz-border-radius: @radius;
            }
            
            @import url("something.css");
            
            @light-blue:   hsl(190, 50%, 65%);
            
            #menu {
              position: absolute;
              width: 100%;
              z-index: 3;
              clear: both;
              display: block;
              background-color: @blue;
              height: 42px;
              border-top: 2px solid lighten(@alpha-blue, 20%);
              border-bottom: 2px solid darken(@alpha-blue, 25%);
              .box-shadow(0, 1px, 8px, 0.6);
              -moz-box-shadow: 0 0 0 #000; // Because firefox sucks.
            
              &.docked {
                background-color: hsla(210, 60%, 40%, 0.4);
              }
              &:hover {
                background-color: @blue;
              }
            
              #dropdown {
                margin: 0 0 0 117px;
                padding: 0;
                padding-top: 5px;
                display: none;
                width: 190px;
                border-top: 2px solid @medium;
                color: @highlight;
                border: 2px solid darken(@medium, 25%);
                border-left-color: darken(@medium, 15%);
                border-right-color: darken(@medium, 15%);
                border-top-width: 0;
                background-color: darken(@medium, 10%);
                ul {
                  padding: 0px;  
                }
                li {
                  font-size: 14px;
                  display: block;
                  text-align: left;
                  padding: 0;
                  border: 0;
                  a {
                    display: block;
                    padding: 0px 15px;  
                    text-decoration: none;
                    color: white;  
                    &:hover {
                      background-color: darken(@medium, 15%);
                      text-decoration: none;
                    }
                  }
                }
                .border-radius(5px, bottom);
                .box-shadow(0, 6px, 8px, 0.5);
              }
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers : true,
                    matchBrackets : true,
                    mode: "text/x-less"
                  });
                </script>
            
                <p>The LESS mode is a sub-mode of the <a href="index.html">CSS mode</a> (defined in <code>css.js</code>).</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#less_*">normal</a>,  <a href="../../test/index.html#verbose,less_*">verbose</a>.</p>
              </article>
            
          • less_test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              "use strict";
            
              var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-less");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "less"); }
            
              MT("variable",
                 "[variable-2 @base]: [atom #f04615];",
                 "[qualifier .class] {",
                 "  [property width]: [variable percentage]([number 0.5]); [comment // returns `50%`]",
                 "  [property color]: [variable saturate]([variable-2 @base], [number 5%]);",
                 "}");
            
              MT("amp",
                 "[qualifier .child], [qualifier .sibling] {",
                 "  [qualifier .parent] [atom &] {",
                 "    [property color]: [keyword black];",
                 "  }",
                 "  [atom &] + [atom &] {",
                 "    [property color]: [keyword red];",
                 "  }",
                 "}");
            
              MT("mixin",
                 "[qualifier .mixin] ([variable dark]; [variable-2 @color]) {",
                 "  [property color]: [variable darken]([variable-2 @color], [number 10%]);",
                 "}",
                 "[qualifier .mixin] ([variable light]; [variable-2 @color]) {",
                 "  [property color]: [variable lighten]([variable-2 @color], [number 10%]);",
                 "}",
                 "[qualifier .mixin] ([variable-2 @_]; [variable-2 @color]) {",
                 "  [property display]: [atom block];",
                 "}",
                 "[variable-2 @switch]: [variable light];",
                 "[qualifier .class] {",
                 "  [qualifier .mixin]([variable-2 @switch]; [atom #888]);",
                 "}");
            
              MT("nest",
                 "[qualifier .one] {",
                 "  [def @media] ([property width]: [number 400px]) {",
                 "    [property font-size]: [number 1.2em];",
                 "    [def @media] [attribute print] [keyword and] [property color] {",
                 "      [property color]: [keyword blue];",
                 "    }",
                 "  }",
                 "}");
            
            
              MT("interpolation", ".@{[variable foo]} { [property font-weight]: [atom bold]; }");
            })();
            
          • scss.html
            <!doctype html>
            
            <title>CodeMirror: SCSS mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="css.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">SCSS</a>
              </ul>
            </div>
            
            <article>
            <h2>SCSS mode</h2>
            <form><textarea id="code" name="code">
            /* Some example SCSS */
            
            @import "compass/css3";
            $variable: #333;
            
            $blue: #3bbfce;
            $margin: 16px;
            
            .content-navigation {
              #nested {
                background-color: black;
              }
              border-color: $blue;
              color:
                darken($blue, 9%);
            }
            
            .border {
              padding: $margin / 2;
              margin: $margin / 2;
              border-color: $blue;
            }
            
            @mixin table-base {
              th {
                text-align: center;
                font-weight: bold;
              }
              td, th {padding: 2px}
            }
            
            table.hl {
              margin: 2em 0;
              td.ln {
                text-align: right;
              }
            }
            
            li {
              font: {
                family: serif;
                weight: bold;
                size: 1.2em;
              }
            }
            
            @mixin left($dist) {
              float: left;
              margin-left: $dist;
            }
            
            #data {
              @include left(10px);
              @include table-base;
            }
            
            .source {
              @include flow-into(target);
              border: 10px solid green;
              margin: 20px;
              width: 200px; }
            
            .new-container {
              @include flow-from(target);
              border: 10px solid red;
              margin: 20px;
              width: 200px; }
            
            body {
              margin: 0;
              padding: 3em 6em;
              font-family: tahoma, arial, sans-serif;
              color: #000;
            }
            
            @mixin yellow() {
              background: yellow;
            }
            
            .big {
              font-size: 14px;
            }
            
            .nested {
              @include border-radius(3px);
              @extend .big;
              p {
                background: whitesmoke;
                a {
                  color: red;
                }
              }
            }
            
            #navigation a {
              font-weight: bold;
              text-decoration: none !important;
            }
            
            h1 {
              font-size: 2.5em;
            }
            
            h2 {
              font-size: 1.7em;
            }
            
            h1:before, h2:before {
              content: "::";
            }
            
            code {
              font-family: courier, monospace;
              font-size: 80%;
              color: #418A8A;
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-scss"
                  });
                </script>
            
                <p>The SCSS mode is a sub-mode of the <a href="index.html">CSS mode</a> (defined in <code>css.js</code>).</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#scss_*">normal</a>,  <a href="../../test/index.html#verbose,scss_*">verbose</a>.</p>
            
              </article>
            
          • scss_test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); }
            
              MT('url_with_quotation',
                "[tag foo] { [property background]:[atom url]([string test.jpg]) }");
            
              MT('url_with_double_quotes',
                "[tag foo] { [property background]:[atom url]([string \"test.jpg\"]) }");
            
              MT('url_with_single_quotes',
                "[tag foo] { [property background]:[atom url]([string \'test.jpg\']) }");
            
              MT('string',
                "[def @import] [string \"compass/css3\"]");
            
              MT('important_keyword',
                "[tag foo] { [property background]:[atom url]([string \'test.jpg\']) [keyword !important] }");
            
              MT('variable',
                "[variable-2 $blue]:[atom #333]");
            
              MT('variable_as_attribute',
                "[tag foo] { [property color]:[variable-2 $blue] }");
            
              MT('numbers',
                "[tag foo] { [property padding]:[number 10px] [number 10] [number 10em] [number 8in] }");
            
              MT('number_percentage',
                "[tag foo] { [property width]:[number 80%] }");
            
              MT('selector',
                "[builtin #hello][qualifier .world]{}");
            
              MT('singleline_comment',
                "[comment // this is a comment]");
            
              MT('multiline_comment',
                "[comment /*foobar*/]");
            
              MT('attribute_with_hyphen',
                "[tag foo] { [property font-size]:[number 10px] }");
            
              MT('string_after_attribute',
                "[tag foo] { [property content]:[string \"::\"] }");
            
              MT('directives',
                "[def @include] [qualifier .mixin]");
            
              MT('basic_structure',
                "[tag p] { [property background]:[keyword red]; }");
            
              MT('nested_structure',
                "[tag p] { [tag a] { [property color]:[keyword red]; } }");
            
              MT('mixin',
                "[def @mixin] [tag table-base] {}");
            
              MT('number_without_semicolon',
                "[tag p] {[property width]:[number 12]}",
                "[tag a] {[property color]:[keyword red];}");
            
              MT('atom_in_nested_block',
                "[tag p] { [tag a] { [property color]:[atom #000]; } }");
            
              MT('interpolation_in_property',
                "[tag foo] { #{[variable-2 $hello]}:[number 2]; }");
            
              MT('interpolation_in_selector',
                "[tag foo]#{[variable-2 $hello]} { [property color]:[atom #000]; }");
            
              MT('interpolation_error',
                "[tag foo]#{[variable foo]} { [property color]:[atom #000]; }");
            
              MT("divide_operator",
                "[tag foo] { [property width]:[number 4] [operator /] [number 2] }");
            
              MT('nested_structure_with_id_selector',
                "[tag p] { [builtin #hello] { [property color]:[keyword red]; } }");
            
              MT('indent_mixin',
                 "[def @mixin] [tag container] (",
                 "  [variable-2 $a]: [number 10],",
                 "  [variable-2 $b]: [number 10])",
                 "{}");
            
              MT('indent_nested',
                 "[tag foo] {",
                 "  [tag bar] {",
                 "  }",
                 "}");
            
              MT('indent_parentheses',
                 "[tag foo] {",
                 "  [property color]: [variable darken]([variable-2 $blue],",
                 "    [number 9%]);",
                 "}");
            
              MT('indent_vardef',
                 "[variable-2 $name]:",
                 "  [string 'val'];",
                 "[tag tag] {",
                 "  [tag inner] {",
                 "    [property margin]: [number 3px];",
                 "  }",
                 "}");
            })();
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 2}, "css");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              // Error, because "foobarhello" is neither a known type or property, but
              // property was expected (after "and"), and it should be in parenthese.
              MT("atMediaUnknownType",
                 "[def @media] [attribute screen] [keyword and] [error foobarhello] { }");
            
              // Soft error, because "foobarhello" is not a known property or type.
              MT("atMediaUnknownProperty",
                 "[def @media] [attribute screen] [keyword and] ([error foobarhello]) { }");
            
              // Make sure nesting works with media queries
              MT("atMediaMaxWidthNested",
                 "[def @media] [attribute screen] [keyword and] ([property max-width]: [number 25px]) { [tag foo] { } }");
            
              MT("tagSelector",
                 "[tag foo] { }");
            
              MT("classSelector",
                 "[qualifier .foo-bar_hello] { }");
            
              MT("idSelector",
                 "[builtin #foo] { [error #foo] }");
            
              MT("tagSelectorUnclosed",
                 "[tag foo] { [property margin]: [number 0] } [tag bar] { }");
            
              MT("tagStringNoQuotes",
                 "[tag foo] { [property font-family]: [variable hello] [variable world]; }");
            
              MT("tagStringDouble",
                 "[tag foo] { [property font-family]: [string \"hello world\"]; }");
            
              MT("tagStringSingle",
                 "[tag foo] { [property font-family]: [string 'hello world']; }");
            
              MT("tagColorKeyword",
                 "[tag foo] {",
                 "  [property color]: [keyword black];",
                 "  [property color]: [keyword navy];",
                 "  [property color]: [keyword yellow];",
                 "}");
            
              MT("tagColorHex3",
                 "[tag foo] { [property background]: [atom #fff]; }");
            
              MT("tagColorHex6",
                 "[tag foo] { [property background]: [atom #ffffff]; }");
            
              MT("tagColorHex4",
                 "[tag foo] { [property background]: [atom&error #ffff]; }");
            
              MT("tagColorHexInvalid",
                 "[tag foo] { [property background]: [atom&error #ffg]; }");
            
              MT("tagNegativeNumber",
                 "[tag foo] { [property margin]: [number -5px]; }");
            
              MT("tagPositiveNumber",
                 "[tag foo] { [property padding]: [number 5px]; }");
            
              MT("tagVendor",
                 "[tag foo] { [meta -foo-][property box-sizing]: [meta -foo-][atom border-box]; }");
            
              MT("tagBogusProperty",
                 "[tag foo] { [property&error barhelloworld]: [number 0]; }");
            
              MT("tagTwoProperties",
                 "[tag foo] { [property margin]: [number 0]; [property padding]: [number 0]; }");
            
              MT("tagTwoPropertiesURL",
                 "[tag foo] { [property background]: [atom url]([string //example.com/foo.png]); [property padding]: [number 0]; }");
            
              MT("indent_tagSelector",
                 "[tag strong], [tag em] {",
                 "  [property background]: [atom rgba](",
                 "    [number 255], [number 255], [number 0], [number .2]",
                 "  );",
                 "}");
            
              MT("indent_atMedia",
                 "[def @media] {",
                 "  [tag foo] {",
                 "    [property color]:",
                 "      [keyword yellow];",
                 "  }",
                 "}");
            
              MT("indent_comma",
                 "[tag foo] {",
                 "  [property font-family]: [variable verdana],",
                 "    [atom sans-serif];",
                 "}");
            
              MT("indent_parentheses",
                 "[tag foo]:[variable-3 before] {",
                 "  [property background]: [atom url](",
                 "[string     blahblah]",
                 "[string     etc]",
                 "[string   ]) [keyword !important];",
                 "}");
            
              MT("font_face",
                 "[def @font-face] {",
                 "  [property font-family]: [string 'myfont'];",
                 "  [error nonsense]: [string 'abc'];",
                 "  [property src]: [atom url]([string http://blah]),",
                 "    [atom url]([string http://foo]);",
                 "}");
            
              MT("empty_url",
                 "[def @import] [tag url]() [tag screen];");
            
              MT("parens",
                 "[qualifier .foo] {",
                 "  [property background-image]: [variable fade]([atom #000], [number 20%]);",
                 "  [property border-image]: [atom linear-gradient](",
                 "    [atom to] [atom bottom],",
                 "    [variable fade]([atom #000], [number 20%]) [number 0%],",
                 "    [variable fade]([atom #000], [number 20%]) [number 100%]",
                 "  );",
                 "}");
            
              MT("css_variable",
                 ":[variable-3 root] {",
                 "  [variable-2 --main-color]: [atom #06c];",
                 "}",
                 "[tag h1][builtin #foo] {",
                 "  [property color]: [atom var]([variable-2 --main-color]);",
                 "}");
            
              MT("supports",
                 "[def @supports] ([keyword not] (([property text-align-last]: [atom justify]) [keyword or] ([meta -moz-][property text-align-last]: [atom justify])) {",
                 "  [property text-align-last]: [atom justify];",
                 "}");
            
               MT("document",
                  "[def @document] [tag url]([string http://blah]),",
                  "  [tag url-prefix]([string https://]),",
                  "  [tag domain]([string blah.com]),",
                  "  [tag regexp]([string \".*blah.+\"]) {",
                  "    [builtin #id] {",
                  "      [property background-color]: [keyword white];",
                  "    }",
                  "    [tag foo] {",
                  "      [property font-family]: [variable Verdana], [atom sans-serif];",
                  "    }",
                  "  }");
            
               MT("document_url",
                  "[def @document] [tag url]([string http://blah]) { [qualifier .class] { } }");
            
               MT("document_urlPrefix",
                  "[def @document] [tag url-prefix]([string https://]) { [builtin #id] { } }");
            
               MT("document_domain",
                  "[def @document] [tag domain]([string blah.com]) { [tag foo] { } }");
            
               MT("document_regexp",
                  "[def @document] [tag regexp]([string \".*blah.+\"]) { [builtin #id] { } }");
            
               MT("counter-style",
                  "[def @counter-style] [variable binary] {",
                  "  [property system]: [atom numeric];",
                  "  [property symbols]: [number 0] [number 1];",
                  "  [property suffix]: [string \".\"];",
                  "  [property range]: [atom infinite];",
                  "  [property speak-as]: [atom numeric];",
                  "}");
            
               MT("counter-style-additive-symbols",
                  "[def @counter-style] [variable simple-roman] {",
                  "  [property system]: [atom additive];",
                  "  [property additive-symbols]: [number 10] [variable X], [number 5] [variable V], [number 1] [variable I];",
                  "  [property range]: [number 1] [number 49];",
                  "}");
            
               MT("counter-style-use",
                  "[tag ol][qualifier .roman] { [property list-style]: [variable simple-roman]; }");
            
               MT("counter-style-symbols",
                  "[tag ol] { [property list-style]: [atom symbols]([atom cyclic] [string \"*\"] [string \"\\2020\"] [string \"\\2021\"] [string \"\\A7\"]); }");
            })();
            
        • cypher
          • cypher.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // By the Neo4j Team and contributors.
            // https://github.com/neo4j-contrib/CodeMirror
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
              var wordRegexp = function(words) {
                return new RegExp("^(?:" + words.join("|") + ")$", "i");
              };
            
              CodeMirror.defineMode("cypher", function(config) {
                var tokenBase = function(stream/*, state*/) {
                  var ch = stream.next();
                  if (ch === "\"" || ch === "'") {
                    stream.match(/.+?["']/);
                    return "string";
                  }
                  if (/[{}\(\),\.;\[\]]/.test(ch)) {
                    curPunc = ch;
                    return "node";
                  } else if (ch === "/" && stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  } else if (operatorChars.test(ch)) {
                    stream.eatWhile(operatorChars);
                    return null;
                  } else {
                    stream.eatWhile(/[_\w\d]/);
                    if (stream.eat(":")) {
                      stream.eatWhile(/[\w\d_\-]/);
                      return "atom";
                    }
                    var word = stream.current();
                    if (funcs.test(word)) return "builtin";
                    if (preds.test(word)) return "def";
                    if (keywords.test(word)) return "keyword";
                    return "variable";
                  }
                };
                var pushContext = function(state, type, col) {
                  return state.context = {
                    prev: state.context,
                    indent: state.indent,
                    col: col,
                    type: type
                  };
                };
                var popContext = function(state) {
                  state.indent = state.context.indent;
                  return state.context = state.context.prev;
                };
                var indentUnit = config.indentUnit;
                var curPunc;
                var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "keys", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "right", "round", "rtrim", "shortestPath", "sign", "sin", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "trim", "type", "upper"]);
                var preds = wordRegexp(["all", "and", "any", "has", "in", "none", "not", "or", "single", "xor"]);
                var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "distinct", "drop", "else", "end", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]);
                var operatorChars = /[*+\-<>=&|~%^]/;
            
                return {
                  startState: function(/*base*/) {
                    return {
                      tokenize: tokenBase,
                      context: null,
                      indent: 0,
                      col: 0
                    };
                  },
                  token: function(stream, state) {
                    if (stream.sol()) {
                      if (state.context && (state.context.align == null)) {
                        state.context.align = false;
                      }
                      state.indent = stream.indentation();
                    }
                    if (stream.eatSpace()) {
                      return null;
                    }
                    var style = state.tokenize(stream, state);
                    if (style !== "comment" && state.context && (state.context.align == null) && state.context.type !== "pattern") {
                      state.context.align = true;
                    }
                    if (curPunc === "(") {
                      pushContext(state, ")", stream.column());
                    } else if (curPunc === "[") {
                      pushContext(state, "]", stream.column());
                    } else if (curPunc === "{") {
                      pushContext(state, "}", stream.column());
                    } else if (/[\]\}\)]/.test(curPunc)) {
                      while (state.context && state.context.type === "pattern") {
                        popContext(state);
                      }
                      if (state.context && curPunc === state.context.type) {
                        popContext(state);
                      }
                    } else if (curPunc === "." && state.context && state.context.type === "pattern") {
                      popContext(state);
                    } else if (/atom|string|variable/.test(style) && state.context) {
                      if (/[\}\]]/.test(state.context.type)) {
                        pushContext(state, "pattern", stream.column());
                      } else if (state.context.type === "pattern" && !state.context.align) {
                        state.context.align = true;
                        state.context.col = stream.column();
                      }
                    }
                    return style;
                  },
                  indent: function(state, textAfter) {
                    var firstChar = textAfter && textAfter.charAt(0);
                    var context = state.context;
                    if (/[\]\}]/.test(firstChar)) {
                      while (context && context.type === "pattern") {
                        context = context.prev;
                      }
                    }
                    var closing = context && firstChar === context.type;
                    if (!context) return 0;
                    if (context.type === "keywords") return CodeMirror.commands.newlineAndIndent;
                    if (context.align) return context.col + (closing ? 0 : 1);
                    return context.indent + (closing ? 0 : indentUnit);
                  }
                };
              });
            
              CodeMirror.modeExtensions["cypher"] = {
                autoFormatLineBreaks: function(text) {
                  var i, lines, reProcessedPortion;
                  var lines = text.split("\n");
                  var reProcessedPortion = /\s+\b(return|where|order by|match|with|skip|limit|create|delete|set)\b\s/g;
                  for (var i = 0; i < lines.length; i++)
                    lines[i] = lines[i].replace(reProcessedPortion, " \n$1 ").trim();
                  return lines.join("\n");
                }
              };
            
              CodeMirror.defineMIME("application/x-cypher-query", "cypher");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Cypher Mode for CodeMirror</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css" />
            <link rel="stylesheet" href="../../theme/neo.css" />
            <script src="../../lib/codemirror.js"></script>
            <script src="cypher.js"></script>
            <style>
            .CodeMirror {
                border-top: 1px solid black;
                border-bottom: 1px solid black;
            }
                    </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Cypher Mode for CodeMirror</a>
              </ul>
            </div>
            
            <article>
            <h2>Cypher Mode for CodeMirror</h2>
            <form>
                        <textarea id="code" name="code">// Cypher Mode for CodeMirror, using the neo theme
            MATCH (joe { name: 'Joe' })-[:knows*2..2]-(friend_of_friend)
            WHERE NOT (joe)-[:knows]-(friend_of_friend)
            RETURN friend_of_friend.name, COUNT(*)
            ORDER BY COUNT(*) DESC , friend_of_friend.name
            </textarea>
                        </form>
                        <p><strong>MIME types defined:</strong> 
                        <code><a href="?mime=application/x-cypher-query">application/x-cypher-query</a></code>
                    </p>
            <script>
            window.onload = function() {
              var mime = 'application/x-cypher-query';
              // get mime type
              if (window.location.href.indexOf('mime=') > -1) {
                mime = window.location.href.substr(window.location.href.indexOf('mime=') + 5);
              }
              window.editor = CodeMirror.fromTextArea(document.getElementById('code'), {
                mode: mime,
                indentWithTabs: true,
                smartIndent: true,
                lineNumbers: true,
                matchBrackets : true,
                autofocus: true,
                theme: 'neo'
              });
            };
            </script>
            
            </article>
            
        • d
          • d.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("d", function(config, parserConfig) {
              var indentUnit = config.indentUnit,
                  statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
                  keywords = parserConfig.keywords || {},
                  builtin = parserConfig.builtin || {},
                  blockKeywords = parserConfig.blockKeywords || {},
                  atoms = parserConfig.atoms || {},
                  hooks = parserConfig.hooks || {},
                  multiLineStrings = parserConfig.multiLineStrings;
              var isOperatorChar = /[+\-*&%=<>!?|\/]/;
            
              var curPunc;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (hooks[ch]) {
                  var result = hooks[ch](stream, state);
                  if (result !== false) return result;
                }
                if (ch == '"' || ch == "'" || ch == "`") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return "number";
                }
                if (ch == "/") {
                  if (stream.eat("+")) {
                    state.tokenize = tokenComment;
                    return tokenNestedComment(stream, state);
                  }
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment;
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                }
                if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_\xa1-\uffff]/);
                var cur = stream.current();
                if (keywords.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "keyword";
                }
                if (builtin.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "builtin";
                }
                if (atoms.propertyIsEnumerable(cur)) return "atom";
                return "variable";
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {end = true; break;}
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !(escaped || multiLineStrings))
                    state.tokenize = null;
                  return "string";
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = null;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function tokenNestedComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = null;
                    break;
                  }
                  maybeEnd = (ch == "+");
                }
                return "comment";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
              function pushContext(state, col, type) {
                var indent = state.indented;
                if (state.context && state.context.type == "statement")
                  indent = state.context.indented;
                return state.context = new Context(indent, col, type, null, state.context);
              }
              function popContext(state) {
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}")
                  state.indented = state.context.indented;
                return state.context = state.context.prev;
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                  return {
                    tokenize: null,
                    context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true
                  };
                },
            
                token: function(stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                  }
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment" || style == "meta") return style;
                  if (ctx.align == null) ctx.align = true;
            
                  if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
                  else if (curPunc == "{") pushContext(state, stream.column(), "}");
                  else if (curPunc == "[") pushContext(state, stream.column(), "]");
                  else if (curPunc == "(") pushContext(state, stream.column(), ")");
                  else if (curPunc == "}") {
                    while (ctx.type == "statement") ctx = popContext(state);
                    if (ctx.type == "}") ctx = popContext(state);
                    while (ctx.type == "statement") ctx = popContext(state);
                  }
                  else if (curPunc == ctx.type) popContext(state);
                  else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement"))
                    pushContext(state, stream.column(), "statement");
                  state.startOfLine = false;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
                  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
                  if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
                  var closing = firstChar == ctx.type;
                  if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
                  else if (ctx.align) return ctx.column + (closing ? 0 : 1);
                  else return ctx.indented + (closing ? 0 : indentUnit);
                },
            
                electricChars: "{}"
              };
            });
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              var blockKeywords = "body catch class do else enum for foreach foreach_reverse if in interface mixin " +
                                  "out scope struct switch try union unittest version while with";
            
              CodeMirror.defineMIME("text/x-d", {
                name: "d",
                keywords: words("abstract alias align asm assert auto break case cast cdouble cent cfloat const continue " +
                                "debug default delegate delete deprecated export extern final finally function goto immutable " +
                                "import inout invariant is lazy macro module new nothrow override package pragma private " +
                                "protected public pure ref return shared short static super synchronized template this " +
                                "throw typedef typeid typeof volatile __FILE__ __LINE__ __gshared __traits __vector __parameters " +
                                blockKeywords),
                blockKeywords: words(blockKeywords),
                builtin: words("bool byte char creal dchar double float idouble ifloat int ireal long real short ubyte " +
                               "ucent uint ulong ushort wchar wstring void size_t sizediff_t"),
                atoms: words("exit failure success true false null"),
                hooks: {
                  "@": function(stream, _state) {
                    stream.eatWhile(/[\w\$_]/);
                    return "meta";
                  }
                }
              });
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: D mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="d.js"></script>
            <style>.CodeMirror {border: 2px inset #dee;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">D</a>
              </ul>
            </div>
            
            <article>
            <h2>D mode</h2>
            <form><textarea id="code" name="code">
            /* D demo code // copied from phobos/sd/metastrings.d */
            // Written in the D programming language.
            
            /**
            Templates with which to do compile-time manipulation of strings.
            
            Macros:
             WIKI = Phobos/StdMetastrings
            
            Copyright: Copyright Digital Mars 2007 - 2009.
            License:   <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
            Authors:   $(WEB digitalmars.com, Walter Bright),
                       Don Clugston
            Source:    $(PHOBOSSRC std/_metastrings.d)
            */
            /*
                     Copyright Digital Mars 2007 - 2009.
            Distributed under the Boost Software License, Version 1.0.
               (See accompanying file LICENSE_1_0.txt or copy at
                     http://www.boost.org/LICENSE_1_0.txt)
             */
            module std.metastrings;
            
            /**
            Formats constants into a string at compile time.  Analogous to $(XREF
            string,format).
            
            Parameters:
            
            A = tuple of constants, which can be strings, characters, or integral
                values.
            
            Formats:
             *    The formats supported are %s for strings, and %%
             *    for the % character.
            Example:
            ---
            import std.metastrings;
            import std.stdio;
            
            void main()
            {
              string s = Format!("Arg %s = %s", "foo", 27);
              writefln(s); // "Arg foo = 27"
            }
             * ---
             */
            
            template Format(A...)
            {
                static if (A.length == 0)
                    enum Format = "";
                else static if (is(typeof(A[0]) : const(char)[]))
                    enum Format = FormatString!(A[0], A[1..$]);
                else
                    enum Format = toStringNow!(A[0]) ~ Format!(A[1..$]);
            }
            
            template FormatString(const(char)[] F, A...)
            {
                static if (F.length == 0)
                    enum FormatString = Format!(A);
                else static if (F.length == 1)
                    enum FormatString = F[0] ~ Format!(A);
                else static if (F[0..2] == "%s")
                    enum FormatString
                        = toStringNow!(A[0]) ~ FormatString!(F[2..$],A[1..$]);
                else static if (F[0..2] == "%%")
                    enum FormatString = "%" ~ FormatString!(F[2..$],A);
                else
                {
                    static assert(F[0] != '%', "unrecognized format %" ~ F[1]);
                    enum FormatString = F[0] ~ FormatString!(F[1..$],A);
                }
            }
            
            unittest
            {
                auto s = Format!("hel%slo", "world", -138, 'c', true);
                assert(s == "helworldlo-138ctrue", "[" ~ s ~ "]");
            }
            
            /**
             * Convert constant argument to a string.
             */
            
            template toStringNow(ulong v)
            {
                static if (v < 10)
                    enum toStringNow = "" ~ cast(char)(v + '0');
                else
                    enum toStringNow = toStringNow!(v / 10) ~ toStringNow!(v % 10);
            }
            
            unittest
            {
                static assert(toStringNow!(1uL << 62) == "4611686018427387904");
            }
            
            /// ditto
            template toStringNow(long v)
            {
                static if (v < 0)
                    enum toStringNow = "-" ~ toStringNow!(cast(ulong) -v);
                else
                    enum toStringNow = toStringNow!(cast(ulong) v);
            }
            
            unittest
            {
                static assert(toStringNow!(0x100000000) == "4294967296");
                static assert(toStringNow!(-138L) == "-138");
            }
            
            /// ditto
            template toStringNow(uint U)
            {
                enum toStringNow = toStringNow!(cast(ulong)U);
            }
            
            /// ditto
            template toStringNow(int I)
            {
                enum toStringNow = toStringNow!(cast(long)I);
            }
            
            /// ditto
            template toStringNow(bool B)
            {
                enum toStringNow = B ? "true" : "false";
            }
            
            /// ditto
            template toStringNow(string S)
            {
                enum toStringNow = S;
            }
            
            /// ditto
            template toStringNow(char C)
            {
                enum toStringNow = "" ~ C;
            }
            
            
            /********
             * Parse unsigned integer literal from the start of string s.
             * returns:
             *    .value = the integer literal as a string,
             *    .rest = the string following the integer literal
             * Otherwise:
             *    .value = null,
             *    .rest = s
             */
            
            template parseUinteger(const(char)[] s)
            {
                static if (s.length == 0)
                {
                    enum value = "";
                    enum rest = "";
                }
                else static if (s[0] >= '0' && s[0] <= '9')
                {
                    enum value = s[0] ~ parseUinteger!(s[1..$]).value;
                    enum rest = parseUinteger!(s[1..$]).rest;
                }
                else
                {
                    enum value = "";
                    enum rest = s;
                }
            }
            
            /********
            Parse integer literal optionally preceded by $(D '-') from the start
            of string $(D s).
            
            Returns:
               .value = the integer literal as a string,
               .rest = the string following the integer literal
            
            Otherwise:
               .value = null,
               .rest = s
            */
            
            template parseInteger(const(char)[] s)
            {
                static if (s.length == 0)
                {
                    enum value = "";
                    enum rest = "";
                }
                else static if (s[0] >= '0' && s[0] <= '9')
                {
                    enum value = s[0] ~ parseUinteger!(s[1..$]).value;
                    enum rest = parseUinteger!(s[1..$]).rest;
                }
                else static if (s.length >= 2 &&
                        s[0] == '-' && s[1] >= '0' && s[1] <= '9')
                {
                    enum value = s[0..2] ~ parseUinteger!(s[2..$]).value;
                    enum rest = parseUinteger!(s[2..$]).rest;
                }
                else
                {
                    enum value = "";
                    enum rest = s;
                }
            }
            
            unittest
            {
                assert(parseUinteger!("1234abc").value == "1234");
                assert(parseUinteger!("1234abc").rest == "abc");
                assert(parseInteger!("-1234abc").value == "-1234");
                assert(parseInteger!("-1234abc").rest == "abc");
            }
            
            /**
            Deprecated aliases held for backward compatibility.
            */
            deprecated alias toStringNow ToString;
            /// Ditto
            deprecated alias parseUinteger ParseUinteger;
            /// Ditto
            deprecated alias parseUinteger ParseInteger;
            
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    indentUnit: 4,
                    mode: "text/x-d"
                  });
                </script>
            
                <p>Simple mode that handle D-Syntax (<a href="http://www.dlang.org">DLang Homepage</a>).</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-d</code>
                .</p>
              </article>
            
        • dart
          • dart.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../clike/clike"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../clike/clike"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var keywords = ("this super static final const abstract class extends external factory " +
                "implements get native operator set typedef with enum throw rethrow " +
                "assert break case continue default in return new deferred async await " +
                "try catch finally do else for if switch while import library export " +
                "part of show hide is").split(" ");
              var blockKeywords = "try catch finally do else for if switch while".split(" ");
              var atoms = "true false null".split(" ");
              var builtins = "void bool num int double dynamic var String".split(" ");
            
              function set(words) {
                var obj = {};
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              CodeMirror.defineMIME("application/dart", {
                name: "clike",
                keywords: set(keywords),
                multiLineStrings: true,
                blockKeywords: set(blockKeywords),
                builtin: set(builtins),
                atoms: set(atoms),
                hooks: {
                  "@": function(stream) {
                    stream.eatWhile(/[\w\$_]/);
                    return "meta";
                  }
                }
              });
            
              CodeMirror.registerHelper("hintWords", "application/dart", keywords.concat(atoms).concat(builtins));
            
              // This is needed to make loading through meta.js work.
              CodeMirror.defineMode("dart", function(conf) {
                return CodeMirror.getMode(conf, "application/dart");
              }, "clike");
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Dart mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../clike/clike.js"></script>
            <script src="dart.js"></script>
            <style>.CodeMirror {border: 1px solid #dee;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Dart</a>
              </ul>
            </div>
            
            <article>
            <h2>Dart mode</h2>
            <form>
            <textarea id="code" name="code">
            import 'dart:math' show Random;
            
            void main() {
              print(new Die(n: 12).roll());
            }
            
            // Define a class.
            class Die {
              // Define a class variable.
              static Random shaker = new Random();
            
              // Define instance variables.
              int sides, value;
            
              // Define a method using shorthand syntax.
              String toString() => '$value';
            
              // Define a constructor.
              Die({int n: 6}) {
                if (4 <= n && n <= 20) {
                  sides = n;
                } else {
                  // Support for errors and exceptions.
                  throw new ArgumentError(/* */);
                }
              }
            
              // Define an instance method.
              int roll() {
                return value = shaker.nextInt(sides) + 1;
              }
            }
            </textarea>
            </form>
            
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                lineNumbers: true,
                mode: "application/dart"
              });
            </script>
            
            </article>
            
        • diff
          • diff.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("diff", function() {
            
              var TOKEN_NAMES = {
                '+': 'positive',
                '-': 'negative',
                '@': 'meta'
              };
            
              return {
                token: function(stream) {
                  var tw_pos = stream.string.search(/[\t ]+?$/);
            
                  if (!stream.sol() || tw_pos === 0) {
                    stream.skipToEnd();
                    return ("error " + (
                      TOKEN_NAMES[stream.string.charAt(0)] || '')).replace(/ $/, '');
                  }
            
                  var token_name = TOKEN_NAMES[stream.peek()] || stream.skipToEnd();
            
                  if (tw_pos === -1) {
                    stream.skipToEnd();
                  } else {
                    stream.pos = tw_pos;
                  }
            
                  return token_name;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-diff", "diff");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Diff mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="diff.js"></script>
            <style>
                  .CodeMirror {border-top: 1px solid #ddd; border-bottom: 1px solid #ddd;}
                  span.cm-meta {color: #a0b !important;}
                  span.cm-error { background-color: black; opacity: 0.4;}
                  span.cm-error.cm-string { background-color: red; }
                  span.cm-error.cm-tag { background-color: #2b2; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Diff</a>
              </ul>
            </div>
            
            <article>
            <h2>Diff mode</h2>
            <form><textarea id="code" name="code">
            diff --git a/index.html b/index.html
            index c1d9156..7764744 100644
            --- a/index.html
            +++ b/index.html
            @@ -95,7 +95,8 @@ StringStream.prototype = {
                 <script>
                   var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                     lineNumbers: true,
            -        autoMatchBrackets: true
            +        autoMatchBrackets: true,
            +      onGutterClick: function(x){console.log(x);}
                   });
                 </script>
               </body>
            diff --git a/lib/codemirror.js b/lib/codemirror.js
            index 04646a9..9a39cc7 100644
            --- a/lib/codemirror.js
            +++ b/lib/codemirror.js
            @@ -399,10 +399,16 @@ var CodeMirror = (function() {
                 }
             
                 function onMouseDown(e) {
            -      var start = posFromMouse(e), last = start;    
            +      var start = posFromMouse(e), last = start, target = e.target();
                   if (!start) return;
                   setCursor(start.line, start.ch, false);
                   if (e.button() != 1) return;
            +      if (target.parentNode == gutter) {    
            +        if (options.onGutterClick)
            +          options.onGutterClick(indexOf(gutter.childNodes, target) + showingFrom);
            +        return;
            +      }
            +
                   if (!focused) onFocus();
             
                   e.stop();
            @@ -808,7 +814,7 @@ var CodeMirror = (function() {
                   for (var i = showingFrom; i < showingTo; ++i) {
                     var marker = lines[i].gutterMarker;
                     if (marker) html.push('<div class="' + marker.style + '">' + htmlEscape(marker.text) + '</div>');
            -        else html.push("<div>" + (options.lineNumbers ? i + 1 : "\u00a0") + "</div>");
            +        else html.push("<div>" + (options.lineNumbers ? i + options.firstLineNumber : "\u00a0") + "</div>");
                   }
                   gutter.style.display = "none"; // TODO test whether this actually helps
                   gutter.innerHTML = html.join("");
            @@ -1371,10 +1377,8 @@ var CodeMirror = (function() {
                     if (option == "parser") setParser(value);
                     else if (option === "lineNumbers") setLineNumbers(value);
                     else if (option === "gutter") setGutter(value);
            -        else if (option === "readOnly") options.readOnly = value;
            -        else if (option === "indentUnit") {options.indentUnit = indentUnit = value; setParser(options.parser);}
            -        else if (/^(?:enterMode|tabMode|indentWithTabs|readOnly|autoMatchBrackets|undoDepth)$/.test(option)) options[option] = value;
            -        else throw new Error("Can't set option " + option);
            +        else if (option === "indentUnit") {options.indentUnit = value; setParser(options.parser);}
            +        else options[option] = value;
                   },
                   cursorCoords: cursorCoords,
                   undo: operation(undo),
            @@ -1402,7 +1406,8 @@ var CodeMirror = (function() {
                   replaceRange: operation(replaceRange),
             
                   operation: function(f){return operation(f)();},
            -      refresh: function(){updateDisplay([{from: 0, to: lines.length}]);}
            +      refresh: function(){updateDisplay([{from: 0, to: lines.length}]);},
            +      getInputField: function(){return input;}
                 };
                 return instance;
               }
            @@ -1420,6 +1425,7 @@ var CodeMirror = (function() {
                 readOnly: false,
                 onChange: null,
                 onCursorActivity: null,
            +    onGutterClick: null,
                 autoMatchBrackets: false,
                 workTime: 200,
                 workDelay: 300,
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-diff</code>.</p>
            
              </article>
            
        • django
          • django.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"),
                    require("../../addon/mode/overlay"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed",
                        "../../addon/mode/overlay"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("django:inner", function() {
                var keywords = ["block", "endblock", "for", "endfor", "true", "false",
                                "loop", "none", "self", "super", "if", "endif", "as",
                                "else", "import", "with", "endwith", "without", "context", "ifequal", "endifequal",
                                "ifnotequal", "endifnotequal", "extends", "include", "load", "comment",
                                "endcomment", "empty", "url", "static", "trans", "blocktrans", "now", "regroup",
                                "lorem", "ifchanged", "endifchanged", "firstof", "debug", "cycle", "csrf_token",
                                "autoescape", "endautoescape", "spaceless", "ssi", "templatetag",
                                "verbatim", "endverbatim", "widthratio"],
                    filters = ["add", "addslashes", "capfirst", "center", "cut", "date",
                               "default", "default_if_none", "dictsort",
                               "dictsortreversed", "divisibleby", "escape", "escapejs",
                               "filesizeformat", "first", "floatformat", "force_escape",
                               "get_digit", "iriencode", "join", "last", "length",
                               "length_is", "linebreaks", "linebreaksbr", "linenumbers",
                               "ljust", "lower", "make_list", "phone2numeric", "pluralize",
                               "pprint", "random", "removetags", "rjust", "safe",
                               "safeseq", "slice", "slugify", "stringformat", "striptags",
                               "time", "timesince", "timeuntil", "title", "truncatechars",
                               "truncatechars_html", "truncatewords", "truncatewords_html",
                               "unordered_list", "upper", "urlencode", "urlize",
                               "urlizetrunc", "wordcount", "wordwrap", "yesno"],
                    operators = ["==", "!=", "<", ">", "<=", ">=", "in", "not", "or", "and"];
            
                keywords = new RegExp("^\\b(" + keywords.join("|") + ")\\b");
                filters = new RegExp("^\\b(" + filters.join("|") + ")\\b");
                operators = new RegExp("^\\b(" + operators.join("|") + ")\\b");
            
                // We have to return "null" instead of null, in order to avoid string
                // styling as the default, when using Django templates inside HTML
                // element attributes
                function tokenBase (stream, state) {
                  // Attempt to identify a variable, template or comment tag respectively
                  if (stream.match("{{")) {
                    state.tokenize = inVariable;
                    return "tag";
                  } else if (stream.match("{%")) {
                    state.tokenize = inTag;
                    return "tag";
                  } else if (stream.match("{#")) {
                    state.tokenize = inComment;
                    return "comment";
                  }
            
                  // Ignore completely any stream series that do not match the
                  // Django template opening tags.
                  while (stream.next() != null && !stream.match("{{", false) && !stream.match("{%", false)) {}
                  return null;
                }
            
                // A string can be included in either single or double quotes (this is
                // the delimeter). Mark everything as a string until the start delimeter
                // occurs again.
                function inString (delimeter, previousTokenizer) {
                  return function (stream, state) {
                    if (!state.escapeNext && stream.eat(delimeter)) {
                      state.tokenize = previousTokenizer;
                    } else {
                      if (state.escapeNext) {
                        state.escapeNext = false;
                      }
            
                      var ch = stream.next();
            
                      // Take into account the backslash for escaping characters, such as
                      // the string delimeter.
                      if (ch == "\\") {
                        state.escapeNext = true;
                      }
                    }
            
                    return "string";
                  };
                }
            
                // Apply Django template variable syntax highlighting
                function inVariable (stream, state) {
                  // Attempt to match a dot that precedes a property
                  if (state.waitDot) {
                    state.waitDot = false;
            
                    if (stream.peek() != ".") {
                      return "null";
                    }
            
                    // Dot folowed by a non-word character should be considered an error.
                    if (stream.match(/\.\W+/)) {
                      return "error";
                    } else if (stream.eat(".")) {
                      state.waitProperty = true;
                      return "null";
                    } else {
                      throw Error ("Unexpected error while waiting for property.");
                    }
                  }
            
                  // Attempt to match a pipe that precedes a filter
                  if (state.waitPipe) {
                    state.waitPipe = false;
            
                    if (stream.peek() != "|") {
                      return "null";
                    }
            
                    // Pipe folowed by a non-word character should be considered an error.
                    if (stream.match(/\.\W+/)) {
                      return "error";
                    } else if (stream.eat("|")) {
                      state.waitFilter = true;
                      return "null";
                    } else {
                      throw Error ("Unexpected error while waiting for filter.");
                    }
                  }
            
                  // Highlight properties
                  if (state.waitProperty) {
                    state.waitProperty = false;
                    if (stream.match(/\b(\w+)\b/)) {
                      state.waitDot = true;  // A property can be followed by another property
                      state.waitPipe = true;  // A property can be followed by a filter
                      return "property";
                    }
                  }
            
                  // Highlight filters
                  if (state.waitFilter) {
                      state.waitFilter = false;
                    if (stream.match(filters)) {
                      return "variable-2";
                    }
                  }
            
                  // Ignore all white spaces
                  if (stream.eatSpace()) {
                    state.waitProperty = false;
                    return "null";
                  }
            
                  // Identify numbers
                  if (stream.match(/\b\d+(\.\d+)?\b/)) {
                    return "number";
                  }
            
                  // Identify strings
                  if (stream.match("'")) {
                    state.tokenize = inString("'", state.tokenize);
                    return "string";
                  } else if (stream.match('"')) {
                    state.tokenize = inString('"', state.tokenize);
                    return "string";
                  }
            
                  // Attempt to find the variable
                  if (stream.match(/\b(\w+)\b/) && !state.foundVariable) {
                    state.waitDot = true;
                    state.waitPipe = true;  // A property can be followed by a filter
                    return "variable";
                  }
            
                  // If found closing tag reset
                  if (stream.match("}}")) {
                    state.waitProperty = null;
                    state.waitFilter = null;
                    state.waitDot = null;
                    state.waitPipe = null;
                    state.tokenize = tokenBase;
                    return "tag";
                  }
            
                  // If nothing was found, advance to the next character
                  stream.next();
                  return "null";
                }
            
                function inTag (stream, state) {
                  // Attempt to match a dot that precedes a property
                  if (state.waitDot) {
                    state.waitDot = false;
            
                    if (stream.peek() != ".") {
                      return "null";
                    }
            
                    // Dot folowed by a non-word character should be considered an error.
                    if (stream.match(/\.\W+/)) {
                      return "error";
                    } else if (stream.eat(".")) {
                      state.waitProperty = true;
                      return "null";
                    } else {
                      throw Error ("Unexpected error while waiting for property.");
                    }
                  }
            
                  // Attempt to match a pipe that precedes a filter
                  if (state.waitPipe) {
                    state.waitPipe = false;
            
                    if (stream.peek() != "|") {
                      return "null";
                    }
            
                    // Pipe folowed by a non-word character should be considered an error.
                    if (stream.match(/\.\W+/)) {
                      return "error";
                    } else if (stream.eat("|")) {
                      state.waitFilter = true;
                      return "null";
                    } else {
                      throw Error ("Unexpected error while waiting for filter.");
                    }
                  }
            
                  // Highlight properties
                  if (state.waitProperty) {
                    state.waitProperty = false;
                    if (stream.match(/\b(\w+)\b/)) {
                      state.waitDot = true;  // A property can be followed by another property
                      state.waitPipe = true;  // A property can be followed by a filter
                      return "property";
                    }
                  }
            
                  // Highlight filters
                  if (state.waitFilter) {
                      state.waitFilter = false;
                    if (stream.match(filters)) {
                      return "variable-2";
                    }
                  }
            
                  // Ignore all white spaces
                  if (stream.eatSpace()) {
                    state.waitProperty = false;
                    return "null";
                  }
            
                  // Identify numbers
                  if (stream.match(/\b\d+(\.\d+)?\b/)) {
                    return "number";
                  }
            
                  // Identify strings
                  if (stream.match("'")) {
                    state.tokenize = inString("'", state.tokenize);
                    return "string";
                  } else if (stream.match('"')) {
                    state.tokenize = inString('"', state.tokenize);
                    return "string";
                  }
            
                  // Attempt to match an operator
                  if (stream.match(operators)) {
                    return "operator";
                  }
            
                  // Attempt to match a keyword
                  var keywordMatch = stream.match(keywords);
                  if (keywordMatch) {
                    if (keywordMatch[0] == "comment") {
                      state.blockCommentTag = true;
                    }
                    return "keyword";
                  }
            
                  // Attempt to match a variable
                  if (stream.match(/\b(\w+)\b/)) {
                    state.waitDot = true;
                    state.waitPipe = true;  // A property can be followed by a filter
                    return "variable";
                  }
            
                  // If found closing tag reset
                  if (stream.match("%}")) {
                    state.waitProperty = null;
                    state.waitFilter = null;
                    state.waitDot = null;
                    state.waitPipe = null;
                    // If the tag that closes is a block comment tag, we want to mark the
                    // following code as comment, until the tag closes.
                    if (state.blockCommentTag) {
                      state.blockCommentTag = false;  // Release the "lock"
                      state.tokenize = inBlockComment;
                    } else {
                      state.tokenize = tokenBase;
                    }
                    return "tag";
                  }
            
                  // If nothing was found, advance to the next character
                  stream.next();
                  return "null";
                }
            
                // Mark everything as comment inside the tag and the tag itself.
                function inComment (stream, state) {
                  if (stream.match("#}")) {
                    state.tokenize = tokenBase;
                  }
                  return "comment";
                }
            
                // Mark everything as a comment until the `blockcomment` tag closes.
                function inBlockComment (stream, state) {
                  if (stream.match(/\{%\s*endcomment\s*%\}/, false)) {
                    state.tokenize = inTag;
                    stream.match("{%");
                    return "tag";
                  } else {
                    stream.next();
                    return "comment";
                  }
                }
            
                return {
                  startState: function () {
                    return {tokenize: tokenBase};
                  },
                  token: function (stream, state) {
                    return state.tokenize(stream, state);
                  },
                  blockCommentStart: "{% comment %}",
                  blockCommentEnd: "{% endcomment %}"
                };
              });
            
              CodeMirror.defineMode("django", function(config) {
                var htmlBase = CodeMirror.getMode(config, "text/html");
                var djangoInner = CodeMirror.getMode(config, "django:inner");
                return CodeMirror.overlayMode(htmlBase, djangoInner);
              });
            
              CodeMirror.defineMIME("text/x-django", "django");
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Django template mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/mdn-like.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/mode/overlay.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="django.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Django</a>
              </ul>
            </div>
            
            <article>
            <h2>Django template mode</h2>
            <form><textarea id="code" name="code">
            <!doctype html>
            <html>
              <head>
                <title>My Django web application</title>
              </head>
              <body>
                <h1>
                  {{ page.title|capfirst }}
                </h1>
                <ul class="my-list">
                  {# traverse a list of items and produce links to their views. #}
                  {% for item in items %}
                  <li>
                    <a href="{% url 'item_view' item.name|slugify %}">
                      {{ item.name }}
                    </a>
                  </li>
                  {% empty %}
                  <li>You have no items in your list.</li>
                  {% endfor %}
                </ul>
                {% comment "this is a forgotten footer" %}
                <footer></footer>
                {% endcomment %}
              </body>
            </html>
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "django",
                    indentUnit: 2,
                    indentWithTabs: true,
                    theme: "mdn-like"
                  });
                </script>
            
                <p>Mode for HTML with embedded Django template markup.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-django</code></p>
              </article>
            
        • dockerfile
          • dockerfile.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../../addon/mode/simple"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../../addon/mode/simple"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              // Collect all Dockerfile directives
              var instructions = ["from", "maintainer", "run", "cmd", "expose", "env",
                                  "add", "copy", "entrypoint", "volume", "user",
                                  "workdir", "onbuild"],
                  instructionRegex = "(" + instructions.join('|') + ")",
                  instructionOnlyLine = new RegExp(instructionRegex + "\\s*$", "i"),
                  instructionWithArguments = new RegExp(instructionRegex + "(\\s+)", "i");
            
              CodeMirror.defineSimpleMode("dockerfile", {
                start: [
                  // Block comment: This is a line starting with a comment
                  {
                    regex: /#.*$/,
                    token: "comment"
                  },
                  // Highlight an instruction without any arguments (for convenience)
                  {
                    regex: instructionOnlyLine,
                    token: "variable-2"
                  },
                  // Highlight an instruction followed by arguments
                  {
                    regex: instructionWithArguments,
                    token: ["variable-2", null],
                    next: "arguments"
                  },
                  {
                    regex: /./,
                    token: null
                  }
                ],
                arguments: [
                  {
                    // Line comment without instruction arguments is an error
                    regex: /#.*$/,
                    token: "error",
                    next: "start"
                  },
                  {
                    regex: /[^#]+\\$/,
                    token: null
                  },
                  {
                    // Match everything except for the inline comment
                    regex: /[^#]+/,
                    token: null,
                    next: "start"
                  },
                  {
                    regex: /$/,
                    token: null,
                    next: "start"
                  },
                  // Fail safe return to start
                  {
                    token: null,
                    next: "start"
                  }
                ]
              });
            
              CodeMirror.defineMIME("text/x-dockerfile", "dockerfile");
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Dockerfile mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/mode/simple.js"></script>
            <script src="dockerfile.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Dockerfile</a>
              </ul>
            </div>
            
            <article>
            <h2>Dockerfile mode</h2>
            <form><textarea id="code" name="code"># Install Ghost blogging platform and run development environment
            #
            # VERSION 1.0.0
            
            FROM ubuntu:12.10
            MAINTAINER Amer Grgic "amer@livebyt.es"
            WORKDIR /data/ghost
            
            # Install dependencies for nginx installation
            RUN apt-get update
            RUN apt-get install -y python g++ make software-properties-common --force-yes
            RUN add-apt-repository ppa:chris-lea/node.js
            RUN apt-get update
            # Install unzip
            RUN apt-get install -y unzip
            # Install curl
            RUN apt-get install -y curl
            # Install nodejs & npm
            RUN apt-get install -y rlwrap
            RUN apt-get install -y nodejs 
            # Download Ghost v0.4.1
            RUN curl -L https://ghost.org/zip/ghost-latest.zip -o /tmp/ghost.zip
            # Unzip Ghost zip to /data/ghost
            RUN unzip -uo /tmp/ghost.zip -d /data/ghost
            # Add custom config js to /data/ghost
            ADD ./config.example.js /data/ghost/config.js
            # Install Ghost with NPM
            RUN cd /data/ghost/ && npm install --production
            # Expose port 2368
            EXPOSE 2368
            # Run Ghost
            CMD ["npm","start"]
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "dockerfile"
                  });
                </script>
            
                <p>Dockerfile syntax highlighting for CodeMirror. Depends on
                the <a href="../../demo/simplemode.html">simplemode</a> addon.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-dockerfile</code></p>
              </article>
            
        • dtd
          • dtd.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*
              DTD mode
              Ported to CodeMirror by Peter Kroon <plakroon@gmail.com>
              Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues
              GitHub: @peterkroon
            */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("dtd", function(config) {
              var indentUnit = config.indentUnit, type;
              function ret(style, tp) {type = tp; return style;}
            
              function tokenBase(stream, state) {
                var ch = stream.next();
            
                if (ch == "<" && stream.eat("!") ) {
                  if (stream.eatWhile(/[\-]/)) {
                    state.tokenize = tokenSGMLComment;
                    return tokenSGMLComment(stream, state);
                  } else if (stream.eatWhile(/[\w]/)) return ret("keyword", "doindent");
                } else if (ch == "<" && stream.eat("?")) { //xml declaration
                  state.tokenize = inBlock("meta", "?>");
                  return ret("meta", ch);
                } else if (ch == "#" && stream.eatWhile(/[\w]/)) return ret("atom", "tag");
                else if (ch == "|") return ret("keyword", "seperator");
                else if (ch.match(/[\(\)\[\]\-\.,\+\?>]/)) return ret(null, ch);//if(ch === ">") return ret(null, "endtag"); else
                else if (ch.match(/[\[\]]/)) return ret("rule", ch);
                else if (ch == "\"" || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                } else if (stream.eatWhile(/[a-zA-Z\?\+\d]/)) {
                  var sc = stream.current();
                  if( sc.substr(sc.length-1,sc.length).match(/\?|\+/) !== null )stream.backUp(1);
                  return ret("tag", "tag");
                } else if (ch == "%" || ch == "*" ) return ret("number", "number");
                else {
                  stream.eatWhile(/[\w\\\-_%.{,]/);
                  return ret(null, null);
                }
              }
            
              function tokenSGMLComment(stream, state) {
                var dashes = 0, ch;
                while ((ch = stream.next()) != null) {
                  if (dashes >= 2 && ch == ">") {
                    state.tokenize = tokenBase;
                    break;
                  }
                  dashes = (ch == "-") ? dashes + 1 : 0;
                }
                return ret("comment", "comment");
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    escaped = !escaped && ch == "\\";
                  }
                  return ret("string", "tag");
                };
              }
            
              function inBlock(style, terminator) {
                return function(stream, state) {
                  while (!stream.eol()) {
                    if (stream.match(terminator)) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    stream.next();
                  }
                  return style;
                };
              }
            
              return {
                startState: function(base) {
                  return {tokenize: tokenBase,
                          baseIndent: base || 0,
                          stack: []};
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
            
                  var context = state.stack[state.stack.length-1];
                  if (stream.current() == "[" || type === "doindent" || type == "[") state.stack.push("rule");
                  else if (type === "endtag") state.stack[state.stack.length-1] = "endtag";
                  else if (stream.current() == "]" || type == "]" || (type == ">" && context == "rule")) state.stack.pop();
                  else if (type == "[") state.stack.push("[");
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var n = state.stack.length;
            
                  if( textAfter.match(/\]\s+|\]/) )n=n-1;
                  else if(textAfter.substr(textAfter.length-1, textAfter.length) === ">"){
                    if(textAfter.substr(0,1) === "<")n;
                    else if( type == "doindent" && textAfter.length > 1 )n;
                    else if( type == "doindent")n--;
                    else if( type == ">" && textAfter.length > 1)n;
                    else if( type == "tag" && textAfter !== ">")n;
                    else if( type == "tag" && state.stack[state.stack.length-1] == "rule")n--;
                    else if( type == "tag")n++;
                    else if( textAfter === ">" && state.stack[state.stack.length-1] == "rule" && type === ">")n--;
                    else if( textAfter === ">" && state.stack[state.stack.length-1] == "rule")n;
                    else if( textAfter.substr(0,1) !== "<" && textAfter.substr(0,1) === ">" )n=n-1;
                    else if( textAfter === ">")n;
                    else n=n-1;
                    //over rule them all
                    if(type == null || type == "]")n--;
                  }
            
                  return state.baseIndent + n * indentUnit;
                },
            
                electricChars: "]>"
              };
            });
            
            CodeMirror.defineMIME("application/xml-dtd", "dtd");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: DTD mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="dtd.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">DTD</a>
              </ul>
            </div>
            
            <article>
            <h2>DTD mode</h2>
            <form><textarea id="code" name="code"><?xml version="1.0" encoding="UTF-8"?>
            
            <!ATTLIST title
              xmlns	CDATA	#FIXED	"http://docbook.org/ns/docbook"
              role	CDATA	#IMPLIED
              %db.common.attributes;
              %db.common.linking.attributes;
            >
            
            <!--
              Try: http://docbook.org/xml/5.0/dtd/docbook.dtd
            -->
            
            <!DOCTYPE xsl:stylesheet
              [
                <!ENTITY nbsp   "&amp;#160;">
                <!ENTITY copy   "&amp;#169;">
                <!ENTITY reg    "&amp;#174;">
                <!ENTITY trade  "&amp;#8482;">
                <!ENTITY mdash  "&amp;#8212;">
                <!ENTITY ldquo  "&amp;#8220;">
                <!ENTITY rdquo  "&amp;#8221;">
                <!ENTITY pound  "&amp;#163;">
                <!ENTITY yen    "&amp;#165;">
                <!ENTITY euro   "&amp;#8364;">
                <!ENTITY mathml "http://www.w3.org/1998/Math/MathML">
              ]
            >
            
            <!ELEMENT title (#PCDATA|inlinemediaobject|remark|superscript|subscript|xref|link|olink|anchor|biblioref|alt|annotation|indexterm|abbrev|acronym|date|emphasis|footnote|footnoteref|foreignphrase|phrase|quote|wordasword|firstterm|glossterm|coref|trademark|productnumber|productname|database|application|hardware|citation|citerefentry|citetitle|citebiblioid|author|person|personname|org|orgname|editor|jobtitle|replaceable|package|parameter|termdef|nonterminal|systemitem|option|optional|property|inlineequation|tag|markup|token|symbol|literal|code|constant|email|uri|guiicon|guibutton|guimenuitem|guimenu|guisubmenu|guilabel|menuchoice|mousebutton|keycombo|keycap|keycode|keysym|shortcut|accel|prompt|envar|filename|command|computeroutput|userinput|function|varname|returnvalue|type|classname|exceptionname|interfacename|methodname|modifier|initializer|ooclass|ooexception|oointerface|errorcode|errortext|errorname|errortype)*>
            
            <!ENTITY % db.common.attributes "
              xml:id	ID	#IMPLIED
              version	CDATA	#IMPLIED
              xml:lang	CDATA	#IMPLIED
              xml:base	CDATA	#IMPLIED
              remap	CDATA	#IMPLIED
              xreflabel	CDATA	#IMPLIED
              revisionflag	(changed|added|deleted|off)	#IMPLIED
              dir	(ltr|rtl|lro|rlo)	#IMPLIED
              arch	CDATA	#IMPLIED
              audience	CDATA	#IMPLIED
              condition	CDATA	#IMPLIED
              conformance	CDATA	#IMPLIED
              os	CDATA	#IMPLIED
              revision	CDATA	#IMPLIED
              security	CDATA	#IMPLIED
              userlevel	CDATA	#IMPLIED
              vendor	CDATA	#IMPLIED
              wordsize	CDATA	#IMPLIED
              annotations	CDATA	#IMPLIED
            
            "></textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "dtd", alignCDATA: true},
                    lineNumbers: true,
                    lineWrapping: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>application/xml-dtd</code>.</p>
              </article>
            
        • dylan
          • dylan.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("dylan", function(_config) {
              // Words
              var words = {
                // Words that introduce unnamed definitions like "define interface"
                unnamedDefinition: ["interface"],
            
                // Words that introduce simple named definitions like "define library"
                namedDefinition: ["module", "library", "macro",
                                  "C-struct", "C-union",
                                  "C-function", "C-callable-wrapper"
                                 ],
            
                // Words that introduce type definitions like "define class".
                // These are also parameterized like "define method" and are
                // appended to otherParameterizedDefinitionWords
                typeParameterizedDefinition: ["class", "C-subtype", "C-mapped-subtype"],
            
                // Words that introduce trickier definitions like "define method".
                // These require special definitions to be added to startExpressions
                otherParameterizedDefinition: ["method", "function",
                                               "C-variable", "C-address"
                                              ],
            
                // Words that introduce module constant definitions.
                // These must also be simple definitions and are
                // appended to otherSimpleDefinitionWords
                constantSimpleDefinition: ["constant"],
            
                // Words that introduce module variable definitions.
                // These must also be simple definitions and are
                // appended to otherSimpleDefinitionWords
                variableSimpleDefinition: ["variable"],
            
                // Other words that introduce simple definitions
                // (without implicit bodies).
                otherSimpleDefinition: ["generic", "domain",
                                        "C-pointer-type",
                                        "table"
                                       ],
            
                // Words that begin statements with implicit bodies.
                statement: ["if", "block", "begin", "method", "case",
                            "for", "select", "when", "unless", "until",
                            "while", "iterate", "profiling", "dynamic-bind"
                           ],
            
                // Patterns that act as separators in compound statements.
                // This may include any general pattern that must be indented
                // specially.
                separator: ["finally", "exception", "cleanup", "else",
                            "elseif", "afterwards"
                           ],
            
                // Keywords that do not require special indentation handling,
                // but which should be highlighted
                other: ["above", "below", "by", "from", "handler", "in",
                        "instance", "let", "local", "otherwise", "slot",
                        "subclass", "then", "to", "keyed-by", "virtual"
                       ],
            
                // Condition signaling function calls
                signalingCalls: ["signal", "error", "cerror",
                                 "break", "check-type", "abort"
                                ]
              };
            
              words["otherDefinition"] =
                words["unnamedDefinition"]
                .concat(words["namedDefinition"])
                .concat(words["otherParameterizedDefinition"]);
            
              words["definition"] =
                words["typeParameterizedDefinition"]
                .concat(words["otherDefinition"]);
            
              words["parameterizedDefinition"] =
                words["typeParameterizedDefinition"]
                .concat(words["otherParameterizedDefinition"]);
            
              words["simpleDefinition"] =
                words["constantSimpleDefinition"]
                .concat(words["variableSimpleDefinition"])
                .concat(words["otherSimpleDefinition"]);
            
              words["keyword"] =
                words["statement"]
                .concat(words["separator"])
                .concat(words["other"]);
            
              // Patterns
              var symbolPattern = "[-_a-zA-Z?!*@<>$%]+";
              var symbol = new RegExp("^" + symbolPattern);
              var patterns = {
                // Symbols with special syntax
                symbolKeyword: symbolPattern + ":",
                symbolClass: "<" + symbolPattern + ">",
                symbolGlobal: "\\*" + symbolPattern + "\\*",
                symbolConstant: "\\$" + symbolPattern
              };
              var patternStyles = {
                symbolKeyword: "atom",
                symbolClass: "tag",
                symbolGlobal: "variable-2",
                symbolConstant: "variable-3"
              };
            
              // Compile all patterns to regular expressions
              for (var patternName in patterns)
                if (patterns.hasOwnProperty(patternName))
                  patterns[patternName] = new RegExp("^" + patterns[patternName]);
            
              // Names beginning "with-" and "without-" are commonly
              // used as statement macro
              patterns["keyword"] = [/^with(?:out)?-[-_a-zA-Z?!*@<>$%]+/];
            
              var styles = {};
              styles["keyword"] = "keyword";
              styles["definition"] = "def";
              styles["simpleDefinition"] = "def";
              styles["signalingCalls"] = "builtin";
            
              // protected words lookup table
              var wordLookup = {};
              var styleLookup = {};
            
              [
                "keyword",
                "definition",
                "simpleDefinition",
                "signalingCalls"
              ].forEach(function(type) {
                words[type].forEach(function(word) {
                  wordLookup[word] = type;
                  styleLookup[word] = styles[type];
                });
              });
            
            
              function chain(stream, state, f) {
                state.tokenize = f;
                return f(stream, state);
              }
            
              function tokenBase(stream, state) {
                // String
                var ch = stream.peek();
                if (ch == "'" || ch == '"') {
                  stream.next();
                  return chain(stream, state, tokenString(ch, "string"));
                }
                // Comment
                else if (ch == "/") {
                  stream.next();
                  if (stream.eat("*")) {
                    return chain(stream, state, tokenComment);
                  } else if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  } else {
                    stream.skipTo(" ");
                    return "operator";
                  }
                }
                // Decimal
                else if (/\d/.test(ch)) {
                  stream.match(/^\d*(?:\.\d*)?(?:e[+\-]?\d+)?/);
                  return "number";
                }
                // Hash
                else if (ch == "#") {
                  stream.next();
                  // Symbol with string syntax
                  ch = stream.peek();
                  if (ch == '"') {
                    stream.next();
                    return chain(stream, state, tokenString('"', "string-2"));
                  }
                  // Binary number
                  else if (ch == "b") {
                    stream.next();
                    stream.eatWhile(/[01]/);
                    return "number";
                  }
                  // Hex number
                  else if (ch == "x") {
                    stream.next();
                    stream.eatWhile(/[\da-f]/i);
                    return "number";
                  }
                  // Octal number
                  else if (ch == "o") {
                    stream.next();
                    stream.eatWhile(/[0-7]/);
                    return "number";
                  }
                  // Hash symbol
                  else {
                    stream.eatWhile(/[-a-zA-Z]/);
                    return "keyword";
                  }
                } else if (stream.match("end")) {
                  return "keyword";
                }
                for (var name in patterns) {
                  if (patterns.hasOwnProperty(name)) {
                    var pattern = patterns[name];
                    if ((pattern instanceof Array && pattern.some(function(p) {
                      return stream.match(p);
                    })) || stream.match(pattern))
                      return patternStyles[name];
                  }
                }
                if (stream.match("define")) {
                  return "def";
                } else {
                  stream.eatWhile(/[\w\-]/);
                  // Keyword
                  if (wordLookup[stream.current()]) {
                    return styleLookup[stream.current()];
                  } else if (stream.current().match(symbol)) {
                    return "variable";
                  } else {
                    stream.next();
                    return "variable-2";
                  }
                }
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false,
                ch;
                while ((ch = stream.next())) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function tokenString(quote, style) {
                return function(stream, state) {
                  var next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote) {
                      end = true;
                      break;
                    }
                  }
                  if (end)
                    state.tokenize = tokenBase;
                  return style;
                };
              }
            
              // Interface
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase,
                    currentIndent: 0
                  };
                },
                token: function(stream, state) {
                  if (stream.eatSpace())
                    return null;
                  var style = state.tokenize(stream, state);
                  return style;
                },
                blockCommentStart: "/*",
                blockCommentEnd: "*/"
              };
            });
            
            CodeMirror.defineMIME("text/x-dylan", "dylan");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Dylan mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="../../addon/comment/continuecomment.js"></script>
            <script src="../../addon/comment/comment.js"></script>
            <script src="dylan.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Dylan</a>
              </ul>
            </div>
            
            <article>
            <h2>Dylan mode</h2>
            
            
            <div><textarea id="code" name="code">
            Module:       locators-internals
            Synopsis:     Abstract modeling of locations
            Author:       Andy Armstrong
            Copyright:    Original Code is Copyright (c) 1995-2004 Functional Objects, Inc.
                          All rights reserved.
            License:      See License.txt in this distribution for details.
            Warranty:     Distributed WITHOUT WARRANTY OF ANY KIND
            
            define open generic locator-server
                (locator :: <locator>) => (server :: false-or(<server-locator>));
            define open generic locator-host
                (locator :: <locator>) => (host :: false-or(<string>));
            define open generic locator-volume
                (locator :: <locator>) => (volume :: false-or(<string>));
            define open generic locator-directory
                (locator :: <locator>) => (directory :: false-or(<directory-locator>));
            define open generic locator-relative?
                (locator :: <locator>) => (relative? :: <boolean>);
            define open generic locator-path
                (locator :: <locator>) => (path :: <sequence>);
            define open generic locator-base
                (locator :: <locator>) => (base :: false-or(<string>));
            define open generic locator-extension
                (locator :: <locator>) => (extension :: false-or(<string>));
            
            /// Locator classes
            
            define open abstract class <directory-locator> (<physical-locator>)
            end class <directory-locator>;
            
            define open abstract class <file-locator> (<physical-locator>)
            end class <file-locator>;
            
            define method as
                (class == <directory-locator>, string :: <string>)
             => (locator :: <directory-locator>)
              as(<native-directory-locator>, string)
            end method as;
            
            define method make
                (class == <directory-locator>,
                 #key server :: false-or(<server-locator>) = #f,
                      path :: <sequence> = #[],
                      relative? :: <boolean> = #f,
                      name :: false-or(<string>) = #f)
             => (locator :: <directory-locator>)
              make(<native-directory-locator>,
                   server:    server,
                   path:      path,
                   relative?: relative?,
                   name:      name)
            end method make;
            
            define method as
                (class == <file-locator>, string :: <string>)
             => (locator :: <file-locator>)
              as(<native-file-locator>, string)
            end method as;
            
            define method make
                (class == <file-locator>,
                 #key directory :: false-or(<directory-locator>) = #f,
                      base :: false-or(<string>) = #f,
                      extension :: false-or(<string>) = #f,
                      name :: false-or(<string>) = #f)
             => (locator :: <file-locator>)
              make(<native-file-locator>,
                   directory: directory,
                   base:      base,
                   extension: extension,
                   name:      name)
            end method make;
            
            /// Locator coercion
            
            //---*** andrewa: This caching scheme doesn't work yet, so disable it.
            define constant $cache-locators?        = #f;
            define constant $cache-locator-strings? = #f;
            
            define constant $locator-to-string-cache = make(<object-table>, weak: #"key");
            define constant $string-to-locator-cache = make(<string-table>, weak: #"value");
            
            define open generic locator-as-string
                (class :: subclass(<string>), locator :: <locator>)
             => (string :: <string>);
            
            define open generic string-as-locator
                (class :: subclass(<locator>), string :: <string>)
             => (locator :: <locator>);
            
            define sealed sideways method as
                (class :: subclass(<string>), locator :: <locator>)
             => (string :: <string>)
              let string = element($locator-to-string-cache, locator, default: #f);
              if (string)
                as(class, string)
              else
                let string = locator-as-string(class, locator);
                if ($cache-locator-strings?)
                  element($locator-to-string-cache, locator) := string;
                else
                  string
                end
              end
            end method as;
            
            define sealed sideways method as
                (class :: subclass(<locator>), string :: <string>)
             => (locator :: <locator>)
              let locator = element($string-to-locator-cache, string, default: #f);
              if (instance?(locator, class))
                locator
              else
                let locator = string-as-locator(class, string);
                if ($cache-locators?)
                  element($string-to-locator-cache, string) := locator;
                else
                  locator
                end
              end
            end method as;
            
            /// Locator conditions
            
            define class <locator-error> (<format-string-condition>, <error>)
            end class <locator-error>;
            
            define function locator-error
                (format-string :: <string>, #rest format-arguments)
              error(make(<locator-error>, 
                         format-string:    format-string,
                         format-arguments: format-arguments))
            end function locator-error;
            
            /// Useful locator protocols
            
            define open generic locator-test
                (locator :: <directory-locator>) => (test :: <function>);
            
            define method locator-test
                (locator :: <directory-locator>) => (test :: <function>)
              \=
            end method locator-test;
            
            define open generic locator-might-have-links?
                (locator :: <directory-locator>) => (links? :: <boolean>);
            
            define method locator-might-have-links?
                (locator :: <directory-locator>) => (links? :: singleton(#f))
              #f
            end method locator-might-have-links?;
            
            define method locator-relative?
                (locator :: <file-locator>) => (relative? :: <boolean>)
              let directory = locator.locator-directory;
              ~directory | directory.locator-relative?
            end method locator-relative?;
            
            define method current-directory-locator?
                (locator :: <directory-locator>) => (current-directory? :: <boolean>)
              locator.locator-relative?
                & locator.locator-path = #[#"self"]
            end method current-directory-locator?;
            
            define method locator-directory
                (locator :: <directory-locator>) => (parent :: false-or(<directory-locator>))
              let path = locator.locator-path;
              unless (empty?(path))
                make(object-class(locator),
                     server:    locator.locator-server,
                     path:      copy-sequence(path, end: path.size - 1),
                     relative?: locator.locator-relative?)
              end
            end method locator-directory;
            
            /// Simplify locator
            
            define open generic simplify-locator
                (locator :: <physical-locator>)
             => (simplified-locator :: <physical-locator>);
            
            define method simplify-locator
                (locator :: <directory-locator>)
             => (simplified-locator :: <directory-locator>)
              let path = locator.locator-path;
              let relative? = locator.locator-relative?;
              let resolve-parent? = ~locator.locator-might-have-links?;
              let simplified-path
                = simplify-path(path, 
                                resolve-parent?: resolve-parent?,
                                relative?: relative?);
              if (path ~= simplified-path)
                make(object-class(locator),
                     server:    locator.locator-server,
                     path:      simplified-path,
                     relative?: locator.locator-relative?)
              else
                locator
              end
            end method simplify-locator;
            
            define method simplify-locator
                (locator :: <file-locator>) => (simplified-locator :: <file-locator>)
              let directory = locator.locator-directory;
              let simplified-directory = directory & simplify-locator(directory);
              if (directory ~= simplified-directory)
                make(object-class(locator),
                     directory: simplified-directory,
                     base:      locator.locator-base,
                     extension: locator.locator-extension)
              else
                locator
              end
            end method simplify-locator;
            
            /// Subdirectory locator
            
            define open generic subdirectory-locator
                (locator :: <directory-locator>, #rest sub-path)
             => (subdirectory :: <directory-locator>);
            
            define method subdirectory-locator
                (locator :: <directory-locator>, #rest sub-path)
             => (subdirectory :: <directory-locator>)
              let old-path = locator.locator-path;
              let new-path = concatenate-as(<simple-object-vector>, old-path, sub-path);
              make(object-class(locator),
                   server:    locator.locator-server,
                   path:      new-path,
                   relative?: locator.locator-relative?)
            end method subdirectory-locator;
            
            /// Relative locator
            
            define open generic relative-locator
                (locator :: <physical-locator>, from-locator :: <physical-locator>)
             => (relative-locator :: <physical-locator>);
            
            define method relative-locator
                (locator :: <directory-locator>, from-locator :: <directory-locator>)
             => (relative-locator :: <directory-locator>)
              let path = locator.locator-path;
              let from-path = from-locator.locator-path;
              case
                ~locator.locator-relative? & from-locator.locator-relative? =>
                  locator-error
                    ("Cannot find relative path of absolute locator %= from relative locator %=",
                     locator, from-locator);
                locator.locator-server ~= from-locator.locator-server =>
                  locator;
                path = from-path =>
                  make(object-class(locator),
                       path: vector(#"self"),
                       relative?: #t);
                otherwise =>
                  make(object-class(locator),
                       path: relative-path(path, from-path, test: locator.locator-test),
                       relative?: #t);
              end
            end method relative-locator;
            
            define method relative-locator
                (locator :: <file-locator>, from-directory :: <directory-locator>)
             => (relative-locator :: <file-locator>)
              let directory = locator.locator-directory;
              let relative-directory = directory & relative-locator(directory, from-directory);
              if (relative-directory ~= directory)
                simplify-locator
                  (make(object-class(locator),
                        directory: relative-directory,
                        base:      locator.locator-base,
                        extension: locator.locator-extension))
              else
                locator
              end
            end method relative-locator;
            
            define method relative-locator
                (locator :: <physical-locator>, from-locator :: <file-locator>)
             => (relative-locator :: <physical-locator>)
              let from-directory = from-locator.locator-directory;
              case
                from-directory =>
                  relative-locator(locator, from-directory);
                ~locator.locator-relative? =>
                  locator-error
                    ("Cannot find relative path of absolute locator %= from relative locator %=",
                     locator, from-locator);
                otherwise =>
                  locator;
              end
            end method relative-locator;
            
            /// Merge locators
            
            define open generic merge-locators
                (locator :: <physical-locator>, from-locator :: <physical-locator>)
             => (merged-locator :: <physical-locator>);
            
            /// Merge locators
            
            define method merge-locators
                (locator :: <directory-locator>, from-locator :: <directory-locator>)
             => (merged-locator :: <directory-locator>)
              if (locator.locator-relative?)
                let path = concatenate(from-locator.locator-path, locator.locator-path);
                simplify-locator
                  (make(object-class(locator),
                        server:    from-locator.locator-server,
                        path:      path,
                        relative?: from-locator.locator-relative?))
              else
                locator
              end
            end method merge-locators;
            
            define method merge-locators
                (locator :: <file-locator>, from-locator :: <directory-locator>)
             => (merged-locator :: <file-locator>)
              let directory = locator.locator-directory;
              let merged-directory 
                = if (directory)
                    merge-locators(directory, from-locator)
                  else
                    simplify-locator(from-locator)
                  end;
              if (merged-directory ~= directory)
                make(object-class(locator),
                     directory: merged-directory,
                     base:      locator.locator-base,
                     extension: locator.locator-extension)
              else
                locator
              end
            end method merge-locators;
            
            define method merge-locators
                (locator :: <physical-locator>, from-locator :: <file-locator>)
             => (merged-locator :: <physical-locator>)
              let from-directory = from-locator.locator-directory;
              if (from-directory)
                merge-locators(locator, from-directory)
              else
                locator
              end
            end method merge-locators;
            
            /// Locator protocols
            
            define sideways method supports-open-locator?
                (locator :: <file-locator>) => (openable? :: <boolean>)
              ~locator.locator-relative?
            end method supports-open-locator?;
            
            define sideways method open-locator
                (locator :: <file-locator>, #rest keywords, #key, #all-keys)
             => (stream :: <stream>)
              apply(open-file-stream, locator, keywords)
            end method open-locator;
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/x-dylan",
                    lineNumbers: true,
                    matchBrackets: true,
                    continueComments: "Enter",
                    extraKeys: {"Ctrl-Q": "toggleComment"},
                    tabMode: "indent",
                    indentUnit: 2
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-dylan</code>.</p>
            </article>
            
        • ebnf
          • ebnf.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("ebnf", function (config) {
                var commentType = {slash: 0, parenthesis: 1};
                var stateType = {comment: 0, _string: 1, characterClass: 2};
                var bracesMode = null;
            
                if (config.bracesMode)
                  bracesMode = CodeMirror.getMode(config, config.bracesMode);
            
                return {
                  startState: function () {
                    return {
                      stringType: null,
                      commentType: null,
                      braced: 0,
                      lhs: true,
                      localState: null,
                      stack: [],
                      inDefinition: false
                    };
                  },
                  token: function (stream, state) {
                    if (!stream) return;
            
                    //check for state changes
                    if (state.stack.length === 0) {
                      //strings
                      if ((stream.peek() == '"') || (stream.peek() == "'")) {
                        state.stringType = stream.peek();
                        stream.next(); // Skip quote
                        state.stack.unshift(stateType._string);
                      } else if (stream.match(/^\/\*/)) { //comments starting with /*
                        state.stack.unshift(stateType.comment);
                        state.commentType = commentType.slash;
                      } else if (stream.match(/^\(\*/)) { //comments starting with (*
                        state.stack.unshift(stateType.comment);
                        state.commentType = commentType.parenthesis;
                      }
                    }
            
                    //return state
                    //stack has
                    switch (state.stack[0]) {
                    case stateType._string:
                      while (state.stack[0] === stateType._string && !stream.eol()) {
                        if (stream.peek() === state.stringType) {
                          stream.next(); // Skip quote
                          state.stack.shift(); // Clear flag
                        } else if (stream.peek() === "\\") {
                          stream.next();
                          stream.next();
                        } else {
                          stream.match(/^.[^\\\"\']*/);
                        }
                      }
                      return state.lhs ? "property string" : "string"; // Token style
            
                    case stateType.comment:
                      while (state.stack[0] === stateType.comment && !stream.eol()) {
                        if (state.commentType === commentType.slash && stream.match(/\*\//)) {
                          state.stack.shift(); // Clear flag
                          state.commentType = null;
                        } else if (state.commentType === commentType.parenthesis && stream.match(/\*\)/)) {
                          state.stack.shift(); // Clear flag
                          state.commentType = null;
                        } else {
                          stream.match(/^.[^\*]*/);
                        }
                      }
                      return "comment";
            
                    case stateType.characterClass:
                      while (state.stack[0] === stateType.characterClass && !stream.eol()) {
                        if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) {
                          state.stack.shift();
                        }
                      }
                      return "operator";
                    }
            
                    var peek = stream.peek();
            
                    if (bracesMode !== null && (state.braced || peek === "{")) {
                      if (state.localState === null)
                        state.localState = bracesMode.startState();
            
                      var token = bracesMode.token(stream, state.localState),
                      text = stream.current();
            
                      if (!token) {
                        for (var i = 0; i < text.length; i++) {
                          if (text[i] === "{") {
                            if (state.braced === 0) {
                              token = "matchingbracket";
                            }
                            state.braced++;
                          } else if (text[i] === "}") {
                            state.braced--;
                            if (state.braced === 0) {
                              token = "matchingbracket";
                            }
                          }
                        }
                      }
                      return token;
                    }
            
                    //no stack
                    switch (peek) {
                    case "[":
                      stream.next();
                      state.stack.unshift(stateType.characterClass);
                      return "bracket";
                    case ":":
                    case "|":
                    case ";":
                      stream.next();
                      return "operator";
                    case "%":
                      if (stream.match("%%")) {
                        return "header";
                      } else if (stream.match(/[%][A-Za-z]+/)) {
                        return "keyword";
                      } else if (stream.match(/[%][}]/)) {
                        return "matchingbracket";
                      }
                      break;
                    case "/":
                      if (stream.match(/[\/][A-Za-z]+/)) {
                      return "keyword";
                    }
                    case "\\":
                      if (stream.match(/[\][a-z]+/)) {
                        return "string-2";
                      }
                    case ".":
                      if (stream.match(".")) {
                        return "atom";
                      }
                    case "*":
                    case "-":
                    case "+":
                    case "^":
                      if (stream.match(peek)) {
                        return "atom";
                      }
                    case "$":
                      if (stream.match("$$")) {
                        return "builtin";
                      } else if (stream.match(/[$][0-9]+/)) {
                        return "variable-3";
                      }
                    case "<":
                      if (stream.match(/<<[a-zA-Z_]+>>/)) {
                        return "builtin";
                      }
                    }
            
                    if (stream.match(/^\/\//)) {
                      stream.skipToEnd();
                      return "comment";
                    } else if (stream.match(/return/)) {
                      return "operator";
                    } else if (stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/)) {
                      if (stream.match(/(?=[\(.])/)) {
                        return "variable";
                      } else if (stream.match(/(?=[\s\n]*[:=])/)) {
                        return "def";
                      }
                      return "variable-2";
                    } else if (["[", "]", "(", ")"].indexOf(stream.peek()) != -1) {
                      stream.next();
                      return "bracket";
                    } else if (!stream.eatSpace()) {
                      stream.next();
                    }
                    return null;
                  }
                };
              });
            
              CodeMirror.defineMIME("text/x-ebnf", "ebnf");
            });
            
          • index.html
            <!doctype html>
            <html>
              <head>
                <title>CodeMirror: EBNF Mode</title>
                <meta charset="utf-8"/>
                <link rel=stylesheet href="../../doc/docs.css">
            
                <link rel="stylesheet" href="../../lib/codemirror.css">
                <script src="../../lib/codemirror.js"></script>
                <script src="../javascript/javascript.js"></script>
                <script src="ebnf.js"></script>
                <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
              </head>
              <body>
                <div id=nav>
                  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
                  <ul>
                    <li><a href="../../index.html">Home</a>
                    <li><a href="../../doc/manual.html">Manual</a>
                    <li><a href="https://github.com/codemirror/codemirror">Code</a>
                  </ul>
                  <ul>
                    <li><a href="../index.html">Language modes</a>
                    <li><a class=active href="#">EBNF Mode</a>
                  </ul>
                </div>
            
                <article>
                  <h2>EBNF Mode (bracesMode setting = "javascript")</h2>
                  <form><textarea id="code" name="code">
            /* description: Parses end executes mathematical expressions. */
            
            /* lexical grammar */
            %lex
            
            %%
            \s+                   /* skip whitespace */
            [0-9]+("."[0-9]+)?\b  return 'NUMBER';
            "*"                   return '*';
            "/"                   return '/';
            "-"                   return '-';
            "+"                   return '+';
            "^"                   return '^';
            "("                   return '(';
            ")"                   return ')';
            "PI"                  return 'PI';
            "E"                   return 'E';
            &lt;&lt;EOF&gt;&gt;               return 'EOF';
            
            /lex
            
            /* operator associations and precedence */
            
            %left '+' '-'
            %left '*' '/'
            %left '^'
            %left UMINUS
            
            %start expressions
            
            %% /* language grammar */
            
            expressions
            : e EOF
            {print($1); return $1;}
            ;
            
            e
            : e '+' e
            {$$ = $1+$3;}
            | e '-' e
            {$$ = $1-$3;}
            | e '*' e
            {$$ = $1*$3;}
            | e '/' e
            {$$ = $1/$3;}
            | e '^' e
            {$$ = Math.pow($1, $3);}
            | '-' e %prec UMINUS
            {$$ = -$2;}
            | '(' e ')'
            {$$ = $2;}
            | NUMBER
            {$$ = Number(yytext);}
            | E
            {$$ = Math.E;}
            | PI
            {$$ = Math.PI;}
            ;</textarea></form>
                  <script>
                    var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                      mode: {name: "ebnf"},
                      lineNumbers: true,
                      bracesMode: 'javascript'
                    });
                  </script>
                  <h3>The EBNF Mode</h3>
                  <p> Created by <a href="https://github.com/robertleeplummerjr">Robert Plummer</a></p>
                </article>
              </body>
            </html>
            
        • ecl
          • ecl.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("ecl", function(config) {
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              function metaHook(stream, state) {
                if (!state.startOfLine) return false;
                stream.skipToEnd();
                return "meta";
              }
            
              var indentUnit = config.indentUnit;
              var keyword = words("abs acos allnodes ascii asin asstring atan atan2 ave case choose choosen choosesets clustersize combine correlation cos cosh count covariance cron dataset dedup define denormalize distribute distributed distribution ebcdic enth error evaluate event eventextra eventname exists exp failcode failmessage fetch fromunicode getisvalid global graph group hash hash32 hash64 hashcrc hashmd5 having if index intformat isvalid iterate join keyunicode length library limit ln local log loop map matched matchlength matchposition matchtext matchunicode max merge mergejoin min nolocal nonempty normalize parse pipe power preload process project pull random range rank ranked realformat recordof regexfind regexreplace regroup rejected rollup round roundup row rowdiff sample set sin sinh sizeof soapcall sort sorted sqrt stepped stored sum table tan tanh thisnode topn tounicode transfer trim truncate typeof ungroup unicodeorder variance which workunit xmldecode xmlencode xmltext xmlunicode");
              var variable = words("apply assert build buildindex evaluate fail keydiff keypatch loadxml nothor notify output parallel sequential soapcall wait");
              var variable_2 = words("__compressed__ all and any as atmost before beginc++ best between case const counter csv descend encrypt end endc++ endmacro except exclusive expire export extend false few first flat from full function group header heading hole ifblock import in interface joined keep keyed last left limit load local locale lookup macro many maxcount maxlength min skew module named nocase noroot noscan nosort not of only opt or outer overwrite packed partition penalty physicallength pipe quote record relationship repeat return right scan self separator service shared skew skip sql store terminator thor threshold token transform trim true type unicodeorder unsorted validate virtual whole wild within xml xpath");
              var variable_3 = words("ascii big_endian boolean data decimal ebcdic integer pattern qstring real record rule set of string token udecimal unicode unsigned varstring varunicode");
              var builtin = words("checkpoint deprecated failcode failmessage failure global independent onwarning persist priority recovery stored success wait when");
              var blockKeywords = words("catch class do else finally for if switch try while");
              var atoms = words("true false null");
              var hooks = {"#": metaHook};
              var isOperatorChar = /[+\-*&%=<>!?|\/]/;
            
              var curPunc;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (hooks[ch]) {
                  var result = hooks[ch](stream, state);
                  if (result !== false) return result;
                }
                if (ch == '"' || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return "number";
                }
                if (ch == "/") {
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment;
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                }
                if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_]/);
                var cur = stream.current().toLowerCase();
                if (keyword.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "keyword";
                } else if (variable.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "variable";
                } else if (variable_2.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "variable-2";
                } else if (variable_3.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "variable-3";
                } else if (builtin.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "builtin";
                } else { //Data types are of from KEYWORD##
                            var i = cur.length - 1;
                            while(i >= 0 && (!isNaN(cur[i]) || cur[i] == '_'))
                                    --i;
            
                            if (i > 0) {
                                    var cur2 = cur.substr(0, i + 1);
                            if (variable_3.propertyIsEnumerable(cur2)) {
                                    if (blockKeywords.propertyIsEnumerable(cur2)) curPunc = "newstatement";
                                    return "variable-3";
                            }
                        }
                }
                if (atoms.propertyIsEnumerable(cur)) return "atom";
                return null;
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {end = true; break;}
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !escaped)
                    state.tokenize = tokenBase;
                  return "string";
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
              function pushContext(state, col, type) {
                return state.context = new Context(state.indented, col, type, null, state.context);
              }
              function popContext(state) {
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}")
                  state.indented = state.context.indented;
                return state.context = state.context.prev;
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                  return {
                    tokenize: null,
                    context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true
                  };
                },
            
                token: function(stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                  }
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment" || style == "meta") return style;
                  if (ctx.align == null) ctx.align = true;
            
                  if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
                  else if (curPunc == "{") pushContext(state, stream.column(), "}");
                  else if (curPunc == "[") pushContext(state, stream.column(), "]");
                  else if (curPunc == "(") pushContext(state, stream.column(), ")");
                  else if (curPunc == "}") {
                    while (ctx.type == "statement") ctx = popContext(state);
                    if (ctx.type == "}") ctx = popContext(state);
                    while (ctx.type == "statement") ctx = popContext(state);
                  }
                  else if (curPunc == ctx.type) popContext(state);
                  else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
                    pushContext(state, stream.column(), "statement");
                  state.startOfLine = false;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase && state.tokenize != null) return 0;
                  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
                  if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
                  var closing = firstChar == ctx.type;
                  if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit);
                  else if (ctx.align) return ctx.column + (closing ? 0 : 1);
                  else return ctx.indented + (closing ? 0 : indentUnit);
                },
            
                electricChars: "{}"
              };
            });
            
            CodeMirror.defineMIME("text/x-ecl", "ecl");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: ECL mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="ecl.js"></script>
            <style>.CodeMirror {border: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">ECL</a>
              </ul>
            </div>
            
            <article>
            <h2>ECL mode</h2>
            <form><textarea id="code" name="code">
            /*
            sample useless code to demonstrate ecl syntax highlighting
            this is a multiline comment!
            */
            
            //  this is a singleline comment!
            
            import ut;
            r := 
              record
               string22 s1 := '123';
               integer4 i1 := 123;
              end;
            #option('tmp', true);
            d := dataset('tmp::qb', r, thor);
            output(d);
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p>Based on CodeMirror's clike mode.  For more information see <a href="http://hpccsystems.com">HPCC Systems</a> web site.</p>
                <p><strong>MIME types defined:</strong> <code>text/x-ecl</code>.</p>
            
              </article>
            
        • eiffel
          • eiffel.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("eiffel", function() {
              function wordObj(words) {
                var o = {};
                for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;
                return o;
              }
              var keywords = wordObj([
                'note',
                'across',
                'when',
                'variant',
                'until',
                'unique',
                'undefine',
                'then',
                'strip',
                'select',
                'retry',
                'rescue',
                'require',
                'rename',
                'reference',
                'redefine',
                'prefix',
                'once',
                'old',
                'obsolete',
                'loop',
                'local',
                'like',
                'is',
                'inspect',
                'infix',
                'include',
                'if',
                'frozen',
                'from',
                'external',
                'export',
                'ensure',
                'end',
                'elseif',
                'else',
                'do',
                'creation',
                'create',
                'check',
                'alias',
                'agent',
                'separate',
                'invariant',
                'inherit',
                'indexing',
                'feature',
                'expanded',
                'deferred',
                'class',
                'Void',
                'True',
                'Result',
                'Precursor',
                'False',
                'Current',
                'create',
                'attached',
                'detachable',
                'as',
                'and',
                'implies',
                'not',
                'or'
              ]);
              var operators = wordObj([":=", "and then","and", "or","<<",">>"]);
            
              function chain(newtok, stream, state) {
                state.tokenize.push(newtok);
                return newtok(stream, state);
              }
            
              function tokenBase(stream, state) {
                if (stream.eatSpace()) return null;
                var ch = stream.next();
                if (ch == '"'||ch == "'") {
                  return chain(readQuoted(ch, "string"), stream, state);
                } else if (ch == "-"&&stream.eat("-")) {
                  stream.skipToEnd();
                  return "comment";
                } else if (ch == ":"&&stream.eat("=")) {
                  return "operator";
                } else if (/[0-9]/.test(ch)) {
                  stream.eatWhile(/[xXbBCc0-9\.]/);
                  stream.eat(/[\?\!]/);
                  return "ident";
                } else if (/[a-zA-Z_0-9]/.test(ch)) {
                  stream.eatWhile(/[a-zA-Z_0-9]/);
                  stream.eat(/[\?\!]/);
                  return "ident";
                } else if (/[=+\-\/*^%<>~]/.test(ch)) {
                  stream.eatWhile(/[=+\-\/*^%<>~]/);
                  return "operator";
                } else {
                  return null;
                }
              }
            
              function readQuoted(quote, style,  unescaped) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && (unescaped || !escaped)) {
                      state.tokenize.pop();
                      break;
                    }
                    escaped = !escaped && ch == "%";
                  }
                  return style;
                };
              }
            
              return {
                startState: function() {
                  return {tokenize: [tokenBase]};
                },
            
                token: function(stream, state) {
                  var style = state.tokenize[state.tokenize.length-1](stream, state);
                  if (style == "ident") {
                    var word = stream.current();
                    style = keywords.propertyIsEnumerable(stream.current()) ? "keyword"
                      : operators.propertyIsEnumerable(stream.current()) ? "operator"
                      : /^[A-Z][A-Z_0-9]*$/g.test(word) ? "tag"
                      : /^0[bB][0-1]+$/g.test(word) ? "number"
                      : /^0[cC][0-7]+$/g.test(word) ? "number"
                      : /^0[xX][a-fA-F0-9]+$/g.test(word) ? "number"
                      : /^([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+)$/g.test(word) ? "number"
                      : /^[0-9]+$/g.test(word) ? "number"
                      : "variable";
                  }
                  return style;
                },
                lineComment: "--"
              };
            });
            
            CodeMirror.defineMIME("text/x-eiffel", "eiffel");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Eiffel mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/neat.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="eiffel.js"></script>
            <style>
                  .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                  .cm-s-default span.cm-arrow { color: red; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Eiffel</a>
              </ul>
            </div>
            
            <article>
            <h2>Eiffel mode</h2>
            <form><textarea id="code" name="code">
            note
                description: "[
                    Project-wide universal properties.
                    This class is an ancestor to all developer-written classes.
                    ANY may be customized for individual projects or teams.
                    ]"
            
                library: "Free implementation of ELKS library"
                status: "See notice at end of class."
                legal: "See notice at end of class."
                date: "$Date: 2013-01-25 11:49:00 -0800 (Fri, 25 Jan 2013) $"
                revision: "$Revision: 712 $"
            
            class
                ANY
            
            feature -- Customization
            
            feature -- Access
            
                generator: STRING
                        -- Name of current object's generating class
                        -- (base class of the type of which it is a direct instance)
                    external
                        "built_in"
                    ensure
                        generator_not_void: Result /= Void
                        generator_not_empty: not Result.is_empty
                    end
            
                generating_type: TYPE [detachable like Current]
                        -- Type of current object
                        -- (type of which it is a direct instance)
                    do
                        Result := {detachable like Current}
                    ensure
                        generating_type_not_void: Result /= Void
                    end
            
            feature -- Status report
            
                conforms_to (other: ANY): BOOLEAN
                        -- Does type of current object conform to type
                        -- of `other' (as per Eiffel: The Language, chapter 13)?
                    require
                        other_not_void: other /= Void
                    external
                        "built_in"
                    end
            
                same_type (other: ANY): BOOLEAN
                        -- Is type of current object identical to type of `other'?
                    require
                        other_not_void: other /= Void
                    external
                        "built_in"
                    ensure
                        definition: Result = (conforms_to (other) and
                                                    other.conforms_to (Current))
                    end
            
            feature -- Comparison
            
                is_equal (other: like Current): BOOLEAN
                        -- Is `other' attached to an object considered
                        -- equal to current object?
                    require
                        other_not_void: other /= Void
                    external
                        "built_in"
                    ensure
                        symmetric: Result implies other ~ Current
                        consistent: standard_is_equal (other) implies Result
                    end
            
                frozen standard_is_equal (other: like Current): BOOLEAN
                        -- Is `other' attached to an object of the same type
                        -- as current object, and field-by-field identical to it?
                    require
                        other_not_void: other /= Void
                    external
                        "built_in"
                    ensure
                        same_type: Result implies same_type (other)
                        symmetric: Result implies other.standard_is_equal (Current)
                    end
            
                frozen equal (a: detachable ANY; b: like a): BOOLEAN
                        -- Are `a' and `b' either both void or attached
                        -- to objects considered equal?
                    do
                        if a = Void then
                            Result := b = Void
                        else
                            Result := b /= Void and then
                                        a.is_equal (b)
                        end
                    ensure
                        definition: Result = (a = Void and b = Void) or else
                                    ((a /= Void and b /= Void) and then
                                    a.is_equal (b))
                    end
            
                frozen standard_equal (a: detachable ANY; b: like a): BOOLEAN
                        -- Are `a' and `b' either both void or attached to
                        -- field-by-field identical objects of the same type?
                        -- Always uses default object comparison criterion.
                    do
                        if a = Void then
                            Result := b = Void
                        else
                            Result := b /= Void and then
                                        a.standard_is_equal (b)
                        end
                    ensure
                        definition: Result = (a = Void and b = Void) or else
                                    ((a /= Void and b /= Void) and then
                                    a.standard_is_equal (b))
                    end
            
                frozen is_deep_equal (other: like Current): BOOLEAN
                        -- Are `Current' and `other' attached to isomorphic object structures?
                    require
                        other_not_void: other /= Void
                    external
                        "built_in"
                    ensure
                        shallow_implies_deep: standard_is_equal (other) implies Result
                        same_type: Result implies same_type (other)
                        symmetric: Result implies other.is_deep_equal (Current)
                    end
            
                frozen deep_equal (a: detachable ANY; b: like a): BOOLEAN
                        -- Are `a' and `b' either both void
                        -- or attached to isomorphic object structures?
                    do
                        if a = Void then
                            Result := b = Void
                        else
                            Result := b /= Void and then a.is_deep_equal (b)
                        end
                    ensure
                        shallow_implies_deep: standard_equal (a, b) implies Result
                        both_or_none_void: (a = Void) implies (Result = (b = Void))
                        same_type: (Result and (a /= Void)) implies (b /= Void and then a.same_type (b))
                        symmetric: Result implies deep_equal (b, a)
                    end
            
            feature -- Duplication
            
                frozen twin: like Current
                        -- New object equal to `Current'
                        -- `twin' calls `copy'; to change copying/twinning semantics, redefine `copy'.
                    external
                        "built_in"
                    ensure
                        twin_not_void: Result /= Void
                        is_equal: Result ~ Current
                    end
            
                copy (other: like Current)
                        -- Update current object using fields of object attached
                        -- to `other', so as to yield equal objects.
                    require
                        other_not_void: other /= Void
                        type_identity: same_type (other)
                    external
                        "built_in"
                    ensure
                        is_equal: Current ~ other
                    end
            
                frozen standard_copy (other: like Current)
                        -- Copy every field of `other' onto corresponding field
                        -- of current object.
                    require
                        other_not_void: other /= Void
                        type_identity: same_type (other)
                    external
                        "built_in"
                    ensure
                        is_standard_equal: standard_is_equal (other)
                    end
            
                frozen clone (other: detachable ANY): like other
                        -- Void if `other' is void; otherwise new object
                        -- equal to `other'
                        --
                        -- For non-void `other', `clone' calls `copy';
                        -- to change copying/cloning semantics, redefine `copy'.
                    obsolete
                        "Use `twin' instead."
                    do
                        if other /= Void then
                            Result := other.twin
                        end
                    ensure
                        equal: Result ~ other
                    end
            
                frozen standard_clone (other: detachable ANY): like other
                        -- Void if `other' is void; otherwise new object
                        -- field-by-field identical to `other'.
                        -- Always uses default copying semantics.
                    obsolete
                        "Use `standard_twin' instead."
                    do
                        if other /= Void then
                            Result := other.standard_twin
                        end
                    ensure
                        equal: standard_equal (Result, other)
                    end
            
                frozen standard_twin: like Current
                        -- New object field-by-field identical to `other'.
                        -- Always uses default copying semantics.
                    external
                        "built_in"
                    ensure
                        standard_twin_not_void: Result /= Void
                        equal: standard_equal (Result, Current)
                    end
            
                frozen deep_twin: like Current
                        -- New object structure recursively duplicated from Current.
                    external
                        "built_in"
                    ensure
                        deep_twin_not_void: Result /= Void
                        deep_equal: deep_equal (Current, Result)
                    end
            
                frozen deep_clone (other: detachable ANY): like other
                        -- Void if `other' is void: otherwise, new object structure
                        -- recursively duplicated from the one attached to `other'
                    obsolete
                        "Use `deep_twin' instead."
                    do
                        if other /= Void then
                            Result := other.deep_twin
                        end
                    ensure
                        deep_equal: deep_equal (other, Result)
                    end
            
                frozen deep_copy (other: like Current)
                        -- Effect equivalent to that of:
                        --      `copy' (`other' . `deep_twin')
                    require
                        other_not_void: other /= Void
                    do
                        copy (other.deep_twin)
                    ensure
                        deep_equal: deep_equal (Current, other)
                    end
            
            feature {NONE} -- Retrieval
            
                frozen internal_correct_mismatch
                        -- Called from runtime to perform a proper dynamic dispatch on `correct_mismatch'
                        -- from MISMATCH_CORRECTOR.
                    local
                        l_msg: STRING
                        l_exc: EXCEPTIONS
                    do
                        if attached {MISMATCH_CORRECTOR} Current as l_corrector then
                            l_corrector.correct_mismatch
                        else
                            create l_msg.make_from_string ("Mismatch: ")
                            create l_exc
                            l_msg.append (generating_type.name)
                            l_exc.raise_retrieval_exception (l_msg)
                        end
                    end
            
            feature -- Output
            
                io: STD_FILES
                        -- Handle to standard file setup
                    once
                        create Result
                        Result.set_output_default
                    ensure
                        io_not_void: Result /= Void
                    end
            
                out: STRING
                        -- New string containing terse printable representation
                        -- of current object
                    do
                        Result := tagged_out
                    ensure
                        out_not_void: Result /= Void
                    end
            
                frozen tagged_out: STRING
                        -- New string containing terse printable representation
                        -- of current object
                    external
                        "built_in"
                    ensure
                        tagged_out_not_void: Result /= Void
                    end
            
                print (o: detachable ANY)
                        -- Write terse external representation of `o'
                        -- on standard output.
                    do
                        if o /= Void then
                            io.put_string (o.out)
                        end
                    end
            
            feature -- Platform
            
                Operating_environment: OPERATING_ENVIRONMENT
                        -- Objects available from the operating system
                    once
                        create Result
                    ensure
                        operating_environment_not_void: Result /= Void
                    end
            
            feature {NONE} -- Initialization
            
                default_create
                        -- Process instances of classes with no creation clause.
                        -- (Default: do nothing.)
                    do
                    end
            
            feature -- Basic operations
            
                default_rescue
                        -- Process exception for routines with no Rescue clause.
                        -- (Default: do nothing.)
                    do
                    end
            
                frozen do_nothing
                        -- Execute a null action.
                    do
                    end
            
                frozen default: detachable like Current
                        -- Default value of object's type
                    do
                    end
            
                frozen default_pointer: POINTER
                        -- Default value of type `POINTER'
                        -- (Avoid the need to write `p'.`default' for
                        -- some `p' of type `POINTER'.)
                    do
                    ensure
                        -- Result = Result.default
                    end
            
                frozen as_attached: attached like Current
                        -- Attached version of Current
                        -- (Can be used during transitional period to convert
                        -- non-void-safe classes to void-safe ones.)
                    do
                        Result := Current
                    end
            
            invariant
                reflexive_equality: standard_is_equal (Current)
                reflexive_conformance: conforms_to (Current)
            
            note
                copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
                license:   "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
                source: "[
                        Eiffel Software
                        5949 Hollister Ave., Goleta, CA 93117 USA
                        Telephone 805-685-1006, Fax 805-685-6869
                        Website http://www.eiffel.com
                        Customer support http://support.eiffel.com
                    ]"
            
            end
            
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/x-eiffel",
                    indentUnit: 4,
                    lineNumbers: true,
                    theme: "neat"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-eiffel</code>.</p>
             
             <p> Created by <a href="https://github.com/ynh">YNH</a>.</p>
              </article>
            
        • erlang
          • erlang.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*jshint unused:true, eqnull:true, curly:true, bitwise:true */
            /*jshint undef:true, latedef:true, trailing:true */
            /*global CodeMirror:true */
            
            // erlang mode.
            // tokenizer -> token types -> CodeMirror styles
            // tokenizer maintains a parse stack
            // indenter uses the parse stack
            
            // TODO indenter:
            //   bit syntax
            //   old guard/bif/conversion clashes (e.g. "float/1")
            //   type/spec/opaque
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMIME("text/x-erlang", "erlang");
            
            CodeMirror.defineMode("erlang", function(cmCfg) {
              "use strict";
            
            /////////////////////////////////////////////////////////////////////////////
            // constants
            
              var typeWords = [
                "-type", "-spec", "-export_type", "-opaque"];
            
              var keywordWords = [
                "after","begin","catch","case","cond","end","fun","if",
                "let","of","query","receive","try","when"];
            
              var separatorRE    = /[\->,;]/;
              var separatorWords = [
                "->",";",","];
            
              var operatorAtomWords = [
                "and","andalso","band","bnot","bor","bsl","bsr","bxor",
                "div","not","or","orelse","rem","xor"];
            
              var operatorSymbolRE    = /[\+\-\*\/<>=\|:!]/;
              var operatorSymbolWords = [
                "=","+","-","*","/",">",">=","<","=<","=:=","==","=/=","/=","||","<-","!"];
            
              var openParenRE    = /[<\(\[\{]/;
              var openParenWords = [
                "<<","(","[","{"];
            
              var closeParenRE    = /[>\)\]\}]/;
              var closeParenWords = [
                "}","]",")",">>"];
            
              var guardWords = [
                "is_atom","is_binary","is_bitstring","is_boolean","is_float",
                "is_function","is_integer","is_list","is_number","is_pid",
                "is_port","is_record","is_reference","is_tuple",
                "atom","binary","bitstring","boolean","function","integer","list",
                "number","pid","port","record","reference","tuple"];
            
              var bifWords = [
                "abs","adler32","adler32_combine","alive","apply","atom_to_binary",
                "atom_to_list","binary_to_atom","binary_to_existing_atom",
                "binary_to_list","binary_to_term","bit_size","bitstring_to_list",
                "byte_size","check_process_code","contact_binary","crc32",
                "crc32_combine","date","decode_packet","delete_module",
                "disconnect_node","element","erase","exit","float","float_to_list",
                "garbage_collect","get","get_keys","group_leader","halt","hd",
                "integer_to_list","internal_bif","iolist_size","iolist_to_binary",
                "is_alive","is_atom","is_binary","is_bitstring","is_boolean",
                "is_float","is_function","is_integer","is_list","is_number","is_pid",
                "is_port","is_process_alive","is_record","is_reference","is_tuple",
                "length","link","list_to_atom","list_to_binary","list_to_bitstring",
                "list_to_existing_atom","list_to_float","list_to_integer",
                "list_to_pid","list_to_tuple","load_module","make_ref","module_loaded",
                "monitor_node","node","node_link","node_unlink","nodes","notalive",
                "now","open_port","pid_to_list","port_close","port_command",
                "port_connect","port_control","pre_loaded","process_flag",
                "process_info","processes","purge_module","put","register",
                "registered","round","self","setelement","size","spawn","spawn_link",
                "spawn_monitor","spawn_opt","split_binary","statistics",
                "term_to_binary","time","throw","tl","trunc","tuple_size",
                "tuple_to_list","unlink","unregister","whereis"];
            
            // upper case: [A-Z] [Ø-Þ] [À-Ö]
            // lower case: [a-z] [ß-ö] [ø-ÿ]
              var anumRE       = /[\w@Ø-ÞÀ-Öß-öø-ÿ]/;
              var escapesRE    =
                /[0-7]{1,3}|[bdefnrstv\\"']|\^[a-zA-Z]|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+}/;
            
            /////////////////////////////////////////////////////////////////////////////
            // tokenizer
            
              function tokenizer(stream,state) {
                // in multi-line string
                if (state.in_string) {
                  state.in_string = (!doubleQuote(stream));
                  return rval(state,stream,"string");
                }
            
                // in multi-line atom
                if (state.in_atom) {
                  state.in_atom = (!singleQuote(stream));
                  return rval(state,stream,"atom");
                }
            
                // whitespace
                if (stream.eatSpace()) {
                  return rval(state,stream,"whitespace");
                }
            
                // attributes and type specs
                if (!peekToken(state) &&
                    stream.match(/-\s*[a-zß-öø-ÿ][\wØ-ÞÀ-Öß-öø-ÿ]*/)) {
                  if (is_member(stream.current(),typeWords)) {
                    return rval(state,stream,"type");
                  }else{
                    return rval(state,stream,"attribute");
                  }
                }
            
                var ch = stream.next();
            
                // comment
                if (ch == '%') {
                  stream.skipToEnd();
                  return rval(state,stream,"comment");
                }
            
                // colon
                if (ch == ":") {
                  return rval(state,stream,"colon");
                }
            
                // macro
                if (ch == '?') {
                  stream.eatSpace();
                  stream.eatWhile(anumRE);
                  return rval(state,stream,"macro");
                }
            
                // record
                if (ch == "#") {
                  stream.eatSpace();
                  stream.eatWhile(anumRE);
                  return rval(state,stream,"record");
                }
            
                // dollar escape
                if (ch == "$") {
                  if (stream.next() == "\\" && !stream.match(escapesRE)) {
                    return rval(state,stream,"error");
                  }
                  return rval(state,stream,"number");
                }
            
                // dot
                if (ch == ".") {
                  return rval(state,stream,"dot");
                }
            
                // quoted atom
                if (ch == '\'') {
                  if (!(state.in_atom = (!singleQuote(stream)))) {
                    if (stream.match(/\s*\/\s*[0-9]/,false)) {
                      stream.match(/\s*\/\s*[0-9]/,true);
                      return rval(state,stream,"fun");      // 'f'/0 style fun
                    }
                    if (stream.match(/\s*\(/,false) || stream.match(/\s*:/,false)) {
                      return rval(state,stream,"function");
                    }
                  }
                  return rval(state,stream,"atom");
                }
            
                // string
                if (ch == '"') {
                  state.in_string = (!doubleQuote(stream));
                  return rval(state,stream,"string");
                }
            
                // variable
                if (/[A-Z_Ø-ÞÀ-Ö]/.test(ch)) {
                  stream.eatWhile(anumRE);
                  return rval(state,stream,"variable");
                }
            
                // atom/keyword/BIF/function
                if (/[a-z_ß-öø-ÿ]/.test(ch)) {
                  stream.eatWhile(anumRE);
            
                  if (stream.match(/\s*\/\s*[0-9]/,false)) {
                    stream.match(/\s*\/\s*[0-9]/,true);
                    return rval(state,stream,"fun");      // f/0 style fun
                  }
            
                  var w = stream.current();
            
                  if (is_member(w,keywordWords)) {
                    return rval(state,stream,"keyword");
                  }else if (is_member(w,operatorAtomWords)) {
                    return rval(state,stream,"operator");
                  }else if (stream.match(/\s*\(/,false)) {
                    // 'put' and 'erlang:put' are bifs, 'foo:put' is not
                    if (is_member(w,bifWords) &&
                        ((peekToken(state).token != ":") ||
                         (peekToken(state,2).token == "erlang"))) {
                      return rval(state,stream,"builtin");
                    }else if (is_member(w,guardWords)) {
                      return rval(state,stream,"guard");
                    }else{
                      return rval(state,stream,"function");
                    }
                  }else if (is_member(w,operatorAtomWords)) {
                    return rval(state,stream,"operator");
                  }else if (lookahead(stream) == ":") {
                    if (w == "erlang") {
                      return rval(state,stream,"builtin");
                    } else {
                      return rval(state,stream,"function");
                    }
                  }else if (is_member(w,["true","false"])) {
                    return rval(state,stream,"boolean");
                  }else if (is_member(w,["true","false"])) {
                    return rval(state,stream,"boolean");
                  }else{
                    return rval(state,stream,"atom");
                  }
                }
            
                // number
                var digitRE      = /[0-9]/;
                var radixRE      = /[0-9a-zA-Z]/;         // 36#zZ style int
                if (digitRE.test(ch)) {
                  stream.eatWhile(digitRE);
                  if (stream.eat('#')) {                // 36#aZ  style integer
                    if (!stream.eatWhile(radixRE)) {
                      stream.backUp(1);                 //"36#" - syntax error
                    }
                  } else if (stream.eat('.')) {       // float
                    if (!stream.eatWhile(digitRE)) {
                      stream.backUp(1);        // "3." - probably end of function
                    } else {
                      if (stream.eat(/[eE]/)) {        // float with exponent
                        if (stream.eat(/[-+]/)) {
                          if (!stream.eatWhile(digitRE)) {
                            stream.backUp(2);            // "2e-" - syntax error
                          }
                        } else {
                          if (!stream.eatWhile(digitRE)) {
                            stream.backUp(1);            // "2e" - syntax error
                          }
                        }
                      }
                    }
                  }
                  return rval(state,stream,"number");   // normal integer
                }
            
                // open parens
                if (nongreedy(stream,openParenRE,openParenWords)) {
                  return rval(state,stream,"open_paren");
                }
            
                // close parens
                if (nongreedy(stream,closeParenRE,closeParenWords)) {
                  return rval(state,stream,"close_paren");
                }
            
                // separators
                if (greedy(stream,separatorRE,separatorWords)) {
                  return rval(state,stream,"separator");
                }
            
                // operators
                if (greedy(stream,operatorSymbolRE,operatorSymbolWords)) {
                  return rval(state,stream,"operator");
                }
            
                return rval(state,stream,null);
              }
            
            /////////////////////////////////////////////////////////////////////////////
            // utilities
              function nongreedy(stream,re,words) {
                if (stream.current().length == 1 && re.test(stream.current())) {
                  stream.backUp(1);
                  while (re.test(stream.peek())) {
                    stream.next();
                    if (is_member(stream.current(),words)) {
                      return true;
                    }
                  }
                  stream.backUp(stream.current().length-1);
                }
                return false;
              }
            
              function greedy(stream,re,words) {
                if (stream.current().length == 1 && re.test(stream.current())) {
                  while (re.test(stream.peek())) {
                    stream.next();
                  }
                  while (0 < stream.current().length) {
                    if (is_member(stream.current(),words)) {
                      return true;
                    }else{
                      stream.backUp(1);
                    }
                  }
                  stream.next();
                }
                return false;
              }
            
              function doubleQuote(stream) {
                return quote(stream, '"', '\\');
              }
            
              function singleQuote(stream) {
                return quote(stream,'\'','\\');
              }
            
              function quote(stream,quoteChar,escapeChar) {
                while (!stream.eol()) {
                  var ch = stream.next();
                  if (ch == quoteChar) {
                    return true;
                  }else if (ch == escapeChar) {
                    stream.next();
                  }
                }
                return false;
              }
            
              function lookahead(stream) {
                var m = stream.match(/([\n\s]+|%[^\n]*\n)*(.)/,false);
                return m ? m.pop() : "";
              }
            
              function is_member(element,list) {
                return (-1 < list.indexOf(element));
              }
            
              function rval(state,stream,type) {
            
                // parse stack
                pushToken(state,realToken(type,stream));
            
                // map erlang token type to CodeMirror style class
                //     erlang             -> CodeMirror tag
                switch (type) {
                  case "atom":        return "atom";
                  case "attribute":   return "attribute";
                  case "boolean":     return "atom";
                  case "builtin":     return "builtin";
                  case "close_paren": return null;
                  case "colon":       return null;
                  case "comment":     return "comment";
                  case "dot":         return null;
                  case "error":       return "error";
                  case "fun":         return "meta";
                  case "function":    return "tag";
                  case "guard":       return "property";
                  case "keyword":     return "keyword";
                  case "macro":       return "variable-2";
                  case "number":      return "number";
                  case "open_paren":  return null;
                  case "operator":    return "operator";
                  case "record":      return "bracket";
                  case "separator":   return null;
                  case "string":      return "string";
                  case "type":        return "def";
                  case "variable":    return "variable";
                  default:            return null;
                }
              }
            
              function aToken(tok,col,ind,typ) {
                return {token:  tok,
                        column: col,
                        indent: ind,
                        type:   typ};
              }
            
              function realToken(type,stream) {
                return aToken(stream.current(),
                             stream.column(),
                             stream.indentation(),
                             type);
              }
            
              function fakeToken(type) {
                return aToken(type,0,0,type);
              }
            
              function peekToken(state,depth) {
                var len = state.tokenStack.length;
                var dep = (depth ? depth : 1);
            
                if (len < dep) {
                  return false;
                }else{
                  return state.tokenStack[len-dep];
                }
              }
            
              function pushToken(state,token) {
            
                if (!(token.type == "comment" || token.type == "whitespace")) {
                  state.tokenStack = maybe_drop_pre(state.tokenStack,token);
                  state.tokenStack = maybe_drop_post(state.tokenStack);
                }
              }
            
              function maybe_drop_pre(s,token) {
                var last = s.length-1;
            
                if (0 < last && s[last].type === "record" && token.type === "dot") {
                  s.pop();
                }else if (0 < last && s[last].type === "group") {
                  s.pop();
                  s.push(token);
                }else{
                  s.push(token);
                }
                return s;
              }
            
              function maybe_drop_post(s) {
                var last = s.length-1;
            
                if (s[last].type === "dot") {
                  return [];
                }
                if (s[last].type === "fun" && s[last-1].token === "fun") {
                  return s.slice(0,last-1);
                }
                switch (s[s.length-1].token) {
                  case "}":    return d(s,{g:["{"]});
                  case "]":    return d(s,{i:["["]});
                  case ")":    return d(s,{i:["("]});
                  case ">>":   return d(s,{i:["<<"]});
                  case "end":  return d(s,{i:["begin","case","fun","if","receive","try"]});
                  case ",":    return d(s,{e:["begin","try","when","->",
                                              ",","(","[","{","<<"]});
                  case "->":   return d(s,{r:["when"],
                                           m:["try","if","case","receive"]});
                  case ";":    return d(s,{E:["case","fun","if","receive","try","when"]});
                  case "catch":return d(s,{e:["try"]});
                  case "of":   return d(s,{e:["case"]});
                  case "after":return d(s,{e:["receive","try"]});
                  default:     return s;
                }
              }
            
              function d(stack,tt) {
                // stack is a stack of Token objects.
                // tt is an object; {type:tokens}
                // type is a char, tokens is a list of token strings.
                // The function returns (possibly truncated) stack.
                // It will descend the stack, looking for a Token such that Token.token
                //  is a member of tokens. If it does not find that, it will normally (but
                //  see "E" below) return stack. If it does find a match, it will remove
                //  all the Tokens between the top and the matched Token.
                // If type is "m", that is all it does.
                // If type is "i", it will also remove the matched Token and the top Token.
                // If type is "g", like "i", but add a fake "group" token at the top.
                // If type is "r", it will remove the matched Token, but not the top Token.
                // If type is "e", it will keep the matched Token but not the top Token.
                // If type is "E", it behaves as for type "e", except if there is no match,
                //  in which case it will return an empty stack.
            
                for (var type in tt) {
                  var len = stack.length-1;
                  var tokens = tt[type];
                  for (var i = len-1; -1 < i ; i--) {
                    if (is_member(stack[i].token,tokens)) {
                      var ss = stack.slice(0,i);
                      switch (type) {
                          case "m": return ss.concat(stack[i]).concat(stack[len]);
                          case "r": return ss.concat(stack[len]);
                          case "i": return ss;
                          case "g": return ss.concat(fakeToken("group"));
                          case "E": return ss.concat(stack[i]);
                          case "e": return ss.concat(stack[i]);
                      }
                    }
                  }
                }
                return (type == "E" ? [] : stack);
              }
            
            /////////////////////////////////////////////////////////////////////////////
            // indenter
            
              function indenter(state,textAfter) {
                var t;
                var unit = cmCfg.indentUnit;
                var wordAfter = wordafter(textAfter);
                var currT = peekToken(state,1);
                var prevT = peekToken(state,2);
            
                if (state.in_string || state.in_atom) {
                  return CodeMirror.Pass;
                }else if (!prevT) {
                  return 0;
                }else if (currT.token == "when") {
                  return currT.column+unit;
                }else if (wordAfter === "when" && prevT.type === "function") {
                  return prevT.indent+unit;
                }else if (wordAfter === "(" && currT.token === "fun") {
                  return  currT.column+3;
                }else if (wordAfter === "catch" && (t = getToken(state,["try"]))) {
                  return t.column;
                }else if (is_member(wordAfter,["end","after","of"])) {
                  t = getToken(state,["begin","case","fun","if","receive","try"]);
                  return t ? t.column : CodeMirror.Pass;
                }else if (is_member(wordAfter,closeParenWords)) {
                  t = getToken(state,openParenWords);
                  return t ? t.column : CodeMirror.Pass;
                }else if (is_member(currT.token,[",","|","||"]) ||
                          is_member(wordAfter,[",","|","||"])) {
                  t = postcommaToken(state);
                  return t ? t.column+t.token.length : unit;
                }else if (currT.token == "->") {
                  if (is_member(prevT.token, ["receive","case","if","try"])) {
                    return prevT.column+unit+unit;
                  }else{
                    return prevT.column+unit;
                  }
                }else if (is_member(currT.token,openParenWords)) {
                  return currT.column+currT.token.length;
                }else{
                  t = defaultToken(state);
                  return truthy(t) ? t.column+unit : 0;
                }
              }
            
              function wordafter(str) {
                var m = str.match(/,|[a-z]+|\}|\]|\)|>>|\|+|\(/);
            
                return truthy(m) && (m.index === 0) ? m[0] : "";
              }
            
              function postcommaToken(state) {
                var objs = state.tokenStack.slice(0,-1);
                var i = getTokenIndex(objs,"type",["open_paren"]);
            
                return truthy(objs[i]) ? objs[i] : false;
              }
            
              function defaultToken(state) {
                var objs = state.tokenStack;
                var stop = getTokenIndex(objs,"type",["open_paren","separator","keyword"]);
                var oper = getTokenIndex(objs,"type",["operator"]);
            
                if (truthy(stop) && truthy(oper) && stop < oper) {
                  return objs[stop+1];
                } else if (truthy(stop)) {
                  return objs[stop];
                } else {
                  return false;
                }
              }
            
              function getToken(state,tokens) {
                var objs = state.tokenStack;
                var i = getTokenIndex(objs,"token",tokens);
            
                return truthy(objs[i]) ? objs[i] : false;
              }
            
              function getTokenIndex(objs,propname,propvals) {
            
                for (var i = objs.length-1; -1 < i ; i--) {
                  if (is_member(objs[i][propname],propvals)) {
                    return i;
                  }
                }
                return false;
              }
            
              function truthy(x) {
                return (x !== false) && (x != null);
              }
            
            /////////////////////////////////////////////////////////////////////////////
            // this object defines the mode
            
              return {
                startState:
                  function() {
                    return {tokenStack: [],
                            in_string:  false,
                            in_atom:    false};
                  },
            
                token:
                  function(stream, state) {
                    return tokenizer(stream, state);
                  },
            
                indent:
                  function(state, textAfter) {
                    return indenter(state,textAfter);
                  },
            
                lineComment: "%"
              };
            });
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Erlang mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/erlang-dark.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="erlang.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Erlang</a>
              </ul>
            </div>
            
            <article>
            <h2>Erlang mode</h2>
            <form><textarea id="code" name="code">
            %% -*- mode: erlang; erlang-indent-level: 2 -*-
            %%% Created :  7 May 2012 by mats cronqvist <masse@klarna.com>
            
            %% @doc
            %% Demonstrates how to print a record.
            %% @end
            
            -module('ex').
            -author('mats cronqvist').
            -export([demo/0,
                     rec_info/1]).
            
            -record(demo,{a="One",b="Two",c="Three",d="Four"}).
            
            rec_info(demo) -> record_info(fields,demo).
            
            demo() -> expand_recs(?MODULE,#demo{a="A",b="BB"}).
            
            expand_recs(M,List) when is_list(List) ->
              [expand_recs(M,L)||L<-List];
            expand_recs(M,Tup) when is_tuple(Tup) ->
              case tuple_size(Tup) of
                L when L < 1 -> Tup;
                L ->
                  try
                    Fields = M:rec_info(element(1,Tup)),
                    L = length(Fields)+1,
                    lists:zip(Fields,expand_recs(M,tl(tuple_to_list(Tup))))
                  catch
                    _:_ -> list_to_tuple(expand_recs(M,tuple_to_list(Tup)))
                  end
              end;
            expand_recs(_,Term) ->
              Term.
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    extraKeys: {"Tab":  "indentAuto"},
                    theme: "erlang-dark"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-erlang</code>.</p>
              </article>
            
        • forth
          • forth.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Author: Aliaksei Chapyzhenka
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              function toWordList(words) {
                var ret = [];
                words.split(' ').forEach(function(e){
                  ret.push({name: e});
                });
                return ret;
              }
            
              var coreWordList = toWordList(
            'INVERT AND OR XOR\
             2* 2/ LSHIFT RSHIFT\
             0= = 0< < > U< MIN MAX\
             2DROP 2DUP 2OVER 2SWAP ?DUP DEPTH DROP DUP OVER ROT SWAP\
             >R R> R@\
             + - 1+ 1- ABS NEGATE\
             S>D * M* UM*\
             FM/MOD SM/REM UM/MOD */ */MOD / /MOD MOD\
             HERE , @ ! CELL+ CELLS C, C@ C! CHARS 2@ 2!\
             ALIGN ALIGNED +! ALLOT\
             CHAR [CHAR] [ ] BL\
             FIND EXECUTE IMMEDIATE COUNT LITERAL STATE\
             ; DOES> >BODY\
             EVALUATE\
             SOURCE >IN\
             <# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL\
             FILL MOVE\
             . CR EMIT SPACE SPACES TYPE U. .R U.R\
             ACCEPT\
             TRUE FALSE\
             <> U> 0<> 0>\
             NIP TUCK ROLL PICK\
             2>R 2R@ 2R>\
             WITHIN UNUSED MARKER\
             I J\
             TO\
             COMPILE, [COMPILE]\
             SAVE-INPUT RESTORE-INPUT\
             PAD ERASE\
             2LITERAL DNEGATE\
             D- D+ D0< D0= D2* D2/ D< D= DMAX DMIN D>S DABS\
             M+ M*/ D. D.R 2ROT DU<\
             CATCH THROW\
             FREE RESIZE ALLOCATE\
             CS-PICK CS-ROLL\
             GET-CURRENT SET-CURRENT FORTH-WORDLIST GET-ORDER SET-ORDER\
             PREVIOUS SEARCH-WORDLIST WORDLIST FIND ALSO ONLY FORTH DEFINITIONS ORDER\
             -TRAILING /STRING SEARCH COMPARE CMOVE CMOVE> BLANK SLITERAL');
            
              var immediateWordList = toWordList('IF ELSE THEN BEGIN WHILE REPEAT UNTIL RECURSE [IF] [ELSE] [THEN] ?DO DO LOOP +LOOP UNLOOP LEAVE EXIT AGAIN CASE OF ENDOF ENDCASE');
            
              CodeMirror.defineMode('forth', function() {
                function searchWordList (wordList, word) {
                  var i;
                  for (i = wordList.length - 1; i >= 0; i--) {
                    if (wordList[i].name === word.toUpperCase()) {
                      return wordList[i];
                    }
                  }
                  return undefined;
                }
              return {
                startState: function() {
                  return {
                    state: '',
                    base: 10,
                    coreWordList: coreWordList,
                    immediateWordList: immediateWordList,
                    wordList: []
                  };
                },
                token: function (stream, stt) {
                  var mat;
                  if (stream.eatSpace()) {
                    return null;
                  }
                  if (stt.state === '') { // interpretation
                    if (stream.match(/^(\]|:NONAME)(\s|$)/i)) {
                      stt.state = ' compilation';
                      return 'builtin compilation';
                    }
                    mat = stream.match(/^(\:)\s+(\S+)(\s|$)+/);
                    if (mat) {
                      stt.wordList.push({name: mat[2].toUpperCase()});
                      stt.state = ' compilation';
                      return 'def' + stt.state;
                    }
                    mat = stream.match(/^(VARIABLE|2VARIABLE|CONSTANT|2CONSTANT|CREATE|POSTPONE|VALUE|WORD)\s+(\S+)(\s|$)+/i);
                    if (mat) {
                      stt.wordList.push({name: mat[2].toUpperCase()});
                      return 'def' + stt.state;
                    }
                    mat = stream.match(/^(\'|\[\'\])\s+(\S+)(\s|$)+/);
                    if (mat) {
                      return 'builtin' + stt.state;
                    }
                    } else { // compilation
                    // ; [
                    if (stream.match(/^(\;|\[)(\s)/)) {
                      stt.state = '';
                      stream.backUp(1);
                      return 'builtin compilation';
                    }
                    if (stream.match(/^(\;|\[)($)/)) {
                      stt.state = '';
                      return 'builtin compilation';
                    }
                    if (stream.match(/^(POSTPONE)\s+\S+(\s|$)+/)) {
                      return 'builtin';
                    }
                  }
            
                  // dynamic wordlist
                  mat = stream.match(/^(\S+)(\s+|$)/);
                  if (mat) {
                    if (searchWordList(stt.wordList, mat[1]) !== undefined) {
                      return 'variable' + stt.state;
                    }
            
                    // comments
                    if (mat[1] === '\\') {
                      stream.skipToEnd();
                        return 'comment' + stt.state;
                      }
            
                      // core words
                      if (searchWordList(stt.coreWordList, mat[1]) !== undefined) {
                        return 'builtin' + stt.state;
                      }
                      if (searchWordList(stt.immediateWordList, mat[1]) !== undefined) {
                        return 'keyword' + stt.state;
                      }
            
                      if (mat[1] === '(') {
                        stream.eatWhile(function (s) { return s !== ')'; });
                        stream.eat(')');
                        return 'comment' + stt.state;
                      }
            
                      // // strings
                      if (mat[1] === '.(') {
                        stream.eatWhile(function (s) { return s !== ')'; });
                        stream.eat(')');
                        return 'string' + stt.state;
                      }
                      if (mat[1] === 'S"' || mat[1] === '."' || mat[1] === 'C"') {
                        stream.eatWhile(function (s) { return s !== '"'; });
                        stream.eat('"');
                        return 'string' + stt.state;
                      }
            
                      // numbers
                      if (mat[1] - 0xfffffffff) {
                        return 'number' + stt.state;
                      }
                      // if (mat[1].match(/^[-+]?[0-9]+\.[0-9]*/)) {
                      //     return 'number' + stt.state;
                      // }
            
                      return 'atom' + stt.state;
                    }
                  }
                };
              });
              CodeMirror.defineMIME("text/x-forth", "forth");
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Forth mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link href='http://fonts.googleapis.com/css?family=Droid+Sans+Mono' rel='stylesheet' type='text/css'>
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel=stylesheet href="../../theme/colorforth.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="forth.js"></script>
            <style>
            .CodeMirror {
                font-family: 'Droid Sans Mono', monospace;
                font-size: 14px;
            }
            </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Forth</a>
              </ul>
            </div>
            
            <article>
            
            <h2>Forth mode</h2>
            
            <form><textarea id="code" name="code">
            \ Insertion sort
            
            : cell-  1 cells - ;
            
            : insert ( start end -- start )
              dup @ >r ( r: v )
              begin
                2dup <
              while
                r@ over cell- @ <
              while
                cell-
                dup @ over cell+ !
              repeat then
              r> swap ! ;
            
            : sort ( array len -- )
              1 ?do
                dup i cells + insert
              loop drop ;</textarea>
              </form>
            
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                lineNumbers: true,
                lineWrapping: true,
                indentUnit: 2,
                tabSize: 2,
                autofocus: true,
                theme: "colorforth",
                mode: "text/x-forth"
              });
            </script>
            
            <p>Simple mode that handle Forth-Syntax (<a href="http://en.wikipedia.org/wiki/Forth_%28programming_language%29">Forth on WikiPedia</a>).</p>
            
            <p><strong>MIME types defined:</strong> <code>text/x-forth</code>.</p>
            
            </article>
            
        • fortran
          • fortran.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("fortran", function() {
              function words(array) {
                var keys = {};
                for (var i = 0; i < array.length; ++i) {
                  keys[array[i]] = true;
                }
                return keys;
              }
            
              var keywords = words([
                              "abstract", "accept", "allocatable", "allocate",
                              "array", "assign", "asynchronous", "backspace",
                              "bind", "block", "byte", "call", "case",
                              "class", "close", "common", "contains",
                              "continue", "cycle", "data", "deallocate",
                              "decode", "deferred", "dimension", "do",
                              "elemental", "else", "encode", "end",
                              "endif", "entry", "enumerator", "equivalence",
                              "exit", "external", "extrinsic", "final",
                              "forall", "format", "function", "generic",
                              "go", "goto", "if", "implicit", "import", "include",
                              "inquire", "intent", "interface", "intrinsic",
                              "module", "namelist", "non_intrinsic",
                              "non_overridable", "none", "nopass",
                              "nullify", "open", "optional", "options",
                              "parameter", "pass", "pause", "pointer",
                              "print", "private", "program", "protected",
                              "public", "pure", "read", "recursive", "result",
                              "return", "rewind", "save", "select", "sequence",
                              "stop", "subroutine", "target", "then", "to", "type",
                              "use", "value", "volatile", "where", "while",
                              "write"]);
              var builtins = words(["abort", "abs", "access", "achar", "acos",
                                      "adjustl", "adjustr", "aimag", "aint", "alarm",
                                      "all", "allocated", "alog", "amax", "amin",
                                      "amod", "and", "anint", "any", "asin",
                                      "associated", "atan", "besj", "besjn", "besy",
                                      "besyn", "bit_size", "btest", "cabs", "ccos",
                                      "ceiling", "cexp", "char", "chdir", "chmod",
                                      "clog", "cmplx", "command_argument_count",
                                      "complex", "conjg", "cos", "cosh", "count",
                                      "cpu_time", "cshift", "csin", "csqrt", "ctime",
                                      "c_funloc", "c_loc", "c_associated", "c_null_ptr",
                                      "c_null_funptr", "c_f_pointer", "c_null_char",
                                      "c_alert", "c_backspace", "c_form_feed",
                                      "c_new_line", "c_carriage_return",
                                      "c_horizontal_tab", "c_vertical_tab", "dabs",
                                      "dacos", "dasin", "datan", "date_and_time",
                                      "dbesj", "dbesj", "dbesjn", "dbesy", "dbesy",
                                      "dbesyn", "dble", "dcos", "dcosh", "ddim", "derf",
                                      "derfc", "dexp", "digits", "dim", "dint", "dlog",
                                      "dlog", "dmax", "dmin", "dmod", "dnint",
                                      "dot_product", "dprod", "dsign", "dsinh",
                                      "dsin", "dsqrt", "dtanh", "dtan", "dtime",
                                      "eoshift", "epsilon", "erf", "erfc", "etime",
                                      "exit", "exp", "exponent", "extends_type_of",
                                      "fdate", "fget", "fgetc", "float", "floor",
                                      "flush", "fnum", "fputc", "fput", "fraction",
                                      "fseek", "fstat", "ftell", "gerror", "getarg",
                                      "get_command", "get_command_argument",
                                      "get_environment_variable", "getcwd",
                                      "getenv", "getgid", "getlog", "getpid",
                                      "getuid", "gmtime", "hostnm", "huge", "iabs",
                                      "iachar", "iand", "iargc", "ibclr", "ibits",
                                      "ibset", "ichar", "idate", "idim", "idint",
                                      "idnint", "ieor", "ierrno", "ifix", "imag",
                                      "imagpart", "index", "int", "ior", "irand",
                                      "isatty", "ishft", "ishftc", "isign",
                                      "iso_c_binding", "is_iostat_end", "is_iostat_eor",
                                      "itime", "kill", "kind", "lbound", "len", "len_trim",
                                      "lge", "lgt", "link", "lle", "llt", "lnblnk", "loc",
                                      "log", "logical", "long", "lshift", "lstat", "ltime",
                                      "matmul", "max", "maxexponent", "maxloc", "maxval",
                                      "mclock", "merge", "move_alloc", "min", "minexponent",
                                      "minloc", "minval", "mod", "modulo", "mvbits",
                                      "nearest", "new_line", "nint", "not", "or", "pack",
                                      "perror", "precision", "present", "product", "radix",
                                      "rand", "random_number", "random_seed", "range",
                                      "real", "realpart", "rename", "repeat", "reshape",
                                      "rrspacing", "rshift", "same_type_as", "scale",
                                      "scan", "second", "selected_int_kind",
                                      "selected_real_kind", "set_exponent", "shape",
                                      "short", "sign", "signal", "sinh", "sin", "sleep",
                                      "sngl", "spacing", "spread", "sqrt", "srand", "stat",
                                      "sum", "symlnk", "system", "system_clock", "tan",
                                      "tanh", "time", "tiny", "transfer", "transpose",
                                      "trim", "ttynam", "ubound", "umask", "unlink",
                                      "unpack", "verify", "xor", "zabs", "zcos", "zexp",
                                      "zlog", "zsin", "zsqrt"]);
            
                var dataTypes =  words(["c_bool", "c_char", "c_double", "c_double_complex",
                                 "c_float", "c_float_complex", "c_funptr", "c_int",
                                 "c_int16_t", "c_int32_t", "c_int64_t", "c_int8_t",
                                 "c_int_fast16_t", "c_int_fast32_t", "c_int_fast64_t",
                                 "c_int_fast8_t", "c_int_least16_t", "c_int_least32_t",
                                 "c_int_least64_t", "c_int_least8_t", "c_intmax_t",
                                 "c_intptr_t", "c_long", "c_long_double",
                                 "c_long_double_complex", "c_long_long", "c_ptr",
                                 "c_short", "c_signed_char", "c_size_t", "character",
                                 "complex", "double", "integer", "logical", "real"]);
              var isOperatorChar = /[+\-*&=<>\/\:]/;
              var litOperator = new RegExp("(\.and\.|\.or\.|\.eq\.|\.lt\.|\.le\.|\.gt\.|\.ge\.|\.ne\.|\.not\.|\.eqv\.|\.neqv\.)", "i");
            
              function tokenBase(stream, state) {
            
                if (stream.match(litOperator)){
                    return 'operator';
                }
            
                var ch = stream.next();
                if (ch == "!") {
                  stream.skipToEnd();
                  return "comment";
                }
                if (ch == '"' || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                if (/[\[\]\(\),]/.test(ch)) {
                  return null;
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return "number";
                }
                if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_]/);
                var word = stream.current().toLowerCase();
            
                if (keywords.hasOwnProperty(word)){
                        return 'keyword';
                }
                if (builtins.hasOwnProperty(word) || dataTypes.hasOwnProperty(word)) {
                        return 'builtin';
                }
                return "variable";
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {
                        end = true;
                        break;
                    }
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !escaped) state.tokenize = null;
                  return "string";
                };
              }
            
              // Interface
            
              return {
                startState: function() {
                  return {tokenize: null};
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment" || style == "meta") return style;
                  return style;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-fortran", "fortran");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Fortran mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="fortran.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Fortran</a>
              </ul>
            </div>
            
            <article>
            <h2>Fortran mode</h2>
            
            
            <div><textarea id="code" name="code">
            ! Example Fortran code
              program average
            
              ! Read in some numbers and take the average
              ! As written, if there are no data points, an average of zero is returned
              ! While this may not be desired behavior, it keeps this example simple
            
              implicit none
            
              real, dimension(:), allocatable :: points
              integer                         :: number_of_points
              real                            :: average_points=0., positive_average=0., negative_average=0.
            
              write (*,*) "Input number of points to average:"
              read  (*,*) number_of_points
            
              allocate (points(number_of_points))
            
              write (*,*) "Enter the points to average:"
              read  (*,*) points
            
              ! Take the average by summing points and dividing by number_of_points
              if (number_of_points > 0) average_points = sum(points) / number_of_points
            
              ! Now form average over positive and negative points only
              if (count(points > 0.) > 0) then
                 positive_average = sum(points, points > 0.) / count(points > 0.)
              end if
            
              if (count(points < 0.) > 0) then
                 negative_average = sum(points, points < 0.) / count(points < 0.)
              end if
            
              deallocate (points)
            
              ! Print result to terminal
              write (*,'(a,g12.4)') 'Average = ', average_points
              write (*,'(a,g12.4)') 'Average of positive points = ', positive_average
              write (*,'(a,g12.4)') 'Average of negative points = ', negative_average
            
              end program average
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "text/x-fortran"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-Fortran</code>.</p>
              </article>
            
        • gas
          • gas.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("gas", function(_config, parserConfig) {
              'use strict';
            
              // If an architecture is specified, its initialization function may
              // populate this array with custom parsing functions which will be
              // tried in the event that the standard functions do not find a match.
              var custom = [];
            
              // The symbol used to start a line comment changes based on the target
              // architecture.
              // If no architecture is pased in "parserConfig" then only multiline
              // comments will have syntax support.
              var lineCommentStartSymbol = "";
            
              // These directives are architecture independent.
              // Machine specific directives should go in their respective
              // architecture initialization function.
              // Reference:
              // http://sourceware.org/binutils/docs/as/Pseudo-Ops.html#Pseudo-Ops
              var directives = {
                ".abort" : "builtin",
                ".align" : "builtin",
                ".altmacro" : "builtin",
                ".ascii" : "builtin",
                ".asciz" : "builtin",
                ".balign" : "builtin",
                ".balignw" : "builtin",
                ".balignl" : "builtin",
                ".bundle_align_mode" : "builtin",
                ".bundle_lock" : "builtin",
                ".bundle_unlock" : "builtin",
                ".byte" : "builtin",
                ".cfi_startproc" : "builtin",
                ".comm" : "builtin",
                ".data" : "builtin",
                ".def" : "builtin",
                ".desc" : "builtin",
                ".dim" : "builtin",
                ".double" : "builtin",
                ".eject" : "builtin",
                ".else" : "builtin",
                ".elseif" : "builtin",
                ".end" : "builtin",
                ".endef" : "builtin",
                ".endfunc" : "builtin",
                ".endif" : "builtin",
                ".equ" : "builtin",
                ".equiv" : "builtin",
                ".eqv" : "builtin",
                ".err" : "builtin",
                ".error" : "builtin",
                ".exitm" : "builtin",
                ".extern" : "builtin",
                ".fail" : "builtin",
                ".file" : "builtin",
                ".fill" : "builtin",
                ".float" : "builtin",
                ".func" : "builtin",
                ".global" : "builtin",
                ".gnu_attribute" : "builtin",
                ".hidden" : "builtin",
                ".hword" : "builtin",
                ".ident" : "builtin",
                ".if" : "builtin",
                ".incbin" : "builtin",
                ".include" : "builtin",
                ".int" : "builtin",
                ".internal" : "builtin",
                ".irp" : "builtin",
                ".irpc" : "builtin",
                ".lcomm" : "builtin",
                ".lflags" : "builtin",
                ".line" : "builtin",
                ".linkonce" : "builtin",
                ".list" : "builtin",
                ".ln" : "builtin",
                ".loc" : "builtin",
                ".loc_mark_labels" : "builtin",
                ".local" : "builtin",
                ".long" : "builtin",
                ".macro" : "builtin",
                ".mri" : "builtin",
                ".noaltmacro" : "builtin",
                ".nolist" : "builtin",
                ".octa" : "builtin",
                ".offset" : "builtin",
                ".org" : "builtin",
                ".p2align" : "builtin",
                ".popsection" : "builtin",
                ".previous" : "builtin",
                ".print" : "builtin",
                ".protected" : "builtin",
                ".psize" : "builtin",
                ".purgem" : "builtin",
                ".pushsection" : "builtin",
                ".quad" : "builtin",
                ".reloc" : "builtin",
                ".rept" : "builtin",
                ".sbttl" : "builtin",
                ".scl" : "builtin",
                ".section" : "builtin",
                ".set" : "builtin",
                ".short" : "builtin",
                ".single" : "builtin",
                ".size" : "builtin",
                ".skip" : "builtin",
                ".sleb128" : "builtin",
                ".space" : "builtin",
                ".stab" : "builtin",
                ".string" : "builtin",
                ".struct" : "builtin",
                ".subsection" : "builtin",
                ".symver" : "builtin",
                ".tag" : "builtin",
                ".text" : "builtin",
                ".title" : "builtin",
                ".type" : "builtin",
                ".uleb128" : "builtin",
                ".val" : "builtin",
                ".version" : "builtin",
                ".vtable_entry" : "builtin",
                ".vtable_inherit" : "builtin",
                ".warning" : "builtin",
                ".weak" : "builtin",
                ".weakref" : "builtin",
                ".word" : "builtin"
              };
            
              var registers = {};
            
              function x86(_parserConfig) {
                lineCommentStartSymbol = "#";
            
                registers.ax  = "variable";
                registers.eax = "variable-2";
                registers.rax = "variable-3";
            
                registers.bx  = "variable";
                registers.ebx = "variable-2";
                registers.rbx = "variable-3";
            
                registers.cx  = "variable";
                registers.ecx = "variable-2";
                registers.rcx = "variable-3";
            
                registers.dx  = "variable";
                registers.edx = "variable-2";
                registers.rdx = "variable-3";
            
                registers.si  = "variable";
                registers.esi = "variable-2";
                registers.rsi = "variable-3";
            
                registers.di  = "variable";
                registers.edi = "variable-2";
                registers.rdi = "variable-3";
            
                registers.sp  = "variable";
                registers.esp = "variable-2";
                registers.rsp = "variable-3";
            
                registers.bp  = "variable";
                registers.ebp = "variable-2";
                registers.rbp = "variable-3";
            
                registers.ip  = "variable";
                registers.eip = "variable-2";
                registers.rip = "variable-3";
            
                registers.cs  = "keyword";
                registers.ds  = "keyword";
                registers.ss  = "keyword";
                registers.es  = "keyword";
                registers.fs  = "keyword";
                registers.gs  = "keyword";
              }
            
              function armv6(_parserConfig) {
                // Reference:
                // http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001l/QRC0001_UAL.pdf
                // http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf
                lineCommentStartSymbol = "@";
                directives.syntax = "builtin";
            
                registers.r0  = "variable";
                registers.r1  = "variable";
                registers.r2  = "variable";
                registers.r3  = "variable";
                registers.r4  = "variable";
                registers.r5  = "variable";
                registers.r6  = "variable";
                registers.r7  = "variable";
                registers.r8  = "variable";
                registers.r9  = "variable";
                registers.r10 = "variable";
                registers.r11 = "variable";
                registers.r12 = "variable";
            
                registers.sp  = "variable-2";
                registers.lr  = "variable-2";
                registers.pc  = "variable-2";
                registers.r13 = registers.sp;
                registers.r14 = registers.lr;
                registers.r15 = registers.pc;
            
                custom.push(function(ch, stream) {
                  if (ch === '#') {
                    stream.eatWhile(/\w/);
                    return "number";
                  }
                });
              }
            
              var arch = (parserConfig.architecture || "x86").toLowerCase();
              if (arch === "x86") {
                x86(parserConfig);
              } else if (arch === "arm" || arch === "armv6") {
                armv6(parserConfig);
              }
            
              function nextUntilUnescaped(stream, end) {
                var escaped = false, next;
                while ((next = stream.next()) != null) {
                  if (next === end && !escaped) {
                    return false;
                  }
                  escaped = !escaped && next === "\\";
                }
                return escaped;
              }
            
              function clikeComment(stream, state) {
                var maybeEnd = false, ch;
                while ((ch = stream.next()) != null) {
                  if (ch === "/" && maybeEnd) {
                    state.tokenize = null;
                    break;
                  }
                  maybeEnd = (ch === "*");
                }
                return "comment";
              }
            
              return {
                startState: function() {
                  return {
                    tokenize: null
                  };
                },
            
                token: function(stream, state) {
                  if (state.tokenize) {
                    return state.tokenize(stream, state);
                  }
            
                  if (stream.eatSpace()) {
                    return null;
                  }
            
                  var style, cur, ch = stream.next();
            
                  if (ch === "/") {
                    if (stream.eat("*")) {
                      state.tokenize = clikeComment;
                      return clikeComment(stream, state);
                    }
                  }
            
                  if (ch === lineCommentStartSymbol) {
                    stream.skipToEnd();
                    return "comment";
                  }
            
                  if (ch === '"') {
                    nextUntilUnescaped(stream, '"');
                    return "string";
                  }
            
                  if (ch === '.') {
                    stream.eatWhile(/\w/);
                    cur = stream.current().toLowerCase();
                    style = directives[cur];
                    return style || null;
                  }
            
                  if (ch === '=') {
                    stream.eatWhile(/\w/);
                    return "tag";
                  }
            
                  if (ch === '{') {
                    return "braket";
                  }
            
                  if (ch === '}') {
                    return "braket";
                  }
            
                  if (/\d/.test(ch)) {
                    if (ch === "0" && stream.eat("x")) {
                      stream.eatWhile(/[0-9a-fA-F]/);
                      return "number";
                    }
                    stream.eatWhile(/\d/);
                    return "number";
                  }
            
                  if (/\w/.test(ch)) {
                    stream.eatWhile(/\w/);
                    if (stream.eat(":")) {
                      return 'tag';
                    }
                    cur = stream.current().toLowerCase();
                    style = registers[cur];
                    return style || null;
                  }
            
                  for (var i = 0; i < custom.length; i++) {
                    style = custom[i](ch, stream, state);
                    if (style) {
                      return style;
                    }
                  }
                },
            
                lineComment: lineCommentStartSymbol,
                blockCommentStart: "/*",
                blockCommentEnd: "*/"
              };
            });
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Gas mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="gas.js"></script>
            <style>.CodeMirror {border: 2px inset #dee;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Gas</a>
              </ul>
            </div>
            
            <article>
            <h2>Gas mode</h2>
            <form>
            <textarea id="code" name="code">
            .syntax unified
            .global main
            
            /* 
             *  A
             *  multi-line
             *  comment.
             */
            
            @ A single line comment.
            
            main:
                    push    {sp, lr}
                    ldr     r0, =message
                    bl      puts
                    mov     r0, #0
                    pop     {sp, pc}
            
            message:
                    .asciz "Hello world!<br />"
            </textarea>
                    </form>
            
                    <script>
                        var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                            lineNumbers: true,
                            mode: {name: "gas", architecture: "ARMv6"},
                        });
                    </script>
            
                    <p>Handles AT&amp;T assembler syntax (more specifically this handles
                    the GNU Assembler (gas) syntax.)
                    It takes a single optional configuration parameter:
                    <code>architecture</code>, which can be one of <code>"ARM"</code>,
                    <code>"ARMv6"</code> or <code>"x86"</code>.
                    Including the parameter adds syntax for the registers and special
                    directives for the supplied architecture.
            
                    <p><strong>MIME types defined:</strong> <code>text/x-gas</code></p>
                </article>
            
        • gfm
          • gfm.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../markdown/markdown"), require("../../addon/mode/overlay"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../markdown/markdown", "../../addon/mode/overlay"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("gfm", function(config, modeConfig) {
              var codeDepth = 0;
              function blankLine(state) {
                state.code = false;
                return null;
              }
              var gfmOverlay = {
                startState: function() {
                  return {
                    code: false,
                    codeBlock: false,
                    ateSpace: false
                  };
                },
                copyState: function(s) {
                  return {
                    code: s.code,
                    codeBlock: s.codeBlock,
                    ateSpace: s.ateSpace
                  };
                },
                token: function(stream, state) {
                  state.combineTokens = null;
            
                  // Hack to prevent formatting override inside code blocks (block and inline)
                  if (state.codeBlock) {
                    if (stream.match(/^```/)) {
                      state.codeBlock = false;
                      return null;
                    }
                    stream.skipToEnd();
                    return null;
                  }
                  if (stream.sol()) {
                    state.code = false;
                  }
                  if (stream.sol() && stream.match(/^```/)) {
                    stream.skipToEnd();
                    state.codeBlock = true;
                    return null;
                  }
                  // If this block is changed, it may need to be updated in Markdown mode
                  if (stream.peek() === '`') {
                    stream.next();
                    var before = stream.pos;
                    stream.eatWhile('`');
                    var difference = 1 + stream.pos - before;
                    if (!state.code) {
                      codeDepth = difference;
                      state.code = true;
                    } else {
                      if (difference === codeDepth) { // Must be exact
                        state.code = false;
                      }
                    }
                    return null;
                  } else if (state.code) {
                    stream.next();
                    return null;
                  }
                  // Check if space. If so, links can be formatted later on
                  if (stream.eatSpace()) {
                    state.ateSpace = true;
                    return null;
                  }
                  if (stream.sol() || state.ateSpace) {
                    state.ateSpace = false;
                    if(stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?:[a-f0-9]{7,40}\b)/)) {
                      // User/Project@SHA
                      // User@SHA
                      // SHA
                      state.combineTokens = true;
                      return "link";
                    } else if (stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/)) {
                      // User/Project#Num
                      // User#Num
                      // #Num
                      state.combineTokens = true;
                      return "link";
                    }
                  }
                  if (stream.match(/^((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`*!()\[\]{};:'".,<>?«»“”‘’]))/i) &&
                     stream.string.slice(stream.start - 2, stream.start) != "](") {
                    // URLs
                    // Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls
                    // And then (issue #1160) simplified to make it not crash the Chrome Regexp engine
                    state.combineTokens = true;
                    return "link";
                  }
                  stream.next();
                  return null;
                },
                blankLine: blankLine
              };
            
              var markdownConfig = {
                underscoresBreakWords: false,
                taskLists: true,
                fencedCodeBlocks: true,
                strikethrough: true
              };
              for (var attr in modeConfig) {
                markdownConfig[attr] = modeConfig[attr];
              }
              markdownConfig.name = "markdown";
              CodeMirror.defineMIME("gfmBase", markdownConfig);
              return CodeMirror.overlayMode(CodeMirror.getMode(config, "gfmBase"), gfmOverlay);
            }, "markdown");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: GFM mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/mode/overlay.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../markdown/markdown.js"></script>
            <script src="gfm.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../css/css.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="../clike/clike.js"></script>
            <script src="../meta.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">GFM</a>
              </ul>
            </div>
            
            <article>
            <h2>GFM mode</h2>
            <form><textarea id="code" name="code">
            GitHub Flavored Markdown
            ========================
            
            Everything from markdown plus GFM features:
            
            ## URL autolinking
            
            Underscores_are_allowed_between_words.
            
            ## Strikethrough text
            
            GFM adds syntax to strikethrough text, which is missing from standard Markdown.
            
            ~~Mistaken text.~~
            ~~**works with other fomatting**~~
            
            ~~spans across
            lines~~
            
            ## Fenced code blocks (and syntax highlighting)
            
            ```javascript
            for (var i = 0; i &lt; items.length; i++) {
                console.log(items[i], i); // log them
            }
            ```
            
            ## Task Lists
            
            - [ ] Incomplete task list item
            - [x] **Completed** task list item
            
            ## A bit of GitHub spice
            
            * SHA: be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
            * User@SHA ref: mojombo@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
            * User/Project@SHA: mojombo/god@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
            * \#Num: #1
            * User/#Num: mojombo#1
            * User/Project#Num: mojombo/god#1
            
            See http://github.github.com/github-flavored-markdown/.
            
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: 'gfm',
                    lineNumbers: true,
                    theme: "default"
                  });
                </script>
            
                <p>Optionally depends on other modes for properly highlighted code blocks.</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#gfm_*">normal</a>,  <a href="../../test/index.html#verbose,gfm_*">verbose</a>.</p>
            
              </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4}, "gfm");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
              var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: "gfm", highlightFormatting: true});
              function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); }
            
              FT("codeBackticks",
                 "[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]");
            
              FT("doubleBackticks",
                 "[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]");
            
              FT("codeBlock",
                 "[comment&formatting&formatting-code-block ```css]",
                 "[tag foo]",
                 "[comment&formatting&formatting-code-block ```]");
            
              FT("taskList",
                 "[variable-2&formatting&formatting-list&formatting-list-ul - ][meta&formatting&formatting-task [ ]]][variable-2  foo]",
                 "[variable-2&formatting&formatting-list&formatting-list-ul - ][property&formatting&formatting-task [x]]][variable-2  foo]");
            
              FT("formatting_strikethrough",
                 "[strikethrough&formatting&formatting-strikethrough ~~][strikethrough foo][strikethrough&formatting&formatting-strikethrough ~~]");
            
              FT("formatting_strikethrough",
                 "foo [strikethrough&formatting&formatting-strikethrough ~~][strikethrough bar][strikethrough&formatting&formatting-strikethrough ~~]");
            
              MT("emInWordAsterisk",
                 "foo[em *bar*]hello");
            
              MT("emInWordUnderscore",
                 "foo_bar_hello");
            
              MT("emStrongUnderscore",
                 "[strong __][em&strong _foo__][em _] bar");
            
              MT("fencedCodeBlocks",
                 "[comment ```]",
                 "[comment foo]",
                 "",
                 "[comment ```]",
                 "bar");
            
              MT("fencedCodeBlockModeSwitching",
                 "[comment ```javascript]",
                 "[variable foo]",
                 "",
                 "[comment ```]",
                 "bar");
            
              MT("taskListAsterisk",
                 "[variable-2 * []] foo]", // Invalid; must have space or x between []
                 "[variable-2 * [ ]]bar]", // Invalid; must have space after ]
                 "[variable-2 * [x]]hello]", // Invalid; must have space after ]
                 "[variable-2 * ][meta [ ]]][variable-2  [world]]]", // Valid; tests reference style links
                 "    [variable-3 * ][property [x]]][variable-3  foo]"); // Valid; can be nested
            
              MT("taskListPlus",
                 "[variable-2 + []] foo]", // Invalid; must have space or x between []
                 "[variable-2 + [ ]]bar]", // Invalid; must have space after ]
                 "[variable-2 + [x]]hello]", // Invalid; must have space after ]
                 "[variable-2 + ][meta [ ]]][variable-2  [world]]]", // Valid; tests reference style links
                 "    [variable-3 + ][property [x]]][variable-3  foo]"); // Valid; can be nested
            
              MT("taskListDash",
                 "[variable-2 - []] foo]", // Invalid; must have space or x between []
                 "[variable-2 - [ ]]bar]", // Invalid; must have space after ]
                 "[variable-2 - [x]]hello]", // Invalid; must have space after ]
                 "[variable-2 - ][meta [ ]]][variable-2  [world]]]", // Valid; tests reference style links
                 "    [variable-3 - ][property [x]]][variable-3  foo]"); // Valid; can be nested
            
              MT("taskListNumber",
                 "[variable-2 1. []] foo]", // Invalid; must have space or x between []
                 "[variable-2 2. [ ]]bar]", // Invalid; must have space after ]
                 "[variable-2 3. [x]]hello]", // Invalid; must have space after ]
                 "[variable-2 4. ][meta [ ]]][variable-2  [world]]]", // Valid; tests reference style links
                 "    [variable-3 1. ][property [x]]][variable-3  foo]"); // Valid; can be nested
            
              MT("SHA",
                 "foo [link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] bar");
            
              MT("SHAEmphasis",
                 "[em *foo ][em&link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]");
            
              MT("shortSHA",
                 "foo [link be6a8cc] bar");
            
              MT("tooShortSHA",
                 "foo be6a8c bar");
            
              MT("longSHA",
                 "foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd22 bar");
            
              MT("badSHA",
                 "foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cg2 bar");
            
              MT("userSHA",
                 "foo [link bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] hello");
            
              MT("userSHAEmphasis",
                 "[em *foo ][em&link bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]");
            
              MT("userProjectSHA",
                 "foo [link bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] world");
            
              MT("userProjectSHAEmphasis",
                 "[em *foo ][em&link bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]");
            
              MT("num",
                 "foo [link #1] bar");
            
              MT("numEmphasis",
                 "[em *foo ][em&link #1][em *]");
            
              MT("badNum",
                 "foo #1bar hello");
            
              MT("userNum",
                 "foo [link bar#1] hello");
            
              MT("userNumEmphasis",
                 "[em *foo ][em&link bar#1][em *]");
            
              MT("userProjectNum",
                 "foo [link bar/hello#1] world");
            
              MT("userProjectNumEmphasis",
                 "[em *foo ][em&link bar/hello#1][em *]");
            
              MT("vanillaLink",
                 "foo [link http://www.example.com/] bar");
            
              MT("vanillaLinkPunctuation",
                 "foo [link http://www.example.com/]. bar");
            
              MT("vanillaLinkExtension",
                 "foo [link http://www.example.com/index.html] bar");
            
              MT("vanillaLinkEmphasis",
                 "foo [em *][em&link http://www.example.com/index.html][em *] bar");
            
              MT("notALink",
                 "[comment ```css]",
                 "[tag foo] {[property color]:[keyword black];}",
                 "[comment ```][link http://www.example.com/]");
            
              MT("notALink",
                 "[comment ``foo `bar` http://www.example.com/``] hello");
            
              MT("notALink",
                 "[comment `foo]",
                 "[link http://www.example.com/]",
                 "[comment `foo]",
                 "",
                 "[link http://www.example.com/]");
            
              MT("headerCodeBlockGithub",
                 "[header&header-1 # heading]",
                 "",
                 "[comment ```]",
                 "[comment code]",
                 "[comment ```]",
                 "",
                 "Commit: [link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2]",
                 "Issue: [link #1]",
                 "Link: [link http://www.example.com/]");
            
              MT("strikethrough",
                 "[strikethrough ~~foo~~]");
            
              MT("strikethroughWithStartingSpace",
                 "~~ foo~~");
            
              MT("strikethroughUnclosedStrayTildes",
                "[strikethrough ~~foo~~~]");
            
              MT("strikethroughUnclosedStrayTildes",
                 "[strikethrough ~~foo ~~]");
            
              MT("strikethroughUnclosedStrayTildes",
                "[strikethrough ~~foo ~~ bar]");
            
              MT("strikethroughUnclosedStrayTildes",
                "[strikethrough ~~foo ~~ bar~~]hello");
            
              MT("strikethroughOneLetter",
                 "[strikethrough ~~a~~]");
            
              MT("strikethroughWrapped",
                 "[strikethrough ~~foo]",
                 "[strikethrough foo~~]");
            
              MT("strikethroughParagraph",
                 "[strikethrough ~~foo]",
                 "",
                 "foo[strikethrough ~~bar]");
            
              MT("strikethroughEm",
                 "[strikethrough ~~foo][em&strikethrough *bar*][strikethrough ~~]");
            
              MT("strikethroughEm",
                 "[em *][em&strikethrough ~~foo~~][em *]");
            
              MT("strikethroughStrong",
                 "[strikethrough ~~][strong&strikethrough **foo**][strikethrough ~~]");
            
              MT("strikethroughStrong",
                 "[strong **][strong&strikethrough ~~foo~~][strong **]");
            
            })();
            
        • gherkin
          • gherkin.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*
            Gherkin mode - http://www.cukes.info/
            Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues
            */
            
            // Following Objs from Brackets implementation: https://github.com/tregusti/brackets-gherkin/blob/master/main.js
            //var Quotes = {
            //  SINGLE: 1,
            //  DOUBLE: 2
            //};
            
            //var regex = {
            //  keywords: /(Feature| {2}(Scenario|In order to|As|I)| {4}(Given|When|Then|And))/
            //};
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("gherkin", function () {
              return {
                startState: function () {
                  return {
                    lineNumber: 0,
                    tableHeaderLine: false,
                    allowFeature: true,
                    allowBackground: false,
                    allowScenario: false,
                    allowSteps: false,
                    allowPlaceholders: false,
                    allowMultilineArgument: false,
                    inMultilineString: false,
                    inMultilineTable: false,
                    inKeywordLine: false
                  };
                },
                token: function (stream, state) {
                  if (stream.sol()) {
                    state.lineNumber++;
                    state.inKeywordLine = false;
                    if (state.inMultilineTable) {
                        state.tableHeaderLine = false;
                        if (!stream.match(/\s*\|/, false)) {
                          state.allowMultilineArgument = false;
                          state.inMultilineTable = false;
                        }
                    }
                  }
            
                  stream.eatSpace();
            
                  if (state.allowMultilineArgument) {
            
                    // STRING
                    if (state.inMultilineString) {
                      if (stream.match('"""')) {
                        state.inMultilineString = false;
                        state.allowMultilineArgument = false;
                      } else {
                        stream.match(/.*/);
                      }
                      return "string";
                    }
            
                    // TABLE
                    if (state.inMultilineTable) {
                      if (stream.match(/\|\s*/)) {
                        return "bracket";
                      } else {
                        stream.match(/[^\|]*/);
                        return state.tableHeaderLine ? "header" : "string";
                      }
                    }
            
                    // DETECT START
                    if (stream.match('"""')) {
                      // String
                      state.inMultilineString = true;
                      return "string";
                    } else if (stream.match("|")) {
                      // Table
                      state.inMultilineTable = true;
                      state.tableHeaderLine = true;
                      return "bracket";
                    }
            
                  }
            
                  // LINE COMMENT
                  if (stream.match(/#.*/)) {
                    return "comment";
            
                  // TAG
                  } else if (!state.inKeywordLine && stream.match(/@\S+/)) {
                    return "tag";
            
                  // FEATURE
                  } else if (!state.inKeywordLine && state.allowFeature && stream.match(/(機能|功能|フィーチャ|기능|โครงหลัก|ความสามารถ|ความต้องการทางธุรกิจ|ಹೆಚ್ಚಳ|గుణము|ਮੁਹਾਂਦਰਾ|ਨਕਸ਼ ਨੁਹਾਰ|ਖਾਸੀਅਤ|रूप लेख|وِیژگی|خاصية|תכונה|Функціонал|Функция|Функционалност|Функционал|Үзенчәлеклелек|Свойство|Особина|Мөмкинлек|Могућност|Λειτουργία|Δυνατότητα|Właściwość|Vlastnosť|Trajto|Tính năng|Savybė|Pretty much|Požiadavka|Požadavek|Potrzeba biznesowa|Özellik|Osobina|Ominaisuus|Omadus|OH HAI|Mogućnost|Mogucnost|Jellemző|Hwæt|Hwaet|Funzionalità|Funktionalitéit|Funktionalität|Funkcja|Funkcionalnost|Funkcionalitāte|Funkcia|Fungsi|Functionaliteit|Funcționalitate|Funcţionalitate|Functionalitate|Funcionalitat|Funcionalidade|Fonctionnalité|Fitur|Fīča|Feature|Eiginleiki|Egenskap|Egenskab|Característica|Caracteristica|Business Need|Aspekt|Arwedd|Ahoy matey!|Ability):/)) {
                    state.allowScenario = true;
                    state.allowBackground = true;
                    state.allowPlaceholders = false;
                    state.allowSteps = false;
                    state.allowMultilineArgument = false;
                    state.inKeywordLine = true;
                    return "keyword";
            
                  // BACKGROUND
                  } else if (!state.inKeywordLine && state.allowBackground && stream.match(/(背景|배경|แนวคิด|ಹಿನ್ನೆಲೆ|నేపథ్యం|ਪਿਛੋਕੜ|पृष्ठभूमि|زمینه|الخلفية|רקע|Тарих|Предыстория|Предистория|Позадина|Передумова|Основа|Контекст|Кереш|Υπόβαθρο|Założenia|Yo\-ho\-ho|Tausta|Taust|Situācija|Rerefons|Pozadina|Pozadie|Pozadí|Osnova|Latar Belakang|Kontext|Konteksts|Kontekstas|Kontekst|Háttér|Hannergrond|Grundlage|Geçmiş|Fundo|Fono|First off|Dis is what went down|Dasar|Contexto|Contexte|Context|Contesto|Cenário de Fundo|Cenario de Fundo|Cefndir|Bối cảnh|Bakgrunnur|Bakgrunn|Bakgrund|Baggrund|Background|B4|Antecedents|Antecedentes|Ær|Aer|Achtergrond):/)) {
                    state.allowPlaceholders = false;
                    state.allowSteps = true;
                    state.allowBackground = false;
                    state.allowMultilineArgument = false;
                    state.inKeywordLine = true;
                    return "keyword";
            
                  // SCENARIO OUTLINE
                  } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景大綱|场景大纲|劇本大綱|剧本大纲|テンプレ|シナリオテンプレート|シナリオテンプレ|シナリオアウトライン|시나리오 개요|สรุปเหตุการณ์|โครงสร้างของเหตุการณ์|ವಿವರಣೆ|కథనం|ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ|ਪਟਕਥਾ ਢਾਂਚਾ|परिदृश्य रूपरेखा|سيناريو مخطط|الگوی سناریو|תבנית תרחיש|Сценарийның төзелеше|Сценарий структураси|Структура сценарію|Структура сценария|Структура сценарија|Скица|Рамка на сценарий|Концепт|Περιγραφή Σεναρίου|Wharrimean is|Template Situai|Template Senario|Template Keadaan|Tapausaihio|Szenariogrundriss|Szablon scenariusza|Swa hwær swa|Swa hwaer swa|Struktura scenarija|Structură scenariu|Structura scenariu|Skica|Skenario konsep|Shiver me timbers|Senaryo taslağı|Schema dello scenario|Scenariomall|Scenariomal|Scenario Template|Scenario Outline|Scenario Amlinellol|Scenārijs pēc parauga|Scenarijaus šablonas|Reckon it's like|Raamstsenaarium|Plang vum Szenario|Plan du Scénario|Plan du scénario|Osnova scénáře|Osnova Scenára|Náčrt Scenáru|Náčrt Scénáře|Náčrt Scenára|MISHUN SRSLY|Menggariskan Senario|Lýsing Dæma|Lýsing Atburðarásar|Konturo de la scenaro|Koncept|Khung tình huống|Khung kịch bản|Forgatókönyv vázlat|Esquema do Cenário|Esquema do Cenario|Esquema del escenario|Esquema de l'escenari|Esbozo do escenario|Delineação do Cenário|Delineacao do Cenario|All y'all|Abstrakt Scenario|Abstract Scenario):/)) {
                    state.allowPlaceholders = true;
                    state.allowSteps = true;
                    state.allowMultilineArgument = false;
                    state.inKeywordLine = true;
                    return "keyword";
            
                  // EXAMPLES
                  } else if (state.allowScenario && stream.match(/(例子|例|サンプル|예|ชุดของเหตุการณ์|ชุดของตัวอย่าง|ಉದಾಹರಣೆಗಳು|ఉదాహరణలు|ਉਦਾਹਰਨਾਂ|उदाहरण|نمونه ها|امثلة|דוגמאות|Үрнәкләр|Сценарији|Примеры|Примери|Приклади|Мисоллар|Мисаллар|Σενάρια|Παραδείγματα|You'll wanna|Voorbeelden|Variantai|Tapaukset|Se þe|Se the|Se ðe|Scenarios|Scenariji|Scenarijai|Przykłady|Primjeri|Primeri|Příklady|Príklady|Piemēri|Példák|Pavyzdžiai|Paraugs|Örnekler|Juhtumid|Exemplos|Exemples|Exemple|Exempel|EXAMPLZ|Examples|Esempi|Enghreifftiau|Ekzemploj|Eksempler|Ejemplos|Dữ liệu|Dead men tell no tales|Dæmi|Contoh|Cenários|Cenarios|Beispiller|Beispiele|Atburðarásir):/)) {
                    state.allowPlaceholders = false;
                    state.allowSteps = true;
                    state.allowBackground = false;
                    state.allowMultilineArgument = true;
                    return "keyword";
            
                  // SCENARIO
                  } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景|场景|劇本|剧本|シナリオ|시나리오|เหตุการณ์|ಕಥಾಸಾರಾಂಶ|సన్నివేశం|ਪਟਕਥਾ|परिदृश्य|سيناريو|سناریو|תרחיש|Сценарій|Сценарио|Сценарий|Пример|Σενάριο|Tình huống|The thing of it is|Tapaus|Szenario|Swa|Stsenaarium|Skenario|Situai|Senaryo|Senario|Scenaro|Scenariusz|Scenariu|Scénario|Scenario|Scenarijus|Scenārijs|Scenarij|Scenarie|Scénář|Scenár|Primer|MISHUN|Kịch bản|Keadaan|Heave to|Forgatókönyv|Escenario|Escenari|Cenário|Cenario|Awww, look mate|Atburðarás):/)) {
                    state.allowPlaceholders = false;
                    state.allowSteps = true;
                    state.allowBackground = false;
                    state.allowMultilineArgument = false;
                    state.inKeywordLine = true;
                    return "keyword";
            
                  // STEPS
                  } else if (!state.inKeywordLine && state.allowSteps && stream.match(/(那麼|那么|而且|當|当|并且|同時|同时|前提|假设|假設|假定|假如|但是|但し|並且|もし|ならば|ただし|しかし|かつ|하지만|조건|먼저|만일|만약|단|그리고|그러면|และ |เมื่อ |แต่ |ดังนั้น |กำหนดให้ |ಸ್ಥಿತಿಯನ್ನು |ಮತ್ತು |ನೀಡಿದ |ನಂತರ |ಆದರೆ |మరియు |చెప్పబడినది |కాని |ఈ పరిస్థితిలో |అప్పుడు |ਪਰ |ਤਦ |ਜੇਕਰ |ਜਿਵੇਂ ਕਿ |ਜਦੋਂ |ਅਤੇ |यदि |परन्तु |पर |तब |तदा |तथा |जब |चूंकि |किन्तु |कदा |और |अगर |و |هنگامی |متى |لكن |عندما |ثم |بفرض |با فرض |اما |اذاً |آنگاه |כאשר |וגם |בהינתן |אזי |אז |אבל |Якщо |Һәм |Унда |Тоді |Тогда |То |Также |Та |Пусть |Припустимо, що |Припустимо |Онда |Но |Нехай |Нәтиҗәдә |Лекин |Ләкин |Коли |Когда |Когато |Када |Кад |К тому же |І |И |Задато |Задати |Задате |Если |Допустим |Дано |Дадено |Вә |Ва |Бирок |Әмма |Әйтик |Әгәр |Аммо |Али |Але |Агар |А також |А |Τότε |Όταν |Και |Δεδομένου |Αλλά |Þurh |Þegar |Þa þe |Þá |Þa |Zatati |Zakładając |Zadato |Zadate |Zadano |Zadani |Zadan |Za předpokladu |Za predpokladu |Youse know when youse got |Youse know like when |Yna |Yeah nah |Y'know |Y |Wun |Wtedy |When y'all |When |Wenn |WEN |wann |Ve |Và |Und |Un |ugeholl |Too right |Thurh |Thì |Then y'all |Then |Tha the |Tha |Tetapi |Tapi |Tak |Tada |Tad |Stel |Soit |Siis |Și |Şi |Si |Sed |Se |Så |Quando |Quand |Quan |Pryd |Potom |Pokud |Pokiaľ |Però |Pero |Pak |Oraz |Onda |Ond |Oletetaan |Og |Och |O zaman |Niin |Nhưng |När |Når |Mutta |Men |Mas |Maka |Majd |Mając |Mais |Maar |mä |Ma |Lorsque |Lorsqu'|Logo |Let go and haul |Kun |Kuid |Kui |Kiedy |Khi |Ketika |Kemudian |Keď |Když |Kaj |Kai |Kada |Kad |Jeżeli |Jeśli |Ja |It's just unbelievable |Ir |I CAN HAZ |I |Ha |Givun |Givet |Given y'all |Given |Gitt |Gegeven |Gegeben seien |Gegeben sei |Gdy |Gangway! |Fakat |Étant donnés |Etant donnés |Étant données |Etant données |Étant donnée |Etant donnée |Étant donné |Etant donné |Et |És |Entonces |Entón |Então |Entao |En |Eğer ki |Ef |Eeldades |E |Ðurh |Duota |Dun |Donitaĵo |Donat |Donada |Do |Diyelim ki |Diberi |Dengan |Den youse gotta |DEN |De |Dato |Dați fiind |Daţi fiind |Dati fiind |Dati |Date fiind |Date |Data |Dat fiind |Dar |Dann |dann |Dan |Dados |Dado |Dadas |Dada |Ða ðe |Ða |Cuando |Cho |Cando |Când |Cand |Cal |But y'all |But at the end of the day I reckon |BUT |But |Buh |Blimey! |Biết |Bet |Bagi |Aye |awer |Avast! |Atunci |Atesa |Atès |Apabila |Anrhegedig a |Angenommen |And y'all |And |AN |An |an |Amikor |Amennyiben |Ama |Als |Alors |Allora |Ali |Aleshores |Ale |Akkor |Ak |Adott |Ac |Aber |A zároveň |A tiež |A taktiež |A také |A |a |7 |\* )/)) {
                    state.inStep = true;
                    state.allowPlaceholders = true;
                    state.allowMultilineArgument = true;
                    state.inKeywordLine = true;
                    return "keyword";
            
                  // INLINE STRING
                  } else if (stream.match(/"[^"]*"?/)) {
                    return "string";
            
                  // PLACEHOLDER
                  } else if (state.allowPlaceholders && stream.match(/<[^>]*>?/)) {
                    return "variable";
            
                  // Fall through
                  } else {
                    stream.next();
                    stream.eatWhile(/[^@"<#]/);
                    return null;
                  }
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-feature", "gherkin");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Gherkin mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="gherkin.js"></script>
            <style>.CodeMirror { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; }</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Gherkin</a>
              </ul>
            </div>
            
            <article>
            <h2>Gherkin mode</h2>
            <form><textarea id="code" name="code">
            Feature: Using Google
              Background: 
                Something something
                Something else
              Scenario: Has a homepage
                When I navigate to the google home page
                Then the home page should contain the menu and the search form
              Scenario: Searching for a term 
                When I navigate to the google home page
                When I search for Tofu
                Then the search results page is displayed
                Then the search results page contains 10 individual search results
                Then the search results contain a link to the wikipedia tofu page
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-feature</code>.</p>
            
              </article>
            
        • go
          • go.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("go", function(config) {
              var indentUnit = config.indentUnit;
            
              var keywords = {
                "break":true, "case":true, "chan":true, "const":true, "continue":true,
                "default":true, "defer":true, "else":true, "fallthrough":true, "for":true,
                "func":true, "go":true, "goto":true, "if":true, "import":true,
                "interface":true, "map":true, "package":true, "range":true, "return":true,
                "select":true, "struct":true, "switch":true, "type":true, "var":true,
                "bool":true, "byte":true, "complex64":true, "complex128":true,
                "float32":true, "float64":true, "int8":true, "int16":true, "int32":true,
                "int64":true, "string":true, "uint8":true, "uint16":true, "uint32":true,
                "uint64":true, "int":true, "uint":true, "uintptr":true
              };
            
              var atoms = {
                "true":true, "false":true, "iota":true, "nil":true, "append":true,
                "cap":true, "close":true, "complex":true, "copy":true, "imag":true,
                "len":true, "make":true, "new":true, "panic":true, "print":true,
                "println":true, "real":true, "recover":true
              };
            
              var isOperatorChar = /[+\-*&^%:=<>!|\/]/;
            
              var curPunc;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"' || ch == "'" || ch == "`") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                if (/[\d\.]/.test(ch)) {
                  if (ch == ".") {
                    stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/);
                  } else if (ch == "0") {
                    stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/);
                  } else {
                    stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/);
                  }
                  return "number";
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                if (ch == "/") {
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment;
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                }
                if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_\xa1-\uffff]/);
                var cur = stream.current();
                if (keywords.propertyIsEnumerable(cur)) {
                  if (cur == "case" || cur == "default") curPunc = "case";
                  return "keyword";
                }
                if (atoms.propertyIsEnumerable(cur)) return "atom";
                return "variable";
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {end = true; break;}
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !(escaped || quote == "`"))
                    state.tokenize = tokenBase;
                  return "string";
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
              function pushContext(state, col, type) {
                return state.context = new Context(state.indented, col, type, null, state.context);
              }
              function popContext(state) {
                if (!state.context.prev) return;
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}")
                  state.indented = state.context.indented;
                return state.context = state.context.prev;
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                  return {
                    tokenize: null,
                    context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true
                  };
                },
            
                token: function(stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                    if (ctx.type == "case") ctx.type = "}";
                  }
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment") return style;
                  if (ctx.align == null) ctx.align = true;
            
                  if (curPunc == "{") pushContext(state, stream.column(), "}");
                  else if (curPunc == "[") pushContext(state, stream.column(), "]");
                  else if (curPunc == "(") pushContext(state, stream.column(), ")");
                  else if (curPunc == "case") ctx.type = "case";
                  else if (curPunc == "}" && ctx.type == "}") ctx = popContext(state);
                  else if (curPunc == ctx.type) popContext(state);
                  state.startOfLine = false;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase && state.tokenize != null) return 0;
                  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
                  if (ctx.type == "case" && /^(?:case|default)\b/.test(textAfter)) {
                    state.context.type = "}";
                    return ctx.indented;
                  }
                  var closing = firstChar == ctx.type;
                  if (ctx.align) return ctx.column + (closing ? 0 : 1);
                  else return ctx.indented + (closing ? 0 : indentUnit);
                },
            
                electricChars: "{}):",
                fold: "brace",
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                lineComment: "//"
              };
            });
            
            CodeMirror.defineMIME("text/x-go", "go");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Go mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/elegant.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="go.js"></script>
            <style>.CodeMirror {border:1px solid #999; background:#ffc}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Go</a>
              </ul>
            </div>
            
            <article>
            <h2>Go mode</h2>
            <form><textarea id="code" name="code">
            // Prime Sieve in Go.
            // Taken from the Go specification.
            // Copyright © The Go Authors.
            
            package main
            
            import "fmt"
            
            // Send the sequence 2, 3, 4, ... to channel 'ch'.
            func generate(ch chan&lt;- int) {
            	for i := 2; ; i++ {
            		ch &lt;- i  // Send 'i' to channel 'ch'
            	}
            }
            
            // Copy the values from channel 'src' to channel 'dst',
            // removing those divisible by 'prime'.
            func filter(src &lt;-chan int, dst chan&lt;- int, prime int) {
            	for i := range src {    // Loop over values received from 'src'.
            		if i%prime != 0 {
            			dst &lt;- i  // Send 'i' to channel 'dst'.
            		}
            	}
            }
            
            // The prime sieve: Daisy-chain filter processes together.
            func sieve() {
            	ch := make(chan int)  // Create a new channel.
            	go generate(ch)       // Start generate() as a subprocess.
            	for {
            		prime := &lt;-ch
            		fmt.Print(prime, "\n")
            		ch1 := make(chan int)
            		go filter(ch, ch1, prime)
            		ch = ch1
            	}
            }
            
            func main() {
            	sieve()
            }
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    theme: "elegant",
                    matchBrackets: true,
                    indentUnit: 8,
                    tabSize: 8,
                    indentWithTabs: true,
                    mode: "text/x-go"
                  });
                </script>
            
                <p><strong>MIME type:</strong> <code>text/x-go</code></p>
              </article>
            
        • groovy
          • groovy.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("groovy", function(config) {
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
              var keywords = words(
                "abstract as assert boolean break byte case catch char class const continue def default " +
                "do double else enum extends final finally float for goto if implements import in " +
                "instanceof int interface long native new package private protected public return " +
                "short static strictfp super switch synchronized threadsafe throw throws transient " +
                "try void volatile while");
              var blockKeywords = words("catch class do else finally for if switch try while enum interface def");
              var atoms = words("null true false this");
            
              var curPunc;
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"' || ch == "'") {
                  return startString(ch, stream, state);
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  if (stream.eat(/eE/)) { stream.eat(/\+\-/); stream.eatWhile(/\d/); }
                  return "number";
                }
                if (ch == "/") {
                  if (stream.eat("*")) {
                    state.tokenize.push(tokenComment);
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                  if (expectExpression(state.lastToken)) {
                    return startString(ch, stream, state);
                  }
                }
                if (ch == "-" && stream.eat(">")) {
                  curPunc = "->";
                  return null;
                }
                if (/[+\-*&%=<>!?|\/~]/.test(ch)) {
                  stream.eatWhile(/[+\-*&%=<>|~]/);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_]/);
                if (ch == "@") { stream.eatWhile(/[\w\$_\.]/); return "meta"; }
                if (state.lastToken == ".") return "property";
                if (stream.eat(":")) { curPunc = "proplabel"; return "property"; }
                var cur = stream.current();
                if (atoms.propertyIsEnumerable(cur)) { return "atom"; }
                if (keywords.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "keyword";
                }
                return "variable";
              }
              tokenBase.isBase = true;
            
              function startString(quote, stream, state) {
                var tripleQuoted = false;
                if (quote != "/" && stream.eat(quote)) {
                  if (stream.eat(quote)) tripleQuoted = true;
                  else return "string";
                }
                function t(stream, state) {
                  var escaped = false, next, end = !tripleQuoted;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {
                      if (!tripleQuoted) { break; }
                      if (stream.match(quote + quote)) { end = true; break; }
                    }
                    if (quote == '"' && next == "$" && !escaped && stream.eat("{")) {
                      state.tokenize.push(tokenBaseUntilBrace());
                      return "string";
                    }
                    escaped = !escaped && next == "\\";
                  }
                  if (end) state.tokenize.pop();
                  return "string";
                }
                state.tokenize.push(t);
                return t(stream, state);
              }
            
              function tokenBaseUntilBrace() {
                var depth = 1;
                function t(stream, state) {
                  if (stream.peek() == "}") {
                    depth--;
                    if (depth == 0) {
                      state.tokenize.pop();
                      return state.tokenize[state.tokenize.length-1](stream, state);
                    }
                  } else if (stream.peek() == "{") {
                    depth++;
                  }
                  return tokenBase(stream, state);
                }
                t.isBase = true;
                return t;
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize.pop();
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function expectExpression(last) {
                return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) ||
                  last == "newstatement" || last == "keyword" || last == "proplabel";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
              function pushContext(state, col, type) {
                return state.context = new Context(state.indented, col, type, null, state.context);
              }
              function popContext(state) {
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}")
                  state.indented = state.context.indented;
                return state.context = state.context.prev;
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                  return {
                    tokenize: [tokenBase],
                    context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true,
                    lastToken: null
                  };
                },
            
                token: function(stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                    // Automatic semicolon insertion
                    if (ctx.type == "statement" && !expectExpression(state.lastToken)) {
                      popContext(state); ctx = state.context;
                    }
                  }
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  var style = state.tokenize[state.tokenize.length-1](stream, state);
                  if (style == "comment") return style;
                  if (ctx.align == null) ctx.align = true;
            
                  if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
                  // Handle indentation for {x -> \n ... }
                  else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") {
                    popContext(state);
                    state.context.align = false;
                  }
                  else if (curPunc == "{") pushContext(state, stream.column(), "}");
                  else if (curPunc == "[") pushContext(state, stream.column(), "]");
                  else if (curPunc == "(") pushContext(state, stream.column(), ")");
                  else if (curPunc == "}") {
                    while (ctx.type == "statement") ctx = popContext(state);
                    if (ctx.type == "}") ctx = popContext(state);
                    while (ctx.type == "statement") ctx = popContext(state);
                  }
                  else if (curPunc == ctx.type) popContext(state);
                  else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
                    pushContext(state, stream.column(), "statement");
                  state.startOfLine = false;
                  state.lastToken = curPunc || style;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (!state.tokenize[state.tokenize.length-1].isBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;
                  if (ctx.type == "statement" && !expectExpression(state.lastToken)) ctx = ctx.prev;
                  var closing = firstChar == ctx.type;
                  if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit);
                  else if (ctx.align) return ctx.column + (closing ? 0 : 1);
                  else return ctx.indented + (closing ? 0 : config.indentUnit);
                },
            
                electricChars: "{}",
                closeBrackets: {triples: "'\""},
                fold: "brace"
              };
            });
            
            CodeMirror.defineMIME("text/x-groovy", "groovy");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Groovy mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="groovy.js"></script>
            <style>.CodeMirror {border-top: 1px solid #500; border-bottom: 1px solid #500;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Groovy</a>
              </ul>
            </div>
            
            <article>
            <h2>Groovy mode</h2>
            <form><textarea id="code" name="code">
            //Pattern for groovy script
            def p = ~/.*\.groovy/
            new File( 'd:\\scripts' ).eachFileMatch(p) {f ->
              // imports list
              def imports = []
              f.eachLine {
                // condition to detect an import instruction
                ln -> if ( ln =~ '^import .*' ) {
                  imports << "${ln - 'import '}"
                }
              }
              // print thmen
              if ( ! imports.empty ) {
                println f
                imports.each{ println "   $it" }
              }
            }
            
            /* Coin changer demo code from http://groovy.codehaus.org */
            
            enum UsCoin {
              quarter(25), dime(10), nickel(5), penny(1)
              UsCoin(v) { value = v }
              final value
            }
            
            enum OzzieCoin {
              fifty(50), twenty(20), ten(10), five(5)
              OzzieCoin(v) { value = v }
              final value
            }
            
            def plural(word, count) {
              if (count == 1) return word
              word[-1] == 'y' ? word[0..-2] + "ies" : word + "s"
            }
            
            def change(currency, amount) {
              currency.values().inject([]){ list, coin ->
                 int count = amount / coin.value
                 amount = amount % coin.value
                 list += "$count ${plural(coin.toString(), count)}"
              }
            }
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-groovy"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-groovy</code></p>
              </article>
            
        • haml
          • haml.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
              // full haml mode. This handled embeded ruby and html fragments too
              CodeMirror.defineMode("haml", function(config) {
                var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"});
                var rubyMode = CodeMirror.getMode(config, "ruby");
            
                function rubyInQuote(endQuote) {
                  return function(stream, state) {
                    var ch = stream.peek();
                    if (ch == endQuote && state.rubyState.tokenize.length == 1) {
                      // step out of ruby context as it seems to complete processing all the braces
                      stream.next();
                      state.tokenize = html;
                      return "closeAttributeTag";
                    } else {
                      return ruby(stream, state);
                    }
                  };
                }
            
                function ruby(stream, state) {
                  if (stream.match("-#")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                  return rubyMode.token(stream, state.rubyState);
                }
            
                function html(stream, state) {
                  var ch = stream.peek();
            
                  // handle haml declarations. All declarations that cant be handled here
                  // will be passed to html mode
                  if (state.previousToken.style == "comment" ) {
                    if (state.indented > state.previousToken.indented) {
                      stream.skipToEnd();
                      return "commentLine";
                    }
                  }
            
                  if (state.startOfLine) {
                    if (ch == "!" && stream.match("!!")) {
                      stream.skipToEnd();
                      return "tag";
                    } else if (stream.match(/^%[\w:#\.]+=/)) {
                      state.tokenize = ruby;
                      return "hamlTag";
                    } else if (stream.match(/^%[\w:]+/)) {
                      return "hamlTag";
                    } else if (ch == "/" ) {
                      stream.skipToEnd();
                      return "comment";
                    }
                  }
            
                  if (state.startOfLine || state.previousToken.style == "hamlTag") {
                    if ( ch == "#" || ch == ".") {
                      stream.match(/[\w-#\.]*/);
                      return "hamlAttribute";
                    }
                  }
            
                  // donot handle --> as valid ruby, make it HTML close comment instead
                  if (state.startOfLine && !stream.match("-->", false) && (ch == "=" || ch == "-" )) {
                    state.tokenize = ruby;
                    return state.tokenize(stream, state);
                  }
            
                  if (state.previousToken.style == "hamlTag" ||
                      state.previousToken.style == "closeAttributeTag" ||
                      state.previousToken.style == "hamlAttribute") {
                    if (ch == "(") {
                      state.tokenize = rubyInQuote(")");
                      return state.tokenize(stream, state);
                    } else if (ch == "{") {
                      state.tokenize = rubyInQuote("}");
                      return state.tokenize(stream, state);
                    }
                  }
            
                  return htmlMode.token(stream, state.htmlState);
                }
            
                return {
                  // default to html mode
                  startState: function() {
                    var htmlState = htmlMode.startState();
                    var rubyState = rubyMode.startState();
                    return {
                      htmlState: htmlState,
                      rubyState: rubyState,
                      indented: 0,
                      previousToken: { style: null, indented: 0},
                      tokenize: html
                    };
                  },
            
                  copyState: function(state) {
                    return {
                      htmlState : CodeMirror.copyState(htmlMode, state.htmlState),
                      rubyState: CodeMirror.copyState(rubyMode, state.rubyState),
                      indented: state.indented,
                      previousToken: state.previousToken,
                      tokenize: state.tokenize
                    };
                  },
            
                  token: function(stream, state) {
                    if (stream.sol()) {
                      state.indented = stream.indentation();
                      state.startOfLine = true;
                    }
                    if (stream.eatSpace()) return null;
                    var style = state.tokenize(stream, state);
                    state.startOfLine = false;
                    // dont record comment line as we only want to measure comment line with
                    // the opening comment block
                    if (style && style != "commentLine") {
                      state.previousToken = { style: style, indented: state.indented };
                    }
                    // if current state is ruby and the previous token is not `,` reset the
                    // tokenize to html
                    if (stream.eol() && state.tokenize == ruby) {
                      stream.backUp(1);
                      var ch = stream.peek();
                      stream.next();
                      if (ch && ch != ",") {
                        state.tokenize = html;
                      }
                    }
                    // reprocess some of the specific style tag when finish setting previousToken
                    if (style == "hamlTag") {
                      style = "tag";
                    } else if (style == "commentLine") {
                      style = "comment";
                    } else if (style == "hamlAttribute") {
                      style = "attribute";
                    } else if (style == "closeAttributeTag") {
                      style = null;
                    }
                    return style;
                  }
                };
              }, "htmlmixed", "ruby");
            
              CodeMirror.defineMIME("text/x-haml", "haml");
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: HAML mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../ruby/ruby.js"></script>
            <script src="haml.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">HAML</a>
              </ul>
            </div>
            
            <article>
            <h2>HAML mode</h2>
            <form><textarea id="code" name="code">
            !!!
            #content
            .left.column(title="title"){:href => "/hello", :test => "#{hello}_#{world}"}
                <!-- This is a comment -->
                %h2 Welcome to our site!
                %p= puts "HAML MODE"
              .right.column
                = render :partial => "sidebar"
            
            .container
              .row
                .span8
                  %h1.title= @page_title
            %p.title= @page_title
            %p
              /
                The same as HTML comment
                Hello multiline comment
            
              -# haml comment
                  This wont be displayed
                  nor will this
              Date/Time:
              - now = DateTime.now
              %strong= now
              - if now > DateTime.parse("December 31, 2006")
                = "Happy new " + "year!"
            
            %title
              = @title
              \= @title
              <h1>Title</h1>
              <h1 title="HELLO">
                Title
              </h1>
                </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "text/x-haml"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-haml</code>.</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#haml_*">normal</a>,  <a href="../../test/index.html#verbose,haml_*">verbose</a>.</p>
            
              </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "haml");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              // Requires at least one media query
              MT("elementName",
                 "[tag %h1] Hey There");
            
              MT("oneElementPerLine",
                 "[tag %h1] Hey There %h2");
            
              MT("idSelector",
                 "[tag %h1][attribute #test] Hey There");
            
              MT("classSelector",
                 "[tag %h1][attribute .hello] Hey There");
            
              MT("docType",
                 "[tag !!! XML]");
            
              MT("comment",
                 "[comment / Hello WORLD]");
            
              MT("notComment",
                 "[tag %h1] This is not a / comment ");
            
              MT("attributes",
                 "[tag %a]([variable title][operator =][string \"test\"]){[atom :title] [operator =>] [string \"test\"]}");
            
              MT("htmlCode",
                 "[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket </][tag h1][tag&bracket >]");
            
              MT("rubyBlock",
                 "[operator =][variable-2 @item]");
            
              MT("selectorRubyBlock",
                 "[tag %a.selector=] [variable-2 @item]");
            
              MT("nestedRubyBlock",
                  "[tag %a]",
                  "   [operator =][variable puts] [string \"test\"]");
            
              MT("multilinePlaintext",
                  "[tag %p]",
                  "  Hello,",
                  "  World");
            
              MT("multilineRuby",
                  "[tag %p]",
                  "  [comment -# this is a comment]",
                  "     [comment and this is a comment too]",
                  "  Date/Time",
                  "  [operator -] [variable now] [operator =] [tag DateTime][operator .][property now]",
                  "  [tag %strong=] [variable now]",
                  "  [operator -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \"December 31, 2006\"])",
                  "     [operator =][string \"Happy\"]",
                  "     [operator =][string \"Belated\"]",
                  "     [operator =][string \"Birthday\"]");
            
              MT("multilineComment",
                  "[comment /]",
                  "  [comment Multiline]",
                  "  [comment Comment]");
            
              MT("hamlComment",
                 "[comment -# this is a comment]");
            
              MT("multilineHamlComment",
                 "[comment -# this is a comment]",
                 "   [comment and this is a comment too]");
            
              MT("multilineHTMLComment",
                "[comment <!--]",
                "  [comment what a comment]",
                "  [comment -->]");
            
              MT("hamlAfterRubyTag",
                "[attribute .block]",
                "  [tag %strong=] [variable now]",
                "  [attribute .test]",
                "     [operator =][variable now]",
                "  [attribute .right]");
            
              MT("stretchedRuby",
                 "[operator =] [variable puts] [string \"Hello\"],",
                 "   [string \"World\"]");
            
              MT("interpolationInHashAttribute",
                 //"[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test");
                 "[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test");
            
              MT("interpolationInHTMLAttribute",
                 "[tag %div]([variable title][operator =][string \"#{][variable test][string }_#{][variable ting]()[string }\"]) Test");
            })();
            
        • handlebars
          • handlebars.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../../addon/mode/simple"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../../addon/mode/simple"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineSimpleMode("handlebars", {
                start: [
                  { regex: /\{\{!--/, push: "dash_comment", token: "comment" },
                  { regex: /\{\{!/,   push: "comment", token: "comment" },
                  { regex: /\{\{/,    push: "handlebars", token: "tag" }
                ],
                handlebars: [
                  { regex: /\}\}/, pop: true, token: "tag" },
            
                  // Double and single quotes
                  { regex: /"(?:[^\\]|\\.)*?"/, token: "string" },
                  { regex: /'(?:[^\\]|\\.)*?'/, token: "string" },
            
                  // Handlebars keywords
                  { regex: />|[#\/]([A-Za-z_]\w*)/, token: "keyword" },
                  { regex: /(?:else|this)\b/, token: "keyword" },
            
                  // Numeral
                  { regex: /\d+/i, token: "number" },
            
                  // Atoms like = and .
                  { regex: /=|~|@|true|false/, token: "atom" },
            
                  // Paths
                  { regex: /(?:\.\.\/)*(?:[A-Za-z_][\w\.]*)+/, token: "variable-2" }
                ],
                dash_comment: [
                  { regex: /--\}\}/, pop: true, token: "comment" },
            
                  // Commented code
                  { regex: /./, token: "comment"}
                ],
                comment: [
                  { regex: /\}\}/, pop: true, token: "comment" },
                  { regex: /./, token: "comment" }
                ]
              });
            
              CodeMirror.defineMIME("text/x-handlebars-template", "handlebars");
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Handlebars mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/mode/simple.js"></script>
            <script src="../../addon/mode/multiplex.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="handlebars.js"></script>
            <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">HTML mixed</a>
              </ul>
            </div>
            
            <article>
            <h2>Handlebars</h2>
            <form><textarea id="code" name="code">
            {{> breadcrumbs}}
            
            {{!--
              You can use the t function to get
              content translated to the current locale, es:
              {{t 'article_list'}}
            --}}
            
            <h1>{{t 'article_list'}}</h1>
            
            {{! one line comment }}
            
            {{#each articles}}
              {{~title}}
              <p>{{excerpt body size=120 ellipsis=true}}</p>
            
              {{#with author}}
                written by {{first_name}} {{last_name}}
                from category: {{../category.title}}
                {{#if @../last}}foobar!{{/if}}
              {{/with~}}
            
              {{#if promoted.latest}}Read this one! {{else}} This is ok! {{/if}}
            
              {{#if @last}}<hr>{{/if}}
            {{/each}}
            
            {{#form new_comment}}
              <input type="text" name="body">
            {{/form}}
            
            </textarea></form>
                <script>
                  CodeMirror.defineMode("htmlhandlebars", function(config) {
                    return CodeMirror.multiplexingMode(
                      CodeMirror.getMode(config, "text/html"),
                      {open: "{{", close: "}}",
                       mode: CodeMirror.getMode(config, "handlebars"),
                       parseDelimiters: true});
                  });
            
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "htmlhandlebars"
                  });
                </script>
                </script>
            
                <p>Handlebars syntax highlighting for CodeMirror.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-handlebars-template</code></p>
            </article>
            
        • haskell
          • haskell.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("haskell", function(_config, modeConfig) {
            
              function switchState(source, setState, f) {
                setState(f);
                return f(source, setState);
              }
            
              // These should all be Unicode extended, as per the Haskell 2010 report
              var smallRE = /[a-z_]/;
              var largeRE = /[A-Z]/;
              var digitRE = /\d/;
              var hexitRE = /[0-9A-Fa-f]/;
              var octitRE = /[0-7]/;
              var idRE = /[a-z_A-Z0-9'\xa1-\uffff]/;
              var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:]/;
              var specialRE = /[(),;[\]`{}]/;
              var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer
            
              function normal(source, setState) {
                if (source.eatWhile(whiteCharRE)) {
                  return null;
                }
            
                var ch = source.next();
                if (specialRE.test(ch)) {
                  if (ch == '{' && source.eat('-')) {
                    var t = "comment";
                    if (source.eat('#')) {
                      t = "meta";
                    }
                    return switchState(source, setState, ncomment(t, 1));
                  }
                  return null;
                }
            
                if (ch == '\'') {
                  if (source.eat('\\')) {
                    source.next();  // should handle other escapes here
                  }
                  else {
                    source.next();
                  }
                  if (source.eat('\'')) {
                    return "string";
                  }
                  return "error";
                }
            
                if (ch == '"') {
                  return switchState(source, setState, stringLiteral);
                }
            
                if (largeRE.test(ch)) {
                  source.eatWhile(idRE);
                  if (source.eat('.')) {
                    return "qualifier";
                  }
                  return "variable-2";
                }
            
                if (smallRE.test(ch)) {
                  source.eatWhile(idRE);
                  return "variable";
                }
            
                if (digitRE.test(ch)) {
                  if (ch == '0') {
                    if (source.eat(/[xX]/)) {
                      source.eatWhile(hexitRE); // should require at least 1
                      return "integer";
                    }
                    if (source.eat(/[oO]/)) {
                      source.eatWhile(octitRE); // should require at least 1
                      return "number";
                    }
                  }
                  source.eatWhile(digitRE);
                  var t = "number";
                  if (source.match(/^\.\d+/)) {
                    t = "number";
                  }
                  if (source.eat(/[eE]/)) {
                    t = "number";
                    source.eat(/[-+]/);
                    source.eatWhile(digitRE); // should require at least 1
                  }
                  return t;
                }
            
                if (ch == "." && source.eat("."))
                  return "keyword";
            
                if (symbolRE.test(ch)) {
                  if (ch == '-' && source.eat(/-/)) {
                    source.eatWhile(/-/);
                    if (!source.eat(symbolRE)) {
                      source.skipToEnd();
                      return "comment";
                    }
                  }
                  var t = "variable";
                  if (ch == ':') {
                    t = "variable-2";
                  }
                  source.eatWhile(symbolRE);
                  return t;
                }
            
                return "error";
              }
            
              function ncomment(type, nest) {
                if (nest == 0) {
                  return normal;
                }
                return function(source, setState) {
                  var currNest = nest;
                  while (!source.eol()) {
                    var ch = source.next();
                    if (ch == '{' && source.eat('-')) {
                      ++currNest;
                    }
                    else if (ch == '-' && source.eat('}')) {
                      --currNest;
                      if (currNest == 0) {
                        setState(normal);
                        return type;
                      }
                    }
                  }
                  setState(ncomment(type, currNest));
                  return type;
                };
              }
            
              function stringLiteral(source, setState) {
                while (!source.eol()) {
                  var ch = source.next();
                  if (ch == '"') {
                    setState(normal);
                    return "string";
                  }
                  if (ch == '\\') {
                    if (source.eol() || source.eat(whiteCharRE)) {
                      setState(stringGap);
                      return "string";
                    }
                    if (source.eat('&')) {
                    }
                    else {
                      source.next(); // should handle other escapes here
                    }
                  }
                }
                setState(normal);
                return "error";
              }
            
              function stringGap(source, setState) {
                if (source.eat('\\')) {
                  return switchState(source, setState, stringLiteral);
                }
                source.next();
                setState(normal);
                return "error";
              }
            
            
              var wellKnownWords = (function() {
                var wkw = {};
                function setType(t) {
                  return function () {
                    for (var i = 0; i < arguments.length; i++)
                      wkw[arguments[i]] = t;
                  };
                }
            
                setType("keyword")(
                  "case", "class", "data", "default", "deriving", "do", "else", "foreign",
                  "if", "import", "in", "infix", "infixl", "infixr", "instance", "let",
                  "module", "newtype", "of", "then", "type", "where", "_");
            
                setType("keyword")(
                  "\.\.", ":", "::", "=", "\\", "\"", "<-", "->", "@", "~", "=>");
            
                setType("builtin")(
                  "!!", "$!", "$", "&&", "+", "++", "-", ".", "/", "/=", "<", "<=", "=<<",
                  "==", ">", ">=", ">>", ">>=", "^", "^^", "||", "*", "**");
            
                setType("builtin")(
                  "Bool", "Bounded", "Char", "Double", "EQ", "Either", "Enum", "Eq",
                  "False", "FilePath", "Float", "Floating", "Fractional", "Functor", "GT",
                  "IO", "IOError", "Int", "Integer", "Integral", "Just", "LT", "Left",
                  "Maybe", "Monad", "Nothing", "Num", "Ord", "Ordering", "Rational", "Read",
                  "ReadS", "Real", "RealFloat", "RealFrac", "Right", "Show", "ShowS",
                  "String", "True");
            
                setType("builtin")(
                  "abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf",
                  "asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling",
                  "compare", "concat", "concatMap", "const", "cos", "cosh", "curry",
                  "cycle", "decodeFloat", "div", "divMod", "drop", "dropWhile", "either",
                  "elem", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo",
                  "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter",
                  "flip", "floatDigits", "floatRadix", "floatRange", "floor", "fmap",
                  "foldl", "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger",
                  "fromIntegral", "fromRational", "fst", "gcd", "getChar", "getContents",
                  "getLine", "head", "id", "init", "interact", "ioError", "isDenormalized",
                  "isIEEE", "isInfinite", "isNaN", "isNegativeZero", "iterate", "last",
                  "lcm", "length", "lex", "lines", "log", "logBase", "lookup", "map",
                  "mapM", "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound",
                  "minimum", "mod", "negate", "not", "notElem", "null", "odd", "or",
                  "otherwise", "pi", "pred", "print", "product", "properFraction",
                  "putChar", "putStr", "putStrLn", "quot", "quotRem", "read", "readFile",
                  "readIO", "readList", "readLn", "readParen", "reads", "readsPrec",
                  "realToFrac", "recip", "rem", "repeat", "replicate", "return", "reverse",
                  "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq",
                  "sequence", "sequence_", "show", "showChar", "showList", "showParen",
                  "showString", "shows", "showsPrec", "significand", "signum", "sin",
                  "sinh", "snd", "span", "splitAt", "sqrt", "subtract", "succ", "sum",
                  "tail", "take", "takeWhile", "tan", "tanh", "toEnum", "toInteger",
                  "toRational", "truncate", "uncurry", "undefined", "unlines", "until",
                  "unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip",
                  "zip3", "zipWith", "zipWith3");
            
                var override = modeConfig.overrideKeywords;
                if (override) for (var word in override) if (override.hasOwnProperty(word))
                  wkw[word] = override[word];
            
                return wkw;
              })();
            
            
            
              return {
                startState: function ()  { return { f: normal }; },
                copyState:  function (s) { return { f: s.f }; },
            
                token: function(stream, state) {
                  var t = state.f(stream, function(s) { state.f = s; });
                  var w = stream.current();
                  return wellKnownWords.hasOwnProperty(w) ? wellKnownWords[w] : t;
                },
            
                blockCommentStart: "{-",
                blockCommentEnd: "-}",
                lineComment: "--"
              };
            
            });
            
            CodeMirror.defineMIME("text/x-haskell", "haskell");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Haskell mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/elegant.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="haskell.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Haskell</a>
              </ul>
            </div>
            
            <article>
            <h2>Haskell mode</h2>
            <form><textarea id="code" name="code">
            module UniquePerms (
                uniquePerms
                )
            where
            
            -- | Find all unique permutations of a list where there might be duplicates.
            uniquePerms :: (Eq a) => [a] -> [[a]]
            uniquePerms = permBag . makeBag
            
            -- | An unordered collection where duplicate values are allowed,
            -- but represented with a single value and a count.
            type Bag a = [(a, Int)]
            
            makeBag :: (Eq a) => [a] -> Bag a
            makeBag [] = []
            makeBag (a:as) = mix a $ makeBag as
              where
                mix a []                        = [(a,1)]
                mix a (bn@(b,n):bs) | a == b    = (b,n+1):bs
                                    | otherwise = bn : mix a bs
            
            permBag :: Bag a -> [[a]]
            permBag [] = [[]]
            permBag bs = concatMap (\(f,cs) -> map (f:) $ permBag cs) . oneOfEach $ bs
              where
                oneOfEach [] = []
                oneOfEach (an@(a,n):bs) =
                    let bs' = if n == 1 then bs else (a,n-1):bs
                    in (a,bs') : mapSnd (an:) (oneOfEach bs)
                
                apSnd f (a,b) = (a, f b)
                mapSnd = map . apSnd
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    theme: "elegant"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-haskell</code>.</p>
              </article>
            
        • haxe
          • haxe.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("haxe", function(config, parserConfig) {
              var indentUnit = config.indentUnit;
            
              // Tokenizer
            
              var keywords = function(){
                function kw(type) {return {type: type, style: "keyword"};}
                var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
                var operator = kw("operator"), atom = {type: "atom", style: "atom"}, attribute = {type:"attribute", style: "attribute"};
              var type = kw("typedef");
                return {
                  "if": A, "while": A, "else": B, "do": B, "try": B,
                  "return": C, "break": C, "continue": C, "new": C, "throw": C,
                  "var": kw("var"), "inline":attribute, "static": attribute, "using":kw("import"),
                "public": attribute, "private": attribute, "cast": kw("cast"), "import": kw("import"), "macro": kw("macro"),
                  "function": kw("function"), "catch": kw("catch"), "untyped": kw("untyped"), "callback": kw("cb"),
                  "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
                  "in": operator, "never": kw("property_access"), "trace":kw("trace"),
                "class": type, "abstract":type, "enum":type, "interface":type, "typedef":type, "extends":type, "implements":type, "dynamic":type,
                  "true": atom, "false": atom, "null": atom
                };
              }();
            
              var isOperatorChar = /[+\-*&%=<>!?|]/;
            
              function chain(stream, state, f) {
                state.tokenize = f;
                return f(stream, state);
              }
            
              function nextUntilUnescaped(stream, end) {
                var escaped = false, next;
                while ((next = stream.next()) != null) {
                  if (next == end && !escaped)
                    return false;
                  escaped = !escaped && next == "\\";
                }
                return escaped;
              }
            
              // Used as scratch variables to communicate multiple values without
              // consing up tons of objects.
              var type, content;
              function ret(tp, style, cont) {
                type = tp; content = cont;
                return style;
              }
            
              function haxeTokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"' || ch == "'")
                  return chain(stream, state, haxeTokenString(ch));
                else if (/[\[\]{}\(\),;\:\.]/.test(ch))
                  return ret(ch);
                else if (ch == "0" && stream.eat(/x/i)) {
                  stream.eatWhile(/[\da-f]/i);
                  return ret("number", "number");
                }
                else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
                  stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
                  return ret("number", "number");
                }
                else if (state.reAllowed && (ch == "~" && stream.eat(/\//))) {
                  nextUntilUnescaped(stream, "/");
                  stream.eatWhile(/[gimsu]/);
                  return ret("regexp", "string-2");
                }
                else if (ch == "/") {
                  if (stream.eat("*")) {
                    return chain(stream, state, haxeTokenComment);
                  }
                  else if (stream.eat("/")) {
                    stream.skipToEnd();
                    return ret("comment", "comment");
                  }
                  else {
                    stream.eatWhile(isOperatorChar);
                    return ret("operator", null, stream.current());
                  }
                }
                else if (ch == "#") {
                    stream.skipToEnd();
                    return ret("conditional", "meta");
                }
                else if (ch == "@") {
                  stream.eat(/:/);
                  stream.eatWhile(/[\w_]/);
                  return ret ("metadata", "meta");
                }
                else if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return ret("operator", null, stream.current());
                }
                else {
                var word;
                if(/[A-Z]/.test(ch))
                {
                  stream.eatWhile(/[\w_<>]/);
                  word = stream.current();
                  return ret("type", "variable-3", word);
                }
                else
                {
                    stream.eatWhile(/[\w_]/);
                    var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
                    return (known && state.kwAllowed) ? ret(known.type, known.style, word) :
                                   ret("variable", "variable", word);
                }
                }
              }
            
              function haxeTokenString(quote) {
                return function(stream, state) {
                  if (!nextUntilUnescaped(stream, quote))
                    state.tokenize = haxeTokenBase;
                  return ret("string", "string");
                };
              }
            
              function haxeTokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = haxeTokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return ret("comment", "comment");
              }
            
              // Parser
            
              var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};
            
              function HaxeLexical(indented, column, type, align, prev, info) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.prev = prev;
                this.info = info;
                if (align != null) this.align = align;
              }
            
              function inScope(state, varname) {
                for (var v = state.localVars; v; v = v.next)
                  if (v.name == varname) return true;
              }
            
              function parseHaxe(state, style, type, content, stream) {
                var cc = state.cc;
                // Communicate our context to the combinators.
                // (Less wasteful than consing up a hundred closures on every call.)
                cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
            
                if (!state.lexical.hasOwnProperty("align"))
                  state.lexical.align = true;
            
                while(true) {
                  var combinator = cc.length ? cc.pop() : statement;
                  if (combinator(type, content)) {
                    while(cc.length && cc[cc.length - 1].lex)
                      cc.pop()();
                    if (cx.marked) return cx.marked;
                    if (type == "variable" && inScope(state, content)) return "variable-2";
                if (type == "variable" && imported(state, content)) return "variable-3";
                    return style;
                  }
                }
              }
            
              function imported(state, typename)
              {
              if (/[a-z]/.test(typename.charAt(0)))
                return false;
              var len = state.importedtypes.length;
              for (var i = 0; i<len; i++)
                if(state.importedtypes[i]==typename) return true;
              }
            
            
              function registerimport(importname) {
              var state = cx.state;
              for (var t = state.importedtypes; t; t = t.next)
                if(t.name == importname) return;
              state.importedtypes = { name: importname, next: state.importedtypes };
              }
              // Combinator utils
            
              var cx = {state: null, column: null, marked: null, cc: null};
              function pass() {
                for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
              }
              function cont() {
                pass.apply(null, arguments);
                return true;
              }
              function register(varname) {
                var state = cx.state;
                if (state.context) {
                  cx.marked = "def";
                  for (var v = state.localVars; v; v = v.next)
                    if (v.name == varname) return;
                  state.localVars = {name: varname, next: state.localVars};
                }
              }
            
              // Combinators
            
              var defaultVars = {name: "this", next: null};
              function pushcontext() {
                if (!cx.state.context) cx.state.localVars = defaultVars;
                cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
              }
              function popcontext() {
                cx.state.localVars = cx.state.context.vars;
                cx.state.context = cx.state.context.prev;
              }
              function pushlex(type, info) {
                var result = function() {
                  var state = cx.state;
                  state.lexical = new HaxeLexical(state.indented, cx.stream.column(), type, null, state.lexical, info);
                };
                result.lex = true;
                return result;
              }
              function poplex() {
                var state = cx.state;
                if (state.lexical.prev) {
                  if (state.lexical.type == ")")
                    state.indented = state.lexical.indented;
                  state.lexical = state.lexical.prev;
                }
              }
              poplex.lex = true;
            
              function expect(wanted) {
                function f(type) {
                  if (type == wanted) return cont();
                  else if (wanted == ";") return pass();
                  else return cont(f);
                };
                return f;
              }
            
              function statement(type) {
                if (type == "@") return cont(metadef);
                if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
                if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
                if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
                if (type == "{") return cont(pushlex("}"), pushcontext, block, poplex, popcontext);
                if (type == ";") return cont();
                if (type == "attribute") return cont(maybeattribute);
                if (type == "function") return cont(functiondef);
                if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
                                                  poplex, statement, poplex);
                if (type == "variable") return cont(pushlex("stat"), maybelabel);
                if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
                                                     block, poplex, poplex);
                if (type == "case") return cont(expression, expect(":"));
                if (type == "default") return cont(expect(":"));
                if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
                                                    statement, poplex, popcontext);
                if (type == "import") return cont(importdef, expect(";"));
                if (type == "typedef") return cont(typedef);
                return pass(pushlex("stat"), expression, expect(";"), poplex);
              }
              function expression(type) {
                if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
                if (type == "function") return cont(functiondef);
                if (type == "keyword c") return cont(maybeexpression);
                if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator);
                if (type == "operator") return cont(expression);
                if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
                if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
                return cont();
              }
              function maybeexpression(type) {
                if (type.match(/[;\}\)\],]/)) return pass();
                return pass(expression);
              }
            
              function maybeoperator(type, value) {
                if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
                if (type == "operator" || type == ":") return cont(expression);
                if (type == ";") return;
                if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
                if (type == ".") return cont(property, maybeoperator);
                if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
              }
            
              function maybeattribute(type) {
                if (type == "attribute") return cont(maybeattribute);
                if (type == "function") return cont(functiondef);
                if (type == "var") return cont(vardef1);
              }
            
              function metadef(type) {
                if(type == ":") return cont(metadef);
                if(type == "variable") return cont(metadef);
                if(type == "(") return cont(pushlex(")"), commasep(metaargs, ")"), poplex, statement);
              }
              function metaargs(type) {
                if(type == "variable") return cont();
              }
            
              function importdef (type, value) {
              if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
              else if(type == "variable" || type == "property" || type == "." || value == "*") return cont(importdef);
              }
            
              function typedef (type, value)
              {
              if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
              else if (type == "type" && /[A-Z]/.test(value.charAt(0))) { return cont(); }
              }
            
              function maybelabel(type) {
                if (type == ":") return cont(poplex, statement);
                return pass(maybeoperator, expect(";"), poplex);
              }
              function property(type) {
                if (type == "variable") {cx.marked = "property"; return cont();}
              }
              function objprop(type) {
                if (type == "variable") cx.marked = "property";
                if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression);
              }
              function commasep(what, end) {
                function proceed(type) {
                  if (type == ",") return cont(what, proceed);
                  if (type == end) return cont();
                  return cont(expect(end));
                }
                return function(type) {
                  if (type == end) return cont();
                  else return pass(what, proceed);
                };
              }
              function block(type) {
                if (type == "}") return cont();
                return pass(statement, block);
              }
              function vardef1(type, value) {
                if (type == "variable"){register(value); return cont(typeuse, vardef2);}
                return cont();
              }
              function vardef2(type, value) {
                if (value == "=") return cont(expression, vardef2);
                if (type == ",") return cont(vardef1);
              }
              function forspec1(type, value) {
              if (type == "variable") {
                register(value);
              }
              return cont(pushlex(")"), pushcontext, forin, expression, poplex, statement, popcontext);
              }
              function forin(_type, value) {
                if (value == "in") return cont();
              }
              function functiondef(type, value) {
                if (type == "variable") {register(value); return cont(functiondef);}
                if (value == "new") return cont(functiondef);
                if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, typeuse, statement, popcontext);
              }
              function typeuse(type) {
                if(type == ":") return cont(typestring);
              }
              function typestring(type) {
                if(type == "type") return cont();
                if(type == "variable") return cont();
                if(type == "{") return cont(pushlex("}"), commasep(typeprop, "}"), poplex);
              }
              function typeprop(type) {
                if(type == "variable") return cont(typeuse);
              }
              function funarg(type, value) {
                if (type == "variable") {register(value); return cont(typeuse);}
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                var defaulttypes = ["Int", "Float", "String", "Void", "Std", "Bool", "Dynamic", "Array"];
                  return {
                    tokenize: haxeTokenBase,
                    reAllowed: true,
                    kwAllowed: true,
                    cc: [],
                    lexical: new HaxeLexical((basecolumn || 0) - indentUnit, 0, "block", false),
                    localVars: parserConfig.localVars,
                importedtypes: defaulttypes,
                    context: parserConfig.localVars && {vars: parserConfig.localVars},
                    indented: 0
                  };
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (!state.lexical.hasOwnProperty("align"))
                      state.lexical.align = false;
                    state.indented = stream.indentation();
                  }
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
                  if (type == "comment") return style;
                  state.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/));
                  state.kwAllowed = type != '.';
                  return parseHaxe(state, style, type, content, stream);
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != haxeTokenBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
                  if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
                  var type = lexical.type, closing = firstChar == type;
                  if (type == "vardef") return lexical.indented + 4;
                  else if (type == "form" && firstChar == "{") return lexical.indented;
                  else if (type == "stat" || type == "form") return lexical.indented + indentUnit;
                  else if (lexical.info == "switch" && !closing)
                    return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
                  else if (lexical.align) return lexical.column + (closing ? 0 : 1);
                  else return lexical.indented + (closing ? 0 : indentUnit);
                },
            
                electricChars: "{}",
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                lineComment: "//"
              };
            });
            
            CodeMirror.defineMIME("text/x-haxe", "haxe");
            
            CodeMirror.defineMode("hxml", function () {
            
              return {
                startState: function () {
                  return {
                    define: false,
                    inString: false
                  };
                },
                token: function (stream, state) {
                  var ch = stream.peek();
                  var sol = stream.sol();
            
                  ///* comments */
                  if (ch == "#") {
                    stream.skipToEnd();
                    return "comment";
                  }
                  if (sol && ch == "-") {
                    var style = "variable-2";
            
                    stream.eat(/-/);
            
                    if (stream.peek() == "-") {
                      stream.eat(/-/);
                      style = "keyword a";
                    }
            
                    if (stream.peek() == "D") {
                      stream.eat(/[D]/);
                      style = "keyword c";
                      state.define = true;
                    }
            
                    stream.eatWhile(/[A-Z]/i);
                    return style;
                  }
            
                  var ch = stream.peek();
            
                  if (state.inString == false && ch == "'") {
                    state.inString = true;
                    ch = stream.next();
                  }
            
                  if (state.inString == true) {
                    if (stream.skipTo("'")) {
            
                    } else {
                      stream.skipToEnd();
                    }
            
                    if (stream.peek() == "'") {
                      stream.next();
                      state.inString = false;
                    }
            
                    return "string";
                  }
            
                  stream.next();
                  return null;
                },
                lineComment: "#"
              };
            });
            
            CodeMirror.defineMIME("text/x-hxml", "hxml");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Haxe mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="haxe.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Haxe</a>
              </ul>
            </div>
            
            <article>
            <h2>Haxe mode</h2>
            
            
            <div><p><textarea id="code-haxe" name="code">
            import one.two.Three;
            
            @attr("test")
            class Foo&lt;T&gt; extends Three
            {
            	public function new()
            	{
            		noFoo = 12;
            	}
            	
            	public static inline function doFoo(obj:{k:Int, l:Float}):Int
            	{
            		for(i in 0...10)
            		{
            			obj.k++;
            			trace(i);
            			var var1 = new Array();
            			if(var1.length > 1)
            				throw "Error";
            		}
            		// The following line should not be colored, the variable is scoped out
            		var1;
            		/* Multi line
            		 * Comment test
            		 */
            		return obj.k;
            	}
            	private function bar():Void
            	{
            		#if flash
            		var t1:String = "1.21";
            		#end
            		try {
            			doFoo({k:3, l:1.2});
            		}
            		catch (e : String) {
            			trace(e);
            		}
            		var t2:Float = cast(3.2);
            		var t3:haxe.Timer = new haxe.Timer();
            		var t4 = {k:Std.int(t2), l:Std.parseFloat(t1)};
            		var t5 = ~/123+.*$/i;
            		doFoo(t4);
            		untyped t1 = 4;
            		bob = new Foo&lt;Int&gt;
            	}
            	public var okFoo(default, never):Float;
            	var noFoo(getFoo, null):Int;
            	function getFoo():Int {
            		return noFoo;
            	}
            	
            	public var three:Int;
            }
            enum Color
            {
            	red;
            	green;
            	blue;
            	grey( v : Int );
            	rgb (r:Int,g:Int,b:Int);
            }
            </textarea></p>
            
            <p>Hxml mode:</p>
            
            <p><textarea id="code-hxml">
            -cp test
            -js path/to/file.js
            #-remap nme:flash
            --next
            -D source-map-content
            -cmd 'test'
            -lib lime
            </textarea></p>
            </div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code-haxe"), {
                  	mode: "haxe",
                    lineNumbers: true,
                    indentUnit: 4,
                    indentWithTabs: true
                  });
                  
                  editor = CodeMirror.fromTextArea(document.getElementById("code-hxml"), {
                  	mode: "hxml",
                    lineNumbers: true,
                    indentUnit: 4,
                    indentWithTabs: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-haxe, text/x-hxml</code>.</p>
              </article>
            
        • htmlembedded
          • htmlembedded.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"),
                    require("../../addon/mode/multiplex"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed",
                        "../../addon/mode/multiplex"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {
                return CodeMirror.multiplexingMode(CodeMirror.getMode(config, "htmlmixed"), {
                  open: parserConfig.open || parserConfig.scriptStartRegex || "<%",
                  close: parserConfig.close || parserConfig.scriptEndRegex || "%>",
                  mode: CodeMirror.getMode(config, parserConfig.scriptingModeSpec)
                });
              }, "htmlmixed");
            
              CodeMirror.defineMIME("application/x-ejs", {name: "htmlembedded", scriptingModeSpec:"javascript"});
              CodeMirror.defineMIME("application/x-aspx", {name: "htmlembedded", scriptingModeSpec:"text/x-csharp"});
              CodeMirror.defineMIME("application/x-jsp", {name: "htmlembedded", scriptingModeSpec:"text/x-java"});
              CodeMirror.defineMIME("application/x-erb", {name: "htmlembedded", scriptingModeSpec:"ruby"});
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Html Embedded Scripts mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../css/css.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="../../addon/mode/multiplex.js"></script>
            <script src="htmlembedded.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Html Embedded Scripts</a>
              </ul>
            </div>
            
            <article>
            <h2>Html Embedded Scripts mode</h2>
            <form><textarea id="code" name="code">
            <%
            function hello(who) {
            	return "Hello " + who;
            }
            %>
            This is an example of EJS (embedded javascript)
            <p>The program says <%= hello("world") %>.</p>
            <script>
            	alert("And here is some normal JS code"); // also colored
            </script>
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "application/x-ejs",
                    indentUnit: 4,
                    indentWithTabs: true
                  });
                </script>
            
                <p>Mode for html embedded scripts like JSP and ASP.NET. Depends on HtmlMixed which in turn depends on
                JavaScript, CSS and XML.<br />Other dependancies include those of the scriping language chosen.</p>
            
                <p><strong>MIME types defined:</strong> <code>application/x-aspx</code> (ASP.NET), 
                <code>application/x-ejs</code> (Embedded Javascript), <code>application/x-jsp</code> (JavaServer Pages)</p>
              </article>
            
        • htmlmixed
          • htmlmixed.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
              var htmlMode = CodeMirror.getMode(config, {name: "xml",
                                                         htmlMode: true,
                                                         multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
                                                         multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag});
              var cssMode = CodeMirror.getMode(config, "css");
            
              var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;
              scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,
                                mode: CodeMirror.getMode(config, "javascript")});
              if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {
                var conf = scriptTypesConf[i];
                scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});
              }
              scriptTypes.push({matches: /./,
                                mode: CodeMirror.getMode(config, "text/plain")});
            
              function html(stream, state) {
                var tagName = state.htmlState.tagName;
                if (tagName) tagName = tagName.toLowerCase();
                var style = htmlMode.token(stream, state.htmlState);
                if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
                  // Script block: mode to change to depends on type attribute
                  var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);
                  scriptType = scriptType ? scriptType[1] : "";
                  if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);
                  for (var i = 0; i < scriptTypes.length; ++i) {
                    var tp = scriptTypes[i];
                    if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) {
                      if (tp.mode) {
                        state.token = script;
                        state.localMode = tp.mode;
                        state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, ""));
                      }
                      break;
                    }
                  }
                } else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") {
                  state.token = css;
                  state.localMode = cssMode;
                  state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
                }
                return style;
              }
              function maybeBackup(stream, pat, style) {
                var cur = stream.current();
                var close = cur.search(pat);
                if (close > -1) stream.backUp(cur.length - close);
                else if (cur.match(/<\/?$/)) {
                  stream.backUp(cur.length);
                  if (!stream.match(pat, false)) stream.match(cur);
                }
                return style;
              }
              function script(stream, state) {
                if (stream.match(/^<\/\s*script\s*>/i, false)) {
                  state.token = html;
                  state.localState = state.localMode = null;
                  return null;
                }
                return maybeBackup(stream, /<\/\s*script\s*>/,
                                   state.localMode.token(stream, state.localState));
              }
              function css(stream, state) {
                if (stream.match(/^<\/\s*style\s*>/i, false)) {
                  state.token = html;
                  state.localState = state.localMode = null;
                  return null;
                }
                return maybeBackup(stream, /<\/\s*style\s*>/,
                                   cssMode.token(stream, state.localState));
              }
            
              return {
                startState: function() {
                  var state = htmlMode.startState();
                  return {token: html, localMode: null, localState: null, htmlState: state};
                },
            
                copyState: function(state) {
                  if (state.localState)
                    var local = CodeMirror.copyState(state.localMode, state.localState);
                  return {token: state.token, localMode: state.localMode, localState: local,
                          htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
                },
            
                token: function(stream, state) {
                  return state.token(stream, state);
                },
            
                indent: function(state, textAfter) {
                  if (!state.localMode || /^\s*<\//.test(textAfter))
                    return htmlMode.indent(state.htmlState, textAfter);
                  else if (state.localMode.indent)
                    return state.localMode.indent(state.localState, textAfter);
                  else
                    return CodeMirror.Pass;
                },
            
                innerMode: function(state) {
                  return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
                }
              };
            }, "xml", "javascript", "css");
            
            CodeMirror.defineMIME("text/html", "htmlmixed");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: HTML mixed mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/selection/selection-pointer.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../css/css.js"></script>
            <script src="../vbscript/vbscript.js"></script>
            <script src="htmlmixed.js"></script>
            <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">HTML mixed</a>
              </ul>
            </div>
            
            <article>
            <h2>HTML mixed mode</h2>
            <form><textarea id="code" name="code">
            <html style="color: green">
              <!-- this is a comment -->
              <head>
                <title>Mixed HTML Example</title>
                <style type="text/css">
                  h1 {font-family: comic sans; color: #f0f;}
                  div {background: yellow !important;}
                  body {
                    max-width: 50em;
                    margin: 1em 2em 1em 5em;
                  }
                </style>
              </head>
              <body>
                <h1>Mixed HTML Example</h1>
                <script>
                  function jsFunc(arg1, arg2) {
                    if (arg1 && arg2) document.body.innerHTML = "achoo";
                  }
                </script>
              </body>
            </html>
            </textarea></form>
                <script>
                  // Define an extended mixed-mode that understands vbscript and
                  // leaves mustache/handlebars embedded templates in html mode
                  var mixedMode = {
                    name: "htmlmixed",
                    scriptTypes: [{matches: /\/x-handlebars-template|\/x-mustache/i,
                                   mode: null},
                                  {matches: /(text|application)\/(x-)?vb(a|script)/i,
                                   mode: "vbscript"}]
                  };
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: mixedMode,
                    selectionPointer: true
                  });
                </script>
            
                <p>The HTML mixed mode depends on the XML, JavaScript, and CSS modes.</p>
            
                <p>It takes an optional mode configuration
                option, <code>scriptTypes</code>, which can be used to add custom
                behavior for specific <code>&lt;script type="..."></code> tags. If
                given, it should hold an array of <code>{matches, mode}</code>
                objects, where <code>matches</code> is a string or regexp that
                matches the script type, and <code>mode</code> is
                either <code>null</code>, for script types that should stay in
                HTML mode, or a <a href="../../doc/manual.html#option_mode">mode
                spec</a> corresponding to the mode that should be used for the
                script.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/html</code>
                (redefined, only takes effect if you load this parser after the
                XML parser).</p>
            
              </article>
            
        • http
          • http.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("http", function() {
              function failFirstLine(stream, state) {
                stream.skipToEnd();
                state.cur = header;
                return "error";
              }
            
              function start(stream, state) {
                if (stream.match(/^HTTP\/\d\.\d/)) {
                  state.cur = responseStatusCode;
                  return "keyword";
                } else if (stream.match(/^[A-Z]+/) && /[ \t]/.test(stream.peek())) {
                  state.cur = requestPath;
                  return "keyword";
                } else {
                  return failFirstLine(stream, state);
                }
              }
            
              function responseStatusCode(stream, state) {
                var code = stream.match(/^\d+/);
                if (!code) return failFirstLine(stream, state);
            
                state.cur = responseStatusText;
                var status = Number(code[0]);
                if (status >= 100 && status < 200) {
                  return "positive informational";
                } else if (status >= 200 && status < 300) {
                  return "positive success";
                } else if (status >= 300 && status < 400) {
                  return "positive redirect";
                } else if (status >= 400 && status < 500) {
                  return "negative client-error";
                } else if (status >= 500 && status < 600) {
                  return "negative server-error";
                } else {
                  return "error";
                }
              }
            
              function responseStatusText(stream, state) {
                stream.skipToEnd();
                state.cur = header;
                return null;
              }
            
              function requestPath(stream, state) {
                stream.eatWhile(/\S/);
                state.cur = requestProtocol;
                return "string-2";
              }
            
              function requestProtocol(stream, state) {
                if (stream.match(/^HTTP\/\d\.\d$/)) {
                  state.cur = header;
                  return "keyword";
                } else {
                  return failFirstLine(stream, state);
                }
              }
            
              function header(stream) {
                if (stream.sol() && !stream.eat(/[ \t]/)) {
                  if (stream.match(/^.*?:/)) {
                    return "atom";
                  } else {
                    stream.skipToEnd();
                    return "error";
                  }
                } else {
                  stream.skipToEnd();
                  return "string";
                }
              }
            
              function body(stream) {
                stream.skipToEnd();
                return null;
              }
            
              return {
                token: function(stream, state) {
                  var cur = state.cur;
                  if (cur != header && cur != body && stream.eatSpace()) return null;
                  return cur(stream, state);
                },
            
                blankLine: function(state) {
                  state.cur = body;
                },
            
                startState: function() {
                  return {cur: start};
                }
              };
            });
            
            CodeMirror.defineMIME("message/http", "http");
            
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: HTTP mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="http.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">HTTP</a>
              </ul>
            </div>
            
            <article>
            <h2>HTTP mode</h2>
            
            
            <div><textarea id="code" name="code">
            POST /somewhere HTTP/1.1
            Host: example.com
            If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
            Content-Type: application/x-www-form-urlencoded;
            	charset=utf-8
            User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.11 (KHTML, like Gecko) Ubuntu/12.04 Chromium/20.0.1132.47 Chrome/20.0.1132.47 Safari/536.11
            
            This is the request body!
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>message/http</code>.</p>
              </article>
            
        • idl
          • idl.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              function wordRegexp(words) {
                return new RegExp('^((' + words.join(')|(') + '))\\b', 'i');
              };
            
              var builtinArray = [
                'a_correlate', 'abs', 'acos', 'adapt_hist_equal', 'alog',
                'alog2', 'alog10', 'amoeba', 'annotate', 'app_user_dir',
                'app_user_dir_query', 'arg_present', 'array_equal', 'array_indices',
                'arrow', 'ascii_template', 'asin', 'assoc', 'atan',
                'axis', 'axis', 'bandpass_filter', 'bandreject_filter', 'barplot',
                'bar_plot', 'beseli', 'beselj', 'beselk', 'besely',
                'beta', 'biginteger', 'bilinear', 'bin_date', 'binary_template',
                'bindgen', 'binomial', 'bit_ffs', 'bit_population', 'blas_axpy',
                'blk_con', 'boolarr', 'boolean', 'boxplot', 'box_cursor',
                'breakpoint', 'broyden', 'bubbleplot', 'butterworth', 'bytarr',
                'byte', 'byteorder', 'bytscl', 'c_correlate', 'calendar',
                'caldat', 'call_external', 'call_function', 'call_method',
                'call_procedure', 'canny', 'catch', 'cd', 'cdf', 'ceil',
                'chebyshev', 'check_math', 'chisqr_cvf', 'chisqr_pdf', 'choldc',
                'cholsol', 'cindgen', 'cir_3pnt', 'clipboard', 'close',
                'clust_wts', 'cluster', 'cluster_tree', 'cmyk_convert', 'code_coverage',
                'color_convert', 'color_exchange', 'color_quan', 'color_range_map',
                'colorbar', 'colorize_sample', 'colormap_applicable',
                'colormap_gradient', 'colormap_rotation', 'colortable',
                'comfit', 'command_line_args', 'common', 'compile_opt', 'complex',
                'complexarr', 'complexround', 'compute_mesh_normals', 'cond', 'congrid',
                'conj', 'constrained_min', 'contour', 'contour', 'convert_coord',
                'convol', 'convol_fft', 'coord2to3', 'copy_lun', 'correlate',
                'cos', 'cosh', 'cpu', 'cramer', 'createboxplotdata',
                'create_cursor', 'create_struct', 'create_view', 'crossp', 'crvlength',
                'ct_luminance', 'cti_test', 'cursor', 'curvefit', 'cv_coord',
                'cvttobm', 'cw_animate', 'cw_animate_getp', 'cw_animate_load',
                'cw_animate_run', 'cw_arcball', 'cw_bgroup', 'cw_clr_index',
                'cw_colorsel', 'cw_defroi', 'cw_field', 'cw_filesel', 'cw_form',
                'cw_fslider', 'cw_light_editor', 'cw_light_editor_get',
                'cw_light_editor_set', 'cw_orient', 'cw_palette_editor',
                'cw_palette_editor_get', 'cw_palette_editor_set', 'cw_pdmenu',
                'cw_rgbslider', 'cw_tmpl', 'cw_zoom', 'db_exists',
                'dblarr', 'dcindgen', 'dcomplex', 'dcomplexarr', 'define_key',
                'define_msgblk', 'define_msgblk_from_file', 'defroi', 'defsysv',
                'delvar', 'dendro_plot', 'dendrogram', 'deriv', 'derivsig',
                'determ', 'device', 'dfpmin', 'diag_matrix', 'dialog_dbconnect',
                'dialog_message', 'dialog_pickfile', 'dialog_printersetup',
                'dialog_printjob', 'dialog_read_image',
                'dialog_write_image', 'dictionary', 'digital_filter', 'dilate', 'dindgen',
                'dissolve', 'dist', 'distance_measure', 'dlm_load', 'dlm_register',
                'doc_library', 'double', 'draw_roi', 'edge_dog', 'efont',
                'eigenql', 'eigenvec', 'ellipse', 'elmhes', 'emboss',
                'empty', 'enable_sysrtn', 'eof', 'eos', 'erase',
                'erf', 'erfc', 'erfcx', 'erode', 'errorplot',
                'errplot', 'estimator_filter', 'execute', 'exit', 'exp',
                'expand', 'expand_path', 'expint', 'extrac', 'extract_slice',
                'f_cvf', 'f_pdf', 'factorial', 'fft', 'file_basename',
                'file_chmod', 'file_copy', 'file_delete', 'file_dirname',
                'file_expand_path', 'file_gunzip', 'file_gzip', 'file_info',
                'file_lines', 'file_link', 'file_mkdir', 'file_move',
                'file_poll_input', 'file_readlink', 'file_same',
                'file_search', 'file_tar', 'file_test', 'file_untar', 'file_unzip',
                'file_which', 'file_zip', 'filepath', 'findgen', 'finite',
                'fix', 'flick', 'float', 'floor', 'flow3',
                'fltarr', 'flush', 'format_axis_values', 'forward_function', 'free_lun',
                'fstat', 'fulstr', 'funct', 'function', 'fv_test',
                'fx_root', 'fz_roots', 'gamma', 'gamma_ct', 'gauss_cvf',
                'gauss_pdf', 'gauss_smooth', 'gauss2dfit', 'gaussfit',
                'gaussian_function', 'gaussint', 'get_drive_list', 'get_dxf_objects',
                'get_kbrd', 'get_login_info',
                'get_lun', 'get_screen_size', 'getenv', 'getwindows', 'greg2jul',
                'grib', 'grid_input', 'grid_tps', 'grid3', 'griddata',
                'gs_iter', 'h_eq_ct', 'h_eq_int', 'hanning', 'hash',
                'hdf', 'hdf5', 'heap_free', 'heap_gc', 'heap_nosave',
                'heap_refcount', 'heap_save', 'help', 'hilbert', 'hist_2d',
                'hist_equal', 'histogram', 'hls', 'hough', 'hqr',
                'hsv', 'i18n_multibytetoutf8',
                'i18n_multibytetowidechar', 'i18n_utf8tomultibyte',
                'i18n_widechartomultibyte',
                'ibeta', 'icontour', 'iconvertcoord', 'idelete', 'identity',
                'idl_base64', 'idl_container', 'idl_validname',
                'idlexbr_assistant', 'idlitsys_createtool',
                'idlunit', 'iellipse', 'igamma', 'igetcurrent', 'igetdata',
                'igetid', 'igetproperty', 'iimage', 'image', 'image_cont',
                'image_statistics', 'image_threshold', 'imaginary', 'imap', 'indgen',
                'int_2d', 'int_3d', 'int_tabulated', 'intarr', 'interpol',
                'interpolate', 'interval_volume', 'invert', 'ioctl', 'iopen',
                'ir_filter', 'iplot', 'ipolygon', 'ipolyline', 'iputdata',
                'iregister', 'ireset', 'iresolve', 'irotate', 'isa',
                'isave', 'iscale', 'isetcurrent', 'isetproperty', 'ishft',
                'isocontour', 'isosurface', 'isurface', 'itext', 'itranslate',
                'ivector', 'ivolume', 'izoom', 'journal', 'json_parse',
                'json_serialize', 'jul2greg', 'julday', 'keyword_set', 'krig2d',
                'kurtosis', 'kw_test', 'l64indgen', 'la_choldc', 'la_cholmprove',
                'la_cholsol', 'la_determ', 'la_eigenproblem', 'la_eigenql', 'la_eigenvec',
                'la_elmhes', 'la_gm_linear_model', 'la_hqr', 'la_invert',
                'la_least_square_equality', 'la_least_squares', 'la_linear_equation',
                'la_ludc', 'la_lumprove', 'la_lusol',
                'la_svd', 'la_tridc', 'la_trimprove', 'la_triql', 'la_trired',
                'la_trisol', 'label_date', 'label_region', 'ladfit', 'laguerre',
                'lambda', 'lambdap', 'lambertw', 'laplacian', 'least_squares_filter',
                'leefilt', 'legend', 'legendre', 'linbcg', 'lindgen',
                'linfit', 'linkimage', 'list', 'll_arc_distance', 'lmfit',
                'lmgr', 'lngamma', 'lnp_test', 'loadct', 'locale_get',
                'logical_and', 'logical_or', 'logical_true', 'lon64arr', 'lonarr',
                'long', 'long64', 'lsode', 'lu_complex', 'ludc',
                'lumprove', 'lusol', 'm_correlate', 'machar', 'make_array',
                'make_dll', 'make_rt', 'map', 'mapcontinents', 'mapgrid',
                'map_2points', 'map_continents', 'map_grid', 'map_image', 'map_patch',
                'map_proj_forward', 'map_proj_image', 'map_proj_info',
                'map_proj_init', 'map_proj_inverse',
                'map_set', 'matrix_multiply', 'matrix_power', 'max', 'md_test',
                'mean', 'meanabsdev', 'mean_filter', 'median', 'memory',
                'mesh_clip', 'mesh_decimate', 'mesh_issolid',
                'mesh_merge', 'mesh_numtriangles',
                'mesh_obj', 'mesh_smooth', 'mesh_surfacearea',
                'mesh_validate', 'mesh_volume',
                'message', 'min', 'min_curve_surf', 'mk_html_help', 'modifyct',
                'moment', 'morph_close', 'morph_distance',
                'morph_gradient', 'morph_hitormiss',
                'morph_open', 'morph_thin', 'morph_tophat', 'multi', 'n_elements',
                'n_params', 'n_tags', 'ncdf', 'newton', 'noise_hurl',
                'noise_pick', 'noise_scatter', 'noise_slur', 'norm', 'obj_class',
                'obj_destroy', 'obj_hasmethod', 'obj_isa', 'obj_new', 'obj_valid',
                'objarr', 'on_error', 'on_ioerror', 'online_help', 'openr',
                'openu', 'openw', 'oplot', 'oploterr', 'orderedhash',
                'p_correlate', 'parse_url', 'particle_trace', 'path_cache', 'path_sep',
                'pcomp', 'plot', 'plot3d', 'plot', 'plot_3dbox',
                'plot_field', 'ploterr', 'plots', 'polar_contour', 'polar_surface',
                'polyfill', 'polyshade', 'pnt_line', 'point_lun', 'polarplot',
                'poly', 'poly_2d', 'poly_area', 'poly_fit', 'polyfillv',
                'polygon', 'polyline', 'polywarp', 'popd', 'powell',
                'pref_commit', 'pref_get', 'pref_set', 'prewitt', 'primes',
                'print', 'printf', 'printd', 'pro', 'product',
                'profile', 'profiler', 'profiles', 'project_vol', 'ps_show_fonts',
                'psafm', 'pseudo', 'ptr_free', 'ptr_new', 'ptr_valid',
                'ptrarr', 'pushd', 'qgrid3', 'qhull', 'qromb',
                'qromo', 'qsimp', 'query_*', 'query_ascii', 'query_bmp',
                'query_csv', 'query_dicom', 'query_gif', 'query_image', 'query_jpeg',
                'query_jpeg2000', 'query_mrsid', 'query_pict', 'query_png', 'query_ppm',
                'query_srf', 'query_tiff', 'query_video', 'query_wav', 'r_correlate',
                'r_test', 'radon', 'randomn', 'randomu', 'ranks',
                'rdpix', 'read', 'readf', 'read_ascii', 'read_binary',
                'read_bmp', 'read_csv', 'read_dicom', 'read_gif', 'read_image',
                'read_interfile', 'read_jpeg', 'read_jpeg2000', 'read_mrsid', 'read_pict',
                'read_png', 'read_ppm', 'read_spr', 'read_srf', 'read_sylk',
                'read_tiff', 'read_video', 'read_wav', 'read_wave', 'read_x11_bitmap',
                'read_xwd', 'reads', 'readu', 'real_part', 'rebin',
                'recall_commands', 'recon3', 'reduce_colors', 'reform', 'region_grow',
                'register_cursor', 'regress', 'replicate',
                'replicate_inplace', 'resolve_all',
                'resolve_routine', 'restore', 'retall', 'return', 'reverse',
                'rk4', 'roberts', 'rot', 'rotate', 'round',
                'routine_filepath', 'routine_info', 'rs_test', 's_test', 'save',
                'savgol', 'scale3', 'scale3d', 'scatterplot', 'scatterplot3d',
                'scope_level', 'scope_traceback', 'scope_varfetch',
                'scope_varname', 'search2d',
                'search3d', 'sem_create', 'sem_delete', 'sem_lock', 'sem_release',
                'set_plot', 'set_shading', 'setenv', 'sfit', 'shade_surf',
                'shade_surf_irr', 'shade_volume', 'shift', 'shift_diff', 'shmdebug',
                'shmmap', 'shmunmap', 'shmvar', 'show3', 'showfont',
                'signum', 'simplex', 'sin', 'sindgen', 'sinh',
                'size', 'skewness', 'skip_lun', 'slicer3', 'slide_image',
                'smooth', 'sobel', 'socket', 'sort', 'spawn',
                'sph_4pnt', 'sph_scat', 'spher_harm', 'spl_init', 'spl_interp',
                'spline', 'spline_p', 'sprsab', 'sprsax', 'sprsin',
                'sprstp', 'sqrt', 'standardize', 'stddev', 'stop',
                'strarr', 'strcmp', 'strcompress', 'streamline', 'streamline',
                'stregex', 'stretch', 'string', 'strjoin', 'strlen',
                'strlowcase', 'strmatch', 'strmessage', 'strmid', 'strpos',
                'strput', 'strsplit', 'strtrim', 'struct_assign', 'struct_hide',
                'strupcase', 'surface', 'surface', 'surfr', 'svdc',
                'svdfit', 'svsol', 'swap_endian', 'swap_endian_inplace', 'symbol',
                'systime', 't_cvf', 't_pdf', 't3d', 'tag_names',
                'tan', 'tanh', 'tek_color', 'temporary', 'terminal_size',
                'tetra_clip', 'tetra_surface', 'tetra_volume', 'text', 'thin',
                'thread', 'threed', 'tic', 'time_test2', 'timegen',
                'timer', 'timestamp', 'timestamptovalues', 'tm_test', 'toc',
                'total', 'trace', 'transpose', 'tri_surf', 'triangulate',
                'trigrid', 'triql', 'trired', 'trisol', 'truncate_lun',
                'ts_coef', 'ts_diff', 'ts_fcast', 'ts_smooth', 'tv',
                'tvcrs', 'tvlct', 'tvrd', 'tvscl', 'typename',
                'uindgen', 'uint', 'uintarr', 'ul64indgen', 'ulindgen',
                'ulon64arr', 'ulonarr', 'ulong', 'ulong64', 'uniq',
                'unsharp_mask', 'usersym', 'value_locate', 'variance', 'vector',
                'vector_field', 'vel', 'velovect', 'vert_t3d', 'voigt',
                'volume', 'voronoi', 'voxel_proj', 'wait', 'warp_tri',
                'watershed', 'wdelete', 'wf_draw', 'where', 'widget_base',
                'widget_button', 'widget_combobox', 'widget_control',
                'widget_displaycontextmenu', 'widget_draw',
                'widget_droplist', 'widget_event', 'widget_info',
                'widget_label', 'widget_list',
                'widget_propertysheet', 'widget_slider', 'widget_tab',
                'widget_table', 'widget_text',
                'widget_tree', 'widget_tree_move', 'widget_window',
                'wiener_filter', 'window',
                'window', 'write_bmp', 'write_csv', 'write_gif', 'write_image',
                'write_jpeg', 'write_jpeg2000', 'write_nrif', 'write_pict', 'write_png',
                'write_ppm', 'write_spr', 'write_srf', 'write_sylk', 'write_tiff',
                'write_video', 'write_wav', 'write_wave', 'writeu', 'wset',
                'wshow', 'wtn', 'wv_applet', 'wv_cwt', 'wv_cw_wavelet',
                'wv_denoise', 'wv_dwt', 'wv_fn_coiflet',
                'wv_fn_daubechies', 'wv_fn_gaussian',
                'wv_fn_haar', 'wv_fn_morlet', 'wv_fn_paul',
                'wv_fn_symlet', 'wv_import_data',
                'wv_import_wavelet', 'wv_plot3d_wps', 'wv_plot_multires',
                'wv_pwt', 'wv_tool_denoise',
                'xbm_edit', 'xdisplayfile', 'xdxf', 'xfont', 'xinteranimate',
                'xloadct', 'xmanager', 'xmng_tmpl', 'xmtool', 'xobjview',
                'xobjview_rotate', 'xobjview_write_image',
                'xpalette', 'xpcolor', 'xplot3d',
                'xregistered', 'xroi', 'xsq_test', 'xsurface', 'xvaredit',
                'xvolume', 'xvolume_rotate', 'xvolume_write_image',
                'xyouts', 'zlib_compress', 'zlib_uncompress', 'zoom', 'zoom_24'
              ];
              var builtins = wordRegexp(builtinArray);
            
              var keywordArray = [
                'begin', 'end', 'endcase', 'endfor',
                'endwhile', 'endif', 'endrep', 'endforeach',
                'break', 'case', 'continue', 'for',
                'foreach', 'goto', 'if', 'then', 'else',
                'repeat', 'until', 'switch', 'while',
                'do', 'pro', 'function'
              ];
              var keywords = wordRegexp(keywordArray);
            
              CodeMirror.registerHelper("hintWords", "idl", builtinArray.concat(keywordArray));
            
              var identifiers = new RegExp('^[_a-z\xa1-\uffff][_a-z0-9\xa1-\uffff]*', 'i');
            
              var singleOperators = /[+\-*&=<>\/@#~$]/;
              var boolOperators = new RegExp('(and|or|eq|lt|le|gt|ge|ne|not)', 'i');
            
              function tokenBase(stream) {
                // whitespaces
                if (stream.eatSpace()) return null;
            
                // Handle one line Comments
                if (stream.match(';')) {
                  stream.skipToEnd();
                  return 'comment';
                }
            
                // Handle Number Literals
                if (stream.match(/^[0-9\.+-]/, false)) {
                  if (stream.match(/^[+-]?0x[0-9a-fA-F]+/))
                    return 'number';
                  if (stream.match(/^[+-]?\d*\.\d+([EeDd][+-]?\d+)?/))
                    return 'number';
                  if (stream.match(/^[+-]?\d+([EeDd][+-]?\d+)?/))
                    return 'number';
                }
            
                // Handle Strings
                if (stream.match(/^"([^"]|(""))*"/)) { return 'string'; }
                if (stream.match(/^'([^']|(''))*'/)) { return 'string'; }
            
                // Handle words
                if (stream.match(keywords)) { return 'keyword'; }
                if (stream.match(builtins)) { return 'builtin'; }
                if (stream.match(identifiers)) { return 'variable'; }
            
                if (stream.match(singleOperators) || stream.match(boolOperators)) {
                  return 'operator'; }
            
                // Handle non-detected items
                stream.next();
                return null;
              };
            
              CodeMirror.defineMode('idl', function() {
                return {
                  token: function(stream) {
                    return tokenBase(stream);
                  }
                };
              });
            
              CodeMirror.defineMIME('text/x-idl', 'idl');
            });
            
          • index.html
            <!doctype html>
            
            <title>CodeMirror: IDL mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="idl.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">IDL</a>
              </ul>
            </div>
            
            <article>
            <h2>IDL mode</h2>
            
                <div><textarea id="code" name="code">
            ;; Example IDL code
            FUNCTION mean_and_stddev,array
              ;; This program reads in an array of numbers
              ;; and returns a structure containing the
              ;; average and standard deviation
            
              ave = 0.0
              count = 0.0
            
              for i=0,N_ELEMENTS(array)-1 do begin
                  ave = ave + array[i]
                  count = count + 1
              endfor
              
              ave = ave/count
            
              std = stddev(array)  
            
              return, {average:ave,std:std}
            
            END
            
                </textarea></div>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "idl",
                           version: 1,
                           singleLineStringErrors: false},
                    lineNumbers: true,
                    indentUnit: 4,
                    matchBrackets: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-idl</code>.</p>
            </article>
            
        • jade
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Jade Templating Mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../css/css.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="jade.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Jade Templating Mode</a>
              </ul>
            </div>
            
            <article>
            <h2>Jade Templating Mode</h2>
            <form><textarea id="code" name="code">
            doctype html
              html
                head
                  title= "Jade Templating CodeMirror Mode Example"
                  link(rel='stylesheet', href='/css/bootstrap.min.css')
                  link(rel='stylesheet', href='/css/index.css')
                  script(type='text/javascript', src='/js/jquery-1.9.1.min.js')
                  script(type='text/javascript', src='/js/bootstrap.min.js')
                body
                  div.header
                    h1 Welcome to this Example
                  div.spots
                    if locals.spots
                      each spot in spots
                        div.spot.well
                     div
                       if spot.logo
                         img.img-rounded.logo(src=spot.logo)
                       else
                         img.img-rounded.logo(src="img/placeholder.png")
                     h3
                       a(href=spot.hash) ##{spot.hash}
                       if spot.title
                         span.title #{spot.title}
                       if spot.desc
                         div #{spot.desc}
                    else
                      h3 There are no spots currently available.
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "jade", alignCDATA: true},
                    lineNumbers: true
                  });
                </script>
                <h3>The Jade Templating Mode</h3>
                  <p> Created by Forbes Lindesay. Managed as part of a Brackets extension at <a href="https://github.com/ForbesLindesay/jade-brackets">https://github.com/ForbesLindesay/jade-brackets</a>.</p>
                <p><strong>MIME type defined:</strong> <code>text/x-jade</code>.</p>
              </article>
            
          • jade.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../javascript/javascript"), require("../css/css"), require("../htmlmixed/htmlmixed"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../javascript/javascript", "../css/css", "../htmlmixed/htmlmixed"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('jade', function (config) {
              // token types
              var KEYWORD = 'keyword';
              var DOCTYPE = 'meta';
              var ID = 'builtin';
              var CLASS = 'qualifier';
            
              var ATTRS_NEST = {
                '{': '}',
                '(': ')',
                '[': ']'
              };
            
              var jsMode = CodeMirror.getMode(config, 'javascript');
            
              function State() {
                this.javaScriptLine = false;
                this.javaScriptLineExcludesColon = false;
            
                this.javaScriptArguments = false;
                this.javaScriptArgumentsDepth = 0;
            
                this.isInterpolating = false;
                this.interpolationNesting = 0;
            
                this.jsState = jsMode.startState();
            
                this.restOfLine = '';
            
                this.isIncludeFiltered = false;
                this.isEach = false;
            
                this.lastTag = '';
                this.scriptType = '';
            
                // Attributes Mode
                this.isAttrs = false;
                this.attrsNest = [];
                this.inAttributeName = true;
                this.attributeIsType = false;
                this.attrValue = '';
            
                // Indented Mode
                this.indentOf = Infinity;
                this.indentToken = '';
            
                this.innerMode = null;
                this.innerState = null;
            
                this.innerModeForLine = false;
              }
              /**
               * Safely copy a state
               *
               * @return {State}
               */
              State.prototype.copy = function () {
                var res = new State();
                res.javaScriptLine = this.javaScriptLine;
                res.javaScriptLineExcludesColon = this.javaScriptLineExcludesColon;
                res.javaScriptArguments = this.javaScriptArguments;
                res.javaScriptArgumentsDepth = this.javaScriptArgumentsDepth;
                res.isInterpolating = this.isInterpolating;
                res.interpolationNesting = this.intpolationNesting;
            
                res.jsState = CodeMirror.copyState(jsMode, this.jsState);
            
                res.innerMode = this.innerMode;
                if (this.innerMode && this.innerState) {
                  res.innerState = CodeMirror.copyState(this.innerMode, this.innerState);
                }
            
                res.restOfLine = this.restOfLine;
            
                res.isIncludeFiltered = this.isIncludeFiltered;
                res.isEach = this.isEach;
                res.lastTag = this.lastTag;
                res.scriptType = this.scriptType;
                res.isAttrs = this.isAttrs;
                res.attrsNest = this.attrsNest.slice();
                res.inAttributeName = this.inAttributeName;
                res.attributeIsType = this.attributeIsType;
                res.attrValue = this.attrValue;
                res.indentOf = this.indentOf;
                res.indentToken = this.indentToken;
            
                res.innerModeForLine = this.innerModeForLine;
            
                return res;
              };
            
              function javaScript(stream, state) {
                if (stream.sol()) {
                  // if javaScriptLine was set at end of line, ignore it
                  state.javaScriptLine = false;
                  state.javaScriptLineExcludesColon = false;
                }
                if (state.javaScriptLine) {
                  if (state.javaScriptLineExcludesColon && stream.peek() === ':') {
                    state.javaScriptLine = false;
                    state.javaScriptLineExcludesColon = false;
                    return;
                  }
                  var tok = jsMode.token(stream, state.jsState);
                  if (stream.eol()) state.javaScriptLine = false;
                  return tok || true;
                }
              }
              function javaScriptArguments(stream, state) {
                if (state.javaScriptArguments) {
                  if (state.javaScriptArgumentsDepth === 0 && stream.peek() !== '(') {
                    state.javaScriptArguments = false;
                    return;
                  }
                  if (stream.peek() === '(') {
                    state.javaScriptArgumentsDepth++;
                  } else if (stream.peek() === ')') {
                    state.javaScriptArgumentsDepth--;
                  }
                  if (state.javaScriptArgumentsDepth === 0) {
                    state.javaScriptArguments = false;
                    return;
                  }
            
                  var tok = jsMode.token(stream, state.jsState);
                  return tok || true;
                }
              }
            
              function yieldStatement(stream) {
                if (stream.match(/^yield\b/)) {
                    return 'keyword';
                }
              }
            
              function doctype(stream) {
                if (stream.match(/^(?:doctype) *([^\n]+)?/)) {
                    return DOCTYPE;
                }
              }
            
              function interpolation(stream, state) {
                if (stream.match('#{')) {
                  state.isInterpolating = true;
                  state.interpolationNesting = 0;
                  return 'punctuation';
                }
              }
            
              function interpolationContinued(stream, state) {
                if (state.isInterpolating) {
                  if (stream.peek() === '}') {
                    state.interpolationNesting--;
                    if (state.interpolationNesting < 0) {
                      stream.next();
                      state.isInterpolating = false;
                      return 'puncutation';
                    }
                  } else if (stream.peek() === '{') {
                    state.interpolationNesting++;
                  }
                  return jsMode.token(stream, state.jsState) || true;
                }
              }
            
              function caseStatement(stream, state) {
                if (stream.match(/^case\b/)) {
                  state.javaScriptLine = true;
                  return KEYWORD;
                }
              }
            
              function when(stream, state) {
                if (stream.match(/^when\b/)) {
                  state.javaScriptLine = true;
                  state.javaScriptLineExcludesColon = true;
                  return KEYWORD;
                }
              }
            
              function defaultStatement(stream) {
                if (stream.match(/^default\b/)) {
                  return KEYWORD;
                }
              }
            
              function extendsStatement(stream, state) {
                if (stream.match(/^extends?\b/)) {
                  state.restOfLine = 'string';
                  return KEYWORD;
                }
              }
            
              function append(stream, state) {
                if (stream.match(/^append\b/)) {
                  state.restOfLine = 'variable';
                  return KEYWORD;
                }
              }
              function prepend(stream, state) {
                if (stream.match(/^prepend\b/)) {
                  state.restOfLine = 'variable';
                  return KEYWORD;
                }
              }
              function block(stream, state) {
                if (stream.match(/^block\b *(?:(prepend|append)\b)?/)) {
                  state.restOfLine = 'variable';
                  return KEYWORD;
                }
              }
            
              function include(stream, state) {
                if (stream.match(/^include\b/)) {
                  state.restOfLine = 'string';
                  return KEYWORD;
                }
              }
            
              function includeFiltered(stream, state) {
                if (stream.match(/^include:([a-zA-Z0-9\-]+)/, false) && stream.match('include')) {
                  state.isIncludeFiltered = true;
                  return KEYWORD;
                }
              }
            
              function includeFilteredContinued(stream, state) {
                if (state.isIncludeFiltered) {
                  var tok = filter(stream, state);
                  state.isIncludeFiltered = false;
                  state.restOfLine = 'string';
                  return tok;
                }
              }
            
              function mixin(stream, state) {
                if (stream.match(/^mixin\b/)) {
                  state.javaScriptLine = true;
                  return KEYWORD;
                }
              }
            
              function call(stream, state) {
                if (stream.match(/^\+([-\w]+)/)) {
                  if (!stream.match(/^\( *[-\w]+ *=/, false)) {
                    state.javaScriptArguments = true;
                    state.javaScriptArgumentsDepth = 0;
                  }
                  return 'variable';
                }
                if (stream.match(/^\+#{/, false)) {
                  stream.next();
                  state.mixinCallAfter = true;
                  return interpolation(stream, state);
                }
              }
              function callArguments(stream, state) {
                if (state.mixinCallAfter) {
                  state.mixinCallAfter = false;
                  if (!stream.match(/^\( *[-\w]+ *=/, false)) {
                    state.javaScriptArguments = true;
                    state.javaScriptArgumentsDepth = 0;
                  }
                  return true;
                }
              }
            
              function conditional(stream, state) {
                if (stream.match(/^(if|unless|else if|else)\b/)) {
                  state.javaScriptLine = true;
                  return KEYWORD;
                }
              }
            
              function each(stream, state) {
                if (stream.match(/^(- *)?(each|for)\b/)) {
                  state.isEach = true;
                  return KEYWORD;
                }
              }
              function eachContinued(stream, state) {
                if (state.isEach) {
                  if (stream.match(/^ in\b/)) {
                    state.javaScriptLine = true;
                    state.isEach = false;
                    return KEYWORD;
                  } else if (stream.sol() || stream.eol()) {
                    state.isEach = false;
                  } else if (stream.next()) {
                    while (!stream.match(/^ in\b/, false) && stream.next());
                    return 'variable';
                  }
                }
              }
            
              function whileStatement(stream, state) {
                if (stream.match(/^while\b/)) {
                  state.javaScriptLine = true;
                  return KEYWORD;
                }
              }
            
              function tag(stream, state) {
                var captures;
                if (captures = stream.match(/^(\w(?:[-:\w]*\w)?)\/?/)) {
                  state.lastTag = captures[1].toLowerCase();
                  if (state.lastTag === 'script') {
                    state.scriptType = 'application/javascript';
                  }
                  return 'tag';
                }
              }
            
              function filter(stream, state) {
                if (stream.match(/^:([\w\-]+)/)) {
                  var innerMode;
                  if (config && config.innerModes) {
                    innerMode = config.innerModes(stream.current().substring(1));
                  }
                  if (!innerMode) {
                    innerMode = stream.current().substring(1);
                  }
                  if (typeof innerMode === 'string') {
                    innerMode = CodeMirror.getMode(config, innerMode);
                  }
                  setInnerMode(stream, state, innerMode);
                  return 'atom';
                }
              }
            
              function code(stream, state) {
                if (stream.match(/^(!?=|-)/)) {
                  state.javaScriptLine = true;
                  return 'punctuation';
                }
              }
            
              function id(stream) {
                if (stream.match(/^#([\w-]+)/)) {
                  return ID;
                }
              }
            
              function className(stream) {
                if (stream.match(/^\.([\w-]+)/)) {
                  return CLASS;
                }
              }
            
              function attrs(stream, state) {
                if (stream.peek() == '(') {
                  stream.next();
                  state.isAttrs = true;
                  state.attrsNest = [];
                  state.inAttributeName = true;
                  state.attrValue = '';
                  state.attributeIsType = false;
                  return 'punctuation';
                }
              }
            
              function attrsContinued(stream, state) {
                if (state.isAttrs) {
                  if (ATTRS_NEST[stream.peek()]) {
                    state.attrsNest.push(ATTRS_NEST[stream.peek()]);
                  }
                  if (state.attrsNest[state.attrsNest.length - 1] === stream.peek()) {
                    state.attrsNest.pop();
                  } else  if (stream.eat(')')) {
                    state.isAttrs = false;
                    return 'punctuation';
                  }
                  if (state.inAttributeName && stream.match(/^[^=,\)!]+/)) {
                    if (stream.peek() === '=' || stream.peek() === '!') {
                      state.inAttributeName = false;
                      state.jsState = jsMode.startState();
                      if (state.lastTag === 'script' && stream.current().trim().toLowerCase() === 'type') {
                        state.attributeIsType = true;
                      } else {
                        state.attributeIsType = false;
                      }
                    }
                    return 'attribute';
                  }
            
                  var tok = jsMode.token(stream, state.jsState);
                  if (state.attributeIsType && tok === 'string') {
                    state.scriptType = stream.current().toString();
                  }
                  if (state.attrsNest.length === 0 && (tok === 'string' || tok === 'variable' || tok === 'keyword')) {
                    try {
                      Function('', 'var x ' + state.attrValue.replace(/,\s*$/, '').replace(/^!/, ''));
                      state.inAttributeName = true;
                      state.attrValue = '';
                      stream.backUp(stream.current().length);
                      return attrsContinued(stream, state);
                    } catch (ex) {
                      //not the end of an attribute
                    }
                  }
                  state.attrValue += stream.current();
                  return tok || true;
                }
              }
            
              function attributesBlock(stream, state) {
                if (stream.match(/^&attributes\b/)) {
                  state.javaScriptArguments = true;
                  state.javaScriptArgumentsDepth = 0;
                  return 'keyword';
                }
              }
            
              function indent(stream) {
                if (stream.sol() && stream.eatSpace()) {
                  return 'indent';
                }
              }
            
              function comment(stream, state) {
                if (stream.match(/^ *\/\/(-)?([^\n]*)/)) {
                  state.indentOf = stream.indentation();
                  state.indentToken = 'comment';
                  return 'comment';
                }
              }
            
              function colon(stream) {
                if (stream.match(/^: */)) {
                  return 'colon';
                }
              }
            
              function text(stream, state) {
                if (stream.match(/^(?:\| ?| )([^\n]+)/)) {
                  return 'string';
                }
                if (stream.match(/^(<[^\n]*)/, false)) {
                  // html string
                  setInnerMode(stream, state, 'htmlmixed');
                  state.innerModeForLine = true;
                  return innerMode(stream, state, true);
                }
              }
            
              function dot(stream, state) {
                if (stream.eat('.')) {
                  var innerMode = null;
                  if (state.lastTag === 'script' && state.scriptType.toLowerCase().indexOf('javascript') != -1) {
                    innerMode = state.scriptType.toLowerCase().replace(/"|'/g, '');
                  } else if (state.lastTag === 'style') {
                    innerMode = 'css';
                  }
                  setInnerMode(stream, state, innerMode);
                  return 'dot';
                }
              }
            
              function fail(stream) {
                stream.next();
                return null;
              }
            
            
              function setInnerMode(stream, state, mode) {
                mode = CodeMirror.mimeModes[mode] || mode;
                mode = config.innerModes ? config.innerModes(mode) || mode : mode;
                mode = CodeMirror.mimeModes[mode] || mode;
                mode = CodeMirror.getMode(config, mode);
                state.indentOf = stream.indentation();
            
                if (mode && mode.name !== 'null') {
                  state.innerMode = mode;
                } else {
                  state.indentToken = 'string';
                }
              }
              function innerMode(stream, state, force) {
                if (stream.indentation() > state.indentOf || (state.innerModeForLine && !stream.sol()) || force) {
                  if (state.innerMode) {
                    if (!state.innerState) {
                      state.innerState = state.innerMode.startState ? state.innerMode.startState(stream.indentation()) : {};
                    }
                    return stream.hideFirstChars(state.indentOf + 2, function () {
                      return state.innerMode.token(stream, state.innerState) || true;
                    });
                  } else {
                    stream.skipToEnd();
                    return state.indentToken;
                  }
                } else if (stream.sol()) {
                  state.indentOf = Infinity;
                  state.indentToken = null;
                  state.innerMode = null;
                  state.innerState = null;
                }
              }
              function restOfLine(stream, state) {
                if (stream.sol()) {
                  // if restOfLine was set at end of line, ignore it
                  state.restOfLine = '';
                }
                if (state.restOfLine) {
                  stream.skipToEnd();
                  var tok = state.restOfLine;
                  state.restOfLine = '';
                  return tok;
                }
              }
            
            
              function startState() {
                return new State();
              }
              function copyState(state) {
                return state.copy();
              }
              /**
               * Get the next token in the stream
               *
               * @param {Stream} stream
               * @param {State} state
               */
              function nextToken(stream, state) {
                var tok = innerMode(stream, state)
                  || restOfLine(stream, state)
                  || interpolationContinued(stream, state)
                  || includeFilteredContinued(stream, state)
                  || eachContinued(stream, state)
                  || attrsContinued(stream, state)
                  || javaScript(stream, state)
                  || javaScriptArguments(stream, state)
                  || callArguments(stream, state)
            
                  || yieldStatement(stream, state)
                  || doctype(stream, state)
                  || interpolation(stream, state)
                  || caseStatement(stream, state)
                  || when(stream, state)
                  || defaultStatement(stream, state)
                  || extendsStatement(stream, state)
                  || append(stream, state)
                  || prepend(stream, state)
                  || block(stream, state)
                  || include(stream, state)
                  || includeFiltered(stream, state)
                  || mixin(stream, state)
                  || call(stream, state)
                  || conditional(stream, state)
                  || each(stream, state)
                  || whileStatement(stream, state)
                  || tag(stream, state)
                  || filter(stream, state)
                  || code(stream, state)
                  || id(stream, state)
                  || className(stream, state)
                  || attrs(stream, state)
                  || attributesBlock(stream, state)
                  || indent(stream, state)
                  || text(stream, state)
                  || comment(stream, state)
                  || colon(stream, state)
                  || dot(stream, state)
                  || fail(stream, state);
            
                return tok === true ? null : tok;
              }
              return {
                startState: startState,
                copyState: copyState,
                token: nextToken
              };
            });
            
            CodeMirror.defineMIME('text/x-jade', 'jade');
            
            });
            
        • javascript
          • index.html
            <!doctype html>
            
            <title>CodeMirror: JavaScript mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="../../addon/comment/continuecomment.js"></script>
            <script src="../../addon/comment/comment.js"></script>
            <script src="javascript.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">JavaScript</a>
              </ul>
            </div>
            
            <article>
            <h2>JavaScript mode</h2>
            
            
            <div><textarea id="code" name="code">
            // Demo code (the actual new parser character stream implementation)
            
            function StringStream(string) {
              this.pos = 0;
              this.string = string;
            }
            
            StringStream.prototype = {
              done: function() {return this.pos >= this.string.length;},
              peek: function() {return this.string.charAt(this.pos);},
              next: function() {
                if (this.pos &lt; this.string.length)
                  return this.string.charAt(this.pos++);
              },
              eat: function(match) {
                var ch = this.string.charAt(this.pos);
                if (typeof match == "string") var ok = ch == match;
                else var ok = ch &amp;&amp; match.test ? match.test(ch) : match(ch);
                if (ok) {this.pos++; return ch;}
              },
              eatWhile: function(match) {
                var start = this.pos;
                while (this.eat(match));
                if (this.pos > start) return this.string.slice(start, this.pos);
              },
              backUp: function(n) {this.pos -= n;},
              column: function() {return this.pos;},
              eatSpace: function() {
                var start = this.pos;
                while (/\s/.test(this.string.charAt(this.pos))) this.pos++;
                return this.pos - start;
              },
              match: function(pattern, consume, caseInsensitive) {
                if (typeof pattern == "string") {
                  function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
                  if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
                    if (consume !== false) this.pos += str.length;
                    return true;
                  }
                }
                else {
                  var match = this.string.slice(this.pos).match(pattern);
                  if (match &amp;&amp; consume !== false) this.pos += match[0].length;
                  return match;
                }
              }
            };
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    continueComments: "Enter",
                    extraKeys: {"Ctrl-Q": "toggleComment"}
                  });
                </script>
            
                <p>
                  JavaScript mode supports several configuration options:
                  <ul>
                    <li><code>json</code> which will set the mode to expect JSON
                    data rather than a JavaScript program.</li>
                    <li><code>jsonld</code> which will set the mode to expect
                    <a href="http://json-ld.org">JSON-LD</a> linked data rather
                    than a JavaScript program (<a href="json-ld.html">demo</a>).</li>
                    <li><code>typescript</code> which will activate additional
                    syntax highlighting and some other things for TypeScript code
                    (<a href="typescript.html">demo</a>).</li>
                    <li><code>statementIndent</code> which (given a number) will
                    determine the amount of indentation to use for statements
                    continued on a new line.</li>
                    <li><code>wordCharacters</code>, a regexp that indicates which
                    characters should be considered part of an identifier.
                    Defaults to <code>/[\w$]/</code>, which does not handle
                    non-ASCII identifiers. Can be set to something more elaborate
                    to improve Unicode support.</li>
                  </ul>
                </p>
            
                <p><strong>MIME types defined:</strong> <code>text/javascript</code>, <code>application/json</code>, <code>application/ld+json</code>, <code>text/typescript</code>, <code>application/typescript</code>.</p>
              </article>
            
          • javascript.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // TODO actually recognize syntax of TypeScript constructs
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("javascript", function(config, parserConfig) {
              var indentUnit = config.indentUnit;
              var statementIndent = parserConfig.statementIndent;
              var jsonldMode = parserConfig.jsonld;
              var jsonMode = parserConfig.json || jsonldMode;
              var isTS = parserConfig.typescript;
              var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
            
              // Tokenizer
            
              var keywords = function(){
                function kw(type) {return {type: type, style: "keyword"};}
                var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
                var operator = kw("operator"), atom = {type: "atom", style: "atom"};
            
                var jsKeywords = {
                  "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
                  "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
                  "var": kw("var"), "const": kw("var"), "let": kw("var"),
                  "function": kw("function"), "catch": kw("catch"),
                  "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
                  "in": operator, "typeof": operator, "instanceof": operator,
                  "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
                  "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
                  "yield": C, "export": kw("export"), "import": kw("import"), "extends": C
                };
            
                // Extend the 'normal' keywords with the TypeScript language extensions
                if (isTS) {
                  var type = {type: "variable", style: "variable-3"};
                  var tsKeywords = {
                    // object-like things
                    "interface": kw("interface"),
                    "extends": kw("extends"),
                    "constructor": kw("constructor"),
            
                    // scope modifiers
                    "public": kw("public"),
                    "private": kw("private"),
                    "protected": kw("protected"),
                    "static": kw("static"),
            
                    // types
                    "string": type, "number": type, "bool": type, "any": type
                  };
            
                  for (var attr in tsKeywords) {
                    jsKeywords[attr] = tsKeywords[attr];
                  }
                }
            
                return jsKeywords;
              }();
            
              var isOperatorChar = /[+\-*&%=<>!?|~^]/;
              var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
            
              function readRegexp(stream) {
                var escaped = false, next, inSet = false;
                while ((next = stream.next()) != null) {
                  if (!escaped) {
                    if (next == "/" && !inSet) return;
                    if (next == "[") inSet = true;
                    else if (inSet && next == "]") inSet = false;
                  }
                  escaped = !escaped && next == "\\";
                }
              }
            
              // Used as scratch variables to communicate multiple values without
              // consing up tons of objects.
              var type, content;
              function ret(tp, style, cont) {
                type = tp; content = cont;
                return style;
              }
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"' || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
                  return ret("number", "number");
                } else if (ch == "." && stream.match("..")) {
                  return ret("spread", "meta");
                } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  return ret(ch);
                } else if (ch == "=" && stream.eat(">")) {
                  return ret("=>", "operator");
                } else if (ch == "0" && stream.eat(/x/i)) {
                  stream.eatWhile(/[\da-f]/i);
                  return ret("number", "number");
                } else if (/\d/.test(ch)) {
                  stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
                  return ret("number", "number");
                } else if (ch == "/") {
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment;
                    return tokenComment(stream, state);
                  } else if (stream.eat("/")) {
                    stream.skipToEnd();
                    return ret("comment", "comment");
                  } else if (state.lastType == "operator" || state.lastType == "keyword c" ||
                           state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
                    readRegexp(stream);
                    stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
                    return ret("regexp", "string-2");
                  } else {
                    stream.eatWhile(isOperatorChar);
                    return ret("operator", "operator", stream.current());
                  }
                } else if (ch == "`") {
                  state.tokenize = tokenQuasi;
                  return tokenQuasi(stream, state);
                } else if (ch == "#") {
                  stream.skipToEnd();
                  return ret("error", "error");
                } else if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return ret("operator", "operator", stream.current());
                } else if (wordRE.test(ch)) {
                  stream.eatWhile(wordRE);
                  var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
                  return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
                                 ret("variable", "variable", word);
                }
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next;
                  if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
                    state.tokenize = tokenBase;
                    return ret("jsonld-keyword", "meta");
                  }
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) break;
                    escaped = !escaped && next == "\\";
                  }
                  if (!escaped) state.tokenize = tokenBase;
                  return ret("string", "string");
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return ret("comment", "comment");
              }
            
              function tokenQuasi(stream, state) {
                var escaped = false, next;
                while ((next = stream.next()) != null) {
                  if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  escaped = !escaped && next == "\\";
                }
                return ret("quasi", "string-2", stream.current());
              }
            
              var brackets = "([{}])";
              // This is a crude lookahead trick to try and notice that we're
              // parsing the argument patterns for a fat-arrow function before we
              // actually hit the arrow token. It only works if the arrow is on
              // the same line as the arguments and there's no strange noise
              // (comments) in between. Fallback is to only notice when we hit the
              // arrow, and not declare the arguments as locals for the arrow
              // body.
              function findFatArrow(stream, state) {
                if (state.fatArrowAt) state.fatArrowAt = null;
                var arrow = stream.string.indexOf("=>", stream.start);
                if (arrow < 0) return;
            
                var depth = 0, sawSomething = false;
                for (var pos = arrow - 1; pos >= 0; --pos) {
                  var ch = stream.string.charAt(pos);
                  var bracket = brackets.indexOf(ch);
                  if (bracket >= 0 && bracket < 3) {
                    if (!depth) { ++pos; break; }
                    if (--depth == 0) break;
                  } else if (bracket >= 3 && bracket < 6) {
                    ++depth;
                  } else if (wordRE.test(ch)) {
                    sawSomething = true;
                  } else if (/["'\/]/.test(ch)) {
                    return;
                  } else if (sawSomething && !depth) {
                    ++pos;
                    break;
                  }
                }
                if (sawSomething && !depth) state.fatArrowAt = pos;
              }
            
              // Parser
            
              var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
            
              function JSLexical(indented, column, type, align, prev, info) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.prev = prev;
                this.info = info;
                if (align != null) this.align = align;
              }
            
              function inScope(state, varname) {
                for (var v = state.localVars; v; v = v.next)
                  if (v.name == varname) return true;
                for (var cx = state.context; cx; cx = cx.prev) {
                  for (var v = cx.vars; v; v = v.next)
                    if (v.name == varname) return true;
                }
              }
            
              function parseJS(state, style, type, content, stream) {
                var cc = state.cc;
                // Communicate our context to the combinators.
                // (Less wasteful than consing up a hundred closures on every call.)
                cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
            
                if (!state.lexical.hasOwnProperty("align"))
                  state.lexical.align = true;
            
                while(true) {
                  var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
                  if (combinator(type, content)) {
                    while(cc.length && cc[cc.length - 1].lex)
                      cc.pop()();
                    if (cx.marked) return cx.marked;
                    if (type == "variable" && inScope(state, content)) return "variable-2";
                    return style;
                  }
                }
              }
            
              // Combinator utils
            
              var cx = {state: null, column: null, marked: null, cc: null};
              function pass() {
                for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
              }
              function cont() {
                pass.apply(null, arguments);
                return true;
              }
              function register(varname) {
                function inList(list) {
                  for (var v = list; v; v = v.next)
                    if (v.name == varname) return true;
                  return false;
                }
                var state = cx.state;
                if (state.context) {
                  cx.marked = "def";
                  if (inList(state.localVars)) return;
                  state.localVars = {name: varname, next: state.localVars};
                } else {
                  if (inList(state.globalVars)) return;
                  if (parserConfig.globalVars)
                    state.globalVars = {name: varname, next: state.globalVars};
                }
              }
            
              // Combinators
            
              var defaultVars = {name: "this", next: {name: "arguments"}};
              function pushcontext() {
                cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
                cx.state.localVars = defaultVars;
              }
              function popcontext() {
                cx.state.localVars = cx.state.context.vars;
                cx.state.context = cx.state.context.prev;
              }
              function pushlex(type, info) {
                var result = function() {
                  var state = cx.state, indent = state.indented;
                  if (state.lexical.type == "stat") indent = state.lexical.indented;
                  else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
                    indent = outer.indented;
                  state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
                };
                result.lex = true;
                return result;
              }
              function poplex() {
                var state = cx.state;
                if (state.lexical.prev) {
                  if (state.lexical.type == ")")
                    state.indented = state.lexical.indented;
                  state.lexical = state.lexical.prev;
                }
              }
              poplex.lex = true;
            
              function expect(wanted) {
                function exp(type) {
                  if (type == wanted) return cont();
                  else if (wanted == ";") return pass();
                  else return cont(exp);
                };
                return exp;
              }
            
              function statement(type, value) {
                if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
                if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
                if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
                if (type == "{") return cont(pushlex("}"), block, poplex);
                if (type == ";") return cont();
                if (type == "if") {
                  if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
                    cx.state.cc.pop()();
                  return cont(pushlex("form"), expression, statement, poplex, maybeelse);
                }
                if (type == "function") return cont(functiondef);
                if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
                if (type == "variable") return cont(pushlex("stat"), maybelabel);
                if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
                                                  block, poplex, poplex);
                if (type == "case") return cont(expression, expect(":"));
                if (type == "default") return cont(expect(":"));
                if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
                                                 statement, poplex, popcontext);
                if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
                if (type == "class") return cont(pushlex("form"), className, poplex);
                if (type == "export") return cont(pushlex("form"), afterExport, poplex);
                if (type == "import") return cont(pushlex("form"), afterImport, poplex);
                return pass(pushlex("stat"), expression, expect(";"), poplex);
              }
              function expression(type) {
                return expressionInner(type, false);
              }
              function expressionNoComma(type) {
                return expressionInner(type, true);
              }
              function expressionInner(type, noComma) {
                if (cx.state.fatArrowAt == cx.stream.start) {
                  var body = noComma ? arrowBodyNoComma : arrowBody;
                  if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
                  else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
                }
            
                var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
                if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
                if (type == "function") return cont(functiondef, maybeop);
                if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
                if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
                if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
                if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
                if (type == "{") return contCommasep(objprop, "}", null, maybeop);
                if (type == "quasi") { return pass(quasi, maybeop); }
                return cont();
              }
              function maybeexpression(type) {
                if (type.match(/[;\}\)\],]/)) return pass();
                return pass(expression);
              }
              function maybeexpressionNoComma(type) {
                if (type.match(/[;\}\)\],]/)) return pass();
                return pass(expressionNoComma);
              }
            
              function maybeoperatorComma(type, value) {
                if (type == ",") return cont(expression);
                return maybeoperatorNoComma(type, value, false);
              }
              function maybeoperatorNoComma(type, value, noComma) {
                var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
                var expr = noComma == false ? expression : expressionNoComma;
                if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
                if (type == "operator") {
                  if (/\+\+|--/.test(value)) return cont(me);
                  if (value == "?") return cont(expression, expect(":"), expr);
                  return cont(expr);
                }
                if (type == "quasi") { return pass(quasi, me); }
                if (type == ";") return;
                if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
                if (type == ".") return cont(property, me);
                if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
              }
              function quasi(type, value) {
                if (type != "quasi") return pass();
                if (value.slice(value.length - 2) != "${") return cont(quasi);
                return cont(expression, continueQuasi);
              }
              function continueQuasi(type) {
                if (type == "}") {
                  cx.marked = "string-2";
                  cx.state.tokenize = tokenQuasi;
                  return cont(quasi);
                }
              }
              function arrowBody(type) {
                findFatArrow(cx.stream, cx.state);
                return pass(type == "{" ? statement : expression);
              }
              function arrowBodyNoComma(type) {
                findFatArrow(cx.stream, cx.state);
                return pass(type == "{" ? statement : expressionNoComma);
              }
              function maybelabel(type) {
                if (type == ":") return cont(poplex, statement);
                return pass(maybeoperatorComma, expect(";"), poplex);
              }
              function property(type) {
                if (type == "variable") {cx.marked = "property"; return cont();}
              }
              function objprop(type, value) {
                if (type == "variable" || cx.style == "keyword") {
                  cx.marked = "property";
                  if (value == "get" || value == "set") return cont(getterSetter);
                  return cont(afterprop);
                } else if (type == "number" || type == "string") {
                  cx.marked = jsonldMode ? "property" : (cx.style + " property");
                  return cont(afterprop);
                } else if (type == "jsonld-keyword") {
                  return cont(afterprop);
                } else if (type == "[") {
                  return cont(expression, expect("]"), afterprop);
                }
              }
              function getterSetter(type) {
                if (type != "variable") return pass(afterprop);
                cx.marked = "property";
                return cont(functiondef);
              }
              function afterprop(type) {
                if (type == ":") return cont(expressionNoComma);
                if (type == "(") return pass(functiondef);
              }
              function commasep(what, end) {
                function proceed(type) {
                  if (type == ",") {
                    var lex = cx.state.lexical;
                    if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
                    return cont(what, proceed);
                  }
                  if (type == end) return cont();
                  return cont(expect(end));
                }
                return function(type) {
                  if (type == end) return cont();
                  return pass(what, proceed);
                };
              }
              function contCommasep(what, end, info) {
                for (var i = 3; i < arguments.length; i++)
                  cx.cc.push(arguments[i]);
                return cont(pushlex(end, info), commasep(what, end), poplex);
              }
              function block(type) {
                if (type == "}") return cont();
                return pass(statement, block);
              }
              function maybetype(type) {
                if (isTS && type == ":") return cont(typedef);
              }
              function typedef(type) {
                if (type == "variable"){cx.marked = "variable-3"; return cont();}
              }
              function vardef() {
                return pass(pattern, maybetype, maybeAssign, vardefCont);
              }
              function pattern(type, value) {
                if (type == "variable") { register(value); return cont(); }
                if (type == "[") return contCommasep(pattern, "]");
                if (type == "{") return contCommasep(proppattern, "}");
              }
              function proppattern(type, value) {
                if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
                  register(value);
                  return cont(maybeAssign);
                }
                if (type == "variable") cx.marked = "property";
                return cont(expect(":"), pattern, maybeAssign);
              }
              function maybeAssign(_type, value) {
                if (value == "=") return cont(expressionNoComma);
              }
              function vardefCont(type) {
                if (type == ",") return cont(vardef);
              }
              function maybeelse(type, value) {
                if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
              }
              function forspec(type) {
                if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
              }
              function forspec1(type) {
                if (type == "var") return cont(vardef, expect(";"), forspec2);
                if (type == ";") return cont(forspec2);
                if (type == "variable") return cont(formaybeinof);
                return pass(expression, expect(";"), forspec2);
              }
              function formaybeinof(_type, value) {
                if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
                return cont(maybeoperatorComma, forspec2);
              }
              function forspec2(type, value) {
                if (type == ";") return cont(forspec3);
                if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
                return pass(expression, expect(";"), forspec3);
              }
              function forspec3(type) {
                if (type != ")") cont(expression);
              }
              function functiondef(type, value) {
                if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
                if (type == "variable") {register(value); return cont(functiondef);}
                if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
              }
              function funarg(type) {
                if (type == "spread") return cont(funarg);
                return pass(pattern, maybetype);
              }
              function className(type, value) {
                if (type == "variable") {register(value); return cont(classNameAfter);}
              }
              function classNameAfter(type, value) {
                if (value == "extends") return cont(expression, classNameAfter);
                if (type == "{") return cont(pushlex("}"), classBody, poplex);
              }
              function classBody(type, value) {
                if (type == "variable" || cx.style == "keyword") {
                  if (value == "static") {
                    cx.marked = "keyword";
                    return cont(classBody);
                  }
                  cx.marked = "property";
                  if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);
                  return cont(functiondef, classBody);
                }
                if (value == "*") {
                  cx.marked = "keyword";
                  return cont(classBody);
                }
                if (type == ";") return cont(classBody);
                if (type == "}") return cont();
              }
              function classGetterSetter(type) {
                if (type != "variable") return pass();
                cx.marked = "property";
                return cont();
              }
              function afterModule(type, value) {
                if (type == "string") return cont(statement);
                if (type == "variable") { register(value); return cont(maybeFrom); }
              }
              function afterExport(_type, value) {
                if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
                if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
                return pass(statement);
              }
              function afterImport(type) {
                if (type == "string") return cont();
                return pass(importSpec, maybeFrom);
              }
              function importSpec(type, value) {
                if (type == "{") return contCommasep(importSpec, "}");
                if (type == "variable") register(value);
                if (value == "*") cx.marked = "keyword";
                return cont(maybeAs);
              }
              function maybeAs(_type, value) {
                if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
              }
              function maybeFrom(_type, value) {
                if (value == "from") { cx.marked = "keyword"; return cont(expression); }
              }
              function arrayLiteral(type) {
                if (type == "]") return cont();
                return pass(expressionNoComma, maybeArrayComprehension);
              }
              function maybeArrayComprehension(type) {
                if (type == "for") return pass(comprehension, expect("]"));
                if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));
                return pass(commasep(expressionNoComma, "]"));
              }
              function comprehension(type) {
                if (type == "for") return cont(forspec, comprehension);
                if (type == "if") return cont(expression, comprehension);
              }
            
              function isContinuedStatement(state, textAfter) {
                return state.lastType == "operator" || state.lastType == "," ||
                  isOperatorChar.test(textAfter.charAt(0)) ||
                  /[,.]/.test(textAfter.charAt(0));
              }
            
              // Interface
            
              return {
                startState: function(basecolumn) {
                  var state = {
                    tokenize: tokenBase,
                    lastType: "sof",
                    cc: [],
                    lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
                    localVars: parserConfig.localVars,
                    context: parserConfig.localVars && {vars: parserConfig.localVars},
                    indented: 0
                  };
                  if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
                    state.globalVars = parserConfig.globalVars;
                  return state;
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (!state.lexical.hasOwnProperty("align"))
                      state.lexical.align = false;
                    state.indented = stream.indentation();
                    findFatArrow(stream, state);
                  }
                  if (state.tokenize != tokenComment && stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
                  if (type == "comment") return style;
                  state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
                  return parseJS(state, style, type, content, stream);
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize == tokenComment) return CodeMirror.Pass;
                  if (state.tokenize != tokenBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
                  // Kludge to prevent 'maybelse' from blocking lexical scope pops
                  if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
                    var c = state.cc[i];
                    if (c == poplex) lexical = lexical.prev;
                    else if (c != maybeelse) break;
                  }
                  if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
                  if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
                    lexical = lexical.prev;
                  var type = lexical.type, closing = firstChar == type;
            
                  if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
                  else if (type == "form" && firstChar == "{") return lexical.indented;
                  else if (type == "form") return lexical.indented + indentUnit;
                  else if (type == "stat")
                    return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
                  else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
                    return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
                  else if (lexical.align) return lexical.column + (closing ? 0 : 1);
                  else return lexical.indented + (closing ? 0 : indentUnit);
                },
            
                electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
                blockCommentStart: jsonMode ? null : "/*",
                blockCommentEnd: jsonMode ? null : "*/",
                lineComment: jsonMode ? null : "//",
                fold: "brace",
                closeBrackets: "()[]{}''\"\"``",
            
                helperType: jsonMode ? "json" : "javascript",
                jsonldMode: jsonldMode,
                jsonMode: jsonMode
              };
            });
            
            CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
            
            CodeMirror.defineMIME("text/javascript", "javascript");
            CodeMirror.defineMIME("text/ecmascript", "javascript");
            CodeMirror.defineMIME("application/javascript", "javascript");
            CodeMirror.defineMIME("application/x-javascript", "javascript");
            CodeMirror.defineMIME("application/ecmascript", "javascript");
            CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
            CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
            CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
            CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
            CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
            
            });
            
          • json-ld.html
            <!doctype html>
            
            <title>CodeMirror: JSON-LD mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="../../addon/comment/continuecomment.js"></script>
            <script src="../../addon/comment/comment.js"></script>
            <script src="javascript.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id="nav">
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"/></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">JSON-LD</a>
              </ul>
            </div>
            
            <article>
            <h2>JSON-LD mode</h2>
            
            
            <div><textarea id="code" name="code">
            {
              "@context": {
                "name": "http://schema.org/name",
                "description": "http://schema.org/description",
                "image": {
                  "@id": "http://schema.org/image",
                  "@type": "@id"
                },
                "geo": "http://schema.org/geo",
                "latitude": {
                  "@id": "http://schema.org/latitude",
                  "@type": "xsd:float"
                },
                "longitude": {
                  "@id": "http://schema.org/longitude",
                  "@type": "xsd:float"
                },
                "xsd": "http://www.w3.org/2001/XMLSchema#"
              },
              "name": "The Empire State Building",
              "description": "The Empire State Building is a 102-story landmark in New York City.",
              "image": "http://www.civil.usherbrooke.ca/cours/gci215a/empire-state-building.jpg",
              "geo": {
                "latitude": "40.75",
                "longitude": "73.98"
              }
            }
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    matchBrackets: true,
                    autoCloseBrackets: true,
                    mode: "application/ld+json",
                    lineWrapping: true
                  });
                </script>
                
                <p>This is a specialization of the <a href="index.html">JavaScript mode</a>.</p>
              </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 2}, "javascript");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT("locals",
                 "[keyword function] [variable foo]([def a], [def b]) { [keyword var] [def c] [operator =] [number 10]; [keyword return] [variable-2 a] [operator +] [variable-2 c] [operator +] [variable d]; }");
            
              MT("comma-and-binop",
                 "[keyword function](){ [keyword var] [def x] [operator =] [number 1] [operator +] [number 2], [def y]; }");
            
              MT("destructuring",
                 "([keyword function]([def a], [[[def b], [def c] ]]) {",
                 "  [keyword let] {[def d], [property foo]: [def c][operator =][number 10], [def x]} [operator =] [variable foo]([variable-2 a]);",
                 "  [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];",
                 "})();");
            
              MT("class_body",
                 "[keyword class] [variable Foo] {",
                 "  [property constructor]() {}",
                 "  [property sayName]() {",
                 "    [keyword return] [string-2 `foo${][variable foo][string-2 }oo`];",
                 "  }",
                 "}");
            
              MT("class",
                 "[keyword class] [variable Point] [keyword extends] [variable SuperThing] {",
                 "  [property get] [property prop]() { [keyword return] [number 24]; }",
                 "  [property constructor]([def x], [def y]) {",
                 "    [keyword super]([string 'something']);",
                 "    [keyword this].[property x] [operator =] [variable-2 x];",
                 "  }",
                 "}");
            
              MT("module",
                 "[keyword module] [string 'foo'] {",
                 "  [keyword export] [keyword let] [def x] [operator =] [number 42];",
                 "  [keyword export] [keyword *] [keyword from] [string 'somewhere'];",
                 "}");
            
              MT("import",
                 "[keyword function] [variable foo]() {",
                 "  [keyword import] [def $] [keyword from] [string 'jquery'];",
                 "  [keyword module] [def crypto] [keyword from] [string 'crypto'];",
                 "  [keyword import] { [def encrypt], [def decrypt] } [keyword from] [string 'crypto'];",
                 "}");
            
              MT("const",
                 "[keyword function] [variable f]() {",
                 "  [keyword const] [[ [def a], [def b] ]] [operator =] [[ [number 1], [number 2] ]];",
                 "}");
            
              MT("for/of",
                 "[keyword for]([keyword let] [variable of] [keyword of] [variable something]) {}");
            
              MT("generator",
                 "[keyword function*] [variable repeat]([def n]) {",
                 "  [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])",
                 "    [keyword yield] [variable-2 i];",
                 "}");
            
              MT("quotedStringAddition",
                 "[keyword let] [variable f] [operator =] [variable a] [operator +] [string 'fatarrow'] [operator +] [variable c];");
            
              MT("quotedFatArrow",
                 "[keyword let] [variable f] [operator =] [variable a] [operator +] [string '=>'] [operator +] [variable c];");
            
              MT("fatArrow",
                 "[variable array].[property filter]([def a] [operator =>] [variable-2 a] [operator +] [number 1]);",
                 "[variable a];", // No longer in scope
                 "[keyword let] [variable f] [operator =] ([[ [def a], [def b] ]], [def c]) [operator =>] [variable-2 a] [operator +] [variable-2 c];",
                 "[variable c];");
            
              MT("spread",
                 "[keyword function] [variable f]([def a], [meta ...][def b]) {",
                 "  [variable something]([variable-2 a], [meta ...][variable-2 b]);",
                 "}");
            
              MT("comprehension",
                 "[keyword function] [variable f]() {",
                 "  [[([variable x] [operator +] [number 1]) [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];",
                 "  ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] [operator ===] [string 'blue']));",
                 "}");
            
              MT("quasi",
                 "[variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");
            
              MT("quasi_no_function",
                 "[variable x] [operator =] [string-2 `fofdlakj${][variable x] [operator +] [string-2 `foo`] [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");
            
              MT("indent_statement",
                 "[keyword var] [variable x] [operator =] [number 10]",
                 "[variable x] [operator +=] [variable y] [operator +]",
                 "  [atom Infinity]",
                 "[keyword debugger];");
            
              MT("indent_if",
                 "[keyword if] ([number 1])",
                 "  [keyword break];",
                 "[keyword else] [keyword if] ([number 2])",
                 "  [keyword continue];",
                 "[keyword else]",
                 "  [number 10];",
                 "[keyword if] ([number 1]) {",
                 "  [keyword break];",
                 "} [keyword else] [keyword if] ([number 2]) {",
                 "  [keyword continue];",
                 "} [keyword else] {",
                 "  [number 10];",
                 "}");
            
              MT("indent_for",
                 "[keyword for] ([keyword var] [variable i] [operator =] [number 0];",
                 "     [variable i] [operator <] [number 100];",
                 "     [variable i][operator ++])",
                 "  [variable doSomething]([variable i]);",
                 "[keyword debugger];");
            
              MT("indent_c_style",
                 "[keyword function] [variable foo]()",
                 "{",
                 "  [keyword debugger];",
                 "}");
            
              MT("indent_else",
                 "[keyword for] (;;)",
                 "  [keyword if] ([variable foo])",
                 "    [keyword if] ([variable bar])",
                 "      [number 1];",
                 "    [keyword else]",
                 "      [number 2];",
                 "  [keyword else]",
                 "    [number 3];");
            
              MT("indent_funarg",
                 "[variable foo]([number 10000],",
                 "    [keyword function]([def a]) {",
                 "  [keyword debugger];",
                 "};");
            
              MT("indent_below_if",
                 "[keyword for] (;;)",
                 "  [keyword if] ([variable foo])",
                 "    [number 1];",
                 "[number 2];");
            
              MT("multilinestring",
                 "[keyword var] [variable x] [operator =] [string 'foo\\]",
                 "[string bar'];");
            
              MT("scary_regexp",
                 "[string-2 /foo[[/]]bar/];");
            
              MT("indent_strange_array",
                 "[keyword var] [variable x] [operator =] [[",
                 "  [number 1],,",
                 "  [number 2],",
                 "]];",
                 "[number 10];");
            
              var jsonld_mode = CodeMirror.getMode(
                {indentUnit: 2},
                {name: "javascript", jsonld: true}
              );
              function LD(name) {
                test.mode(name, jsonld_mode, Array.prototype.slice.call(arguments, 1));
              }
            
              LD("json_ld_keywords",
                '{',
                '  [meta "@context"]: {',
                '    [meta "@base"]: [string "http://example.com"],',
                '    [meta "@vocab"]: [string "http://xmlns.com/foaf/0.1/"],',
                '    [property "likesFlavor"]: {',
                '      [meta "@container"]: [meta "@list"]',
                '      [meta "@reverse"]: [string "@beFavoriteOf"]',
                '    },',
                '    [property "nick"]: { [meta "@container"]: [meta "@set"] },',
                '    [property "nick"]: { [meta "@container"]: [meta "@index"] }',
                '  },',
                '  [meta "@graph"]: [[ {',
                '    [meta "@id"]: [string "http://dbpedia.org/resource/John_Lennon"],',
                '    [property "name"]: [string "John Lennon"],',
                '    [property "modified"]: {',
                '      [meta "@value"]: [string "2010-05-29T14:17:39+02:00"],',
                '      [meta "@type"]: [string "http://www.w3.org/2001/XMLSchema#dateTime"]',
                '    }',
                '  } ]]',
                '}');
            
              LD("json_ld_fake",
                '{',
                '  [property "@fake"]: [string "@fake"],',
                '  [property "@contextual"]: [string "@identifier"],',
                '  [property "user@domain.com"]: [string "@graphical"],',
                '  [property "@ID"]: [string "@@ID"]',
                '}');
            })();
            
          • typescript.html
            <!doctype html>
            
            <title>CodeMirror: TypeScript mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="javascript.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">TypeScript</a>
              </ul>
            </div>
            
            <article>
            <h2>TypeScript mode</h2>
            
            
            <div><textarea id="code" name="code">
            class Greeter {
            	greeting: string;
            	constructor (message: string) {
            		this.greeting = message;
            	}
            	greet() {
            		return "Hello, " + this.greeting;
            	}
            }   
            
            var greeter = new Greeter("world");
            
            var button = document.createElement('button')
            button.innerText = "Say Hello"
            button.onclick = function() {
            	alert(greeter.greet())
            }
            
            document.body.appendChild(button)
            
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/typescript"
                  });
                </script>
            
                <p>This is a specialization of the <a href="index.html">JavaScript mode</a>.</p>
              </article>
            
        • jinja2
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Jinja2 mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="jinja2.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Jinja2</a>
              </ul>
            </div>
            
            <article>
            <h2>Jinja2 mode</h2>
            <form><textarea id="code" name="code">
            {# this is a comment #}
            {%- for item in li -%}
              &lt;li&gt;{{ item.label }}&lt;/li&gt;
            {% endfor -%}
            {{ item.sand == true and item.keyword == false ? 1 : 0 }}
            {{ app.get(55, 1.2, true) }}
            {% if app.get(&#39;_route&#39;) == (&#39;_home&#39;) %}home{% endif %}
            {% if app.session.flashbag.has(&#39;message&#39;) %}
              {% for message in app.session.flashbag.get(&#39;message&#39;) %}
                {{ message.content }}
              {% endfor %}
            {% endif %}
            {{ path(&#39;_home&#39;, {&#39;section&#39;: app.request.get(&#39;section&#39;)}) }}
            {{ path(&#39;_home&#39;, {
                &#39;section&#39;: app.request.get(&#39;section&#39;),
                &#39;boolean&#39;: true,
                &#39;number&#39;: 55.33
              })
            }}
            {% include (&#39;test.incl.html.twig&#39;) %}
            </textarea></form>
                <script>
                  var editor =
                  CodeMirror.fromTextArea(document.getElementById("code"), {mode:
                    {name: "jinja2", htmlMode: true}});
                </script>
              </article>
            
          • jinja2.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("jinja2", function() {
                var keywords = ["and", "as", "block", "endblock", "by", "cycle", "debug", "else", "elif",
                  "extends", "filter", "endfilter", "firstof", "for",
                  "endfor", "if", "endif", "ifchanged", "endifchanged",
                  "ifequal", "endifequal", "ifnotequal",
                  "endifnotequal", "in", "include", "load", "not", "now", "or",
                  "parsed", "regroup", "reversed", "spaceless",
                  "endspaceless", "ssi", "templatetag", "openblock",
                  "closeblock", "openvariable", "closevariable",
                  "openbrace", "closebrace", "opencomment",
                  "closecomment", "widthratio", "url", "with", "endwith",
                  "get_current_language", "trans", "endtrans", "noop", "blocktrans",
                  "endblocktrans", "get_available_languages",
                  "get_current_language_bidi", "plural"],
                operator = /^[+\-*&%=<>!?|~^]/,
                sign = /^[:\[\(\{]/,
                atom = ["true", "false"],
                number = /^(\d[+\-\*\/])?\d+(\.\d+)?/;
            
                keywords = new RegExp("((" + keywords.join(")|(") + "))\\b");
                atom = new RegExp("((" + atom.join(")|(") + "))\\b");
            
                function tokenBase (stream, state) {
                  var ch = stream.peek();
            
                  //Comment
                  if (state.incomment) {
                    if(!stream.skipTo("#}")) {
                      stream.skipToEnd();
                    } else {
                      stream.eatWhile(/\#|}/);
                      state.incomment = false;
                    }
                    return "comment";
                  //Tag
                  } else if (state.intag) {
                    //After operator
                    if(state.operator) {
                      state.operator = false;
                      if(stream.match(atom)) {
                        return "atom";
                      }
                      if(stream.match(number)) {
                        return "number";
                      }
                    }
                    //After sign
                    if(state.sign) {
                      state.sign = false;
                      if(stream.match(atom)) {
                        return "atom";
                      }
                      if(stream.match(number)) {
                        return "number";
                      }
                    }
            
                    if(state.instring) {
                      if(ch == state.instring) {
                        state.instring = false;
                      }
                      stream.next();
                      return "string";
                    } else if(ch == "'" || ch == '"') {
                      state.instring = ch;
                      stream.next();
                      return "string";
                    } else if(stream.match(state.intag + "}") || stream.eat("-") && stream.match(state.intag + "}")) {
                      state.intag = false;
                      return "tag";
                    } else if(stream.match(operator)) {
                      state.operator = true;
                      return "operator";
                    } else if(stream.match(sign)) {
                      state.sign = true;
                    } else {
                      if(stream.eat(" ") || stream.sol()) {
                        if(stream.match(keywords)) {
                          return "keyword";
                        }
                        if(stream.match(atom)) {
                          return "atom";
                        }
                        if(stream.match(number)) {
                          return "number";
                        }
                        if(stream.sol()) {
                          stream.next();
                        }
                      } else {
                        stream.next();
                      }
            
                    }
                    return "variable";
                  } else if (stream.eat("{")) {
                    if (ch = stream.eat("#")) {
                      state.incomment = true;
                      if(!stream.skipTo("#}")) {
                        stream.skipToEnd();
                      } else {
                        stream.eatWhile(/\#|}/);
                        state.incomment = false;
                      }
                      return "comment";
                    //Open tag
                    } else if (ch = stream.eat(/\{|%/)) {
                      //Cache close tag
                      state.intag = ch;
                      if(ch == "{") {
                        state.intag = "}";
                      }
                      stream.eat("-");
                      return "tag";
                    }
                  }
                  stream.next();
                };
            
                return {
                  startState: function () {
                    return {tokenize: tokenBase};
                  },
                  token: function (stream, state) {
                    return state.tokenize(stream, state);
                  }
                };
              });
            });
            
        • julia
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Julia mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="julia.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Julia</a>
              </ul>
            </div>
            
            <article>
            <h2>Julia mode</h2>
            
                <div><textarea id="code" name="code">
            #numbers
            1234
            1234im
            .234
            .234im
            2.23im
            2.3f3
            23e2
            0x234
            
            #strings
            'a'
            "asdf"
            r"regex"
            b"bytestring"
            
            """
            multiline string
            """
            
            #identifiers
            a
            as123
            function_name!
            
            #unicode identifiers
            # a = x\ddot
            a⃗ = ẍ
            # a = v\dot
            a⃗ = v̇
            #F\vec = m \cdotp a\vec
            F⃗ = m·a⃗
            
            #literal identifier multiples
            3x
            4[1, 2, 3]
            
            #dicts and indexing
            x=[1, 2, 3]
            x[end-1]
            x={"julia"=>"language of technical computing"}
            
            
            #exception handling
            try
              f()
            catch
              @printf "Error"
            finally
              g()
            end
            
            #types
            immutable Color{T<:Number}
              r::T
              g::T
              b::T
            end
            
            #functions
            function change!(x::Vector{Float64})
              for i = 1:length(x)
                x[i] *= 2
              end
            end
            
            #function invocation
            f('b', (2, 3)...)
            
            #operators
            |=
            &=
            ^=
            \-
            %=
            *=
            +=
            -=
            <=
            >=
            !=
            ==
            %
            *
            +
            -
            <
            >
            !
            =
            |
            &
            ^
            \
            ?
            ~
            :
            $
            <:
            .<
            .>
            <<
            <<=
            >>
            >>>>
            >>=
            >>>=
            <<=
            <<<=
            .<=
            .>=
            .==
            ->
            //
            in
            ...
            //
            :=
            .//=
            .*=
            ./=
            .^=
            .%=
            .+=
            .-=
            \=
            \\=
            ||
            ===
            &&
            |=
            .|=
            <:
            >:
            |>
            <|
            ::
            x ? y : z
            
            #macros
            @spawnat 2 1+1
            @eval(:x)
            
            #keywords and operators
            if else elseif while for
             begin let end do
            try catch finally return break continue
            global local const 
            export import importall using
            function macro module baremodule 
            type immutable quote
            true false enumerate
            
            
                </textarea></div>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "julia",
                           },
                    lineNumbers: true,
                    indentUnit: 4,
                    matchBrackets: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-julia</code>.</p>
            </article>
            
          • julia.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("julia", function(_conf, parserConf) {
              var ERRORCLASS = 'error';
            
              function wordRegexp(words) {
                return new RegExp("^((" + words.join(")|(") + "))\\b");
              }
            
              var operators = parserConf.operators || /^\.?[|&^\\%*+\-<>!=\/]=?|\?|~|:|\$|\.[<>]|<<=?|>>>?=?|\.[<>=]=|->?|\/\/|\bin\b/;
              var delimiters = parserConf.delimiters || /^[;,()[\]{}]/;
              var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*!*/;
              var blockOpeners = ["begin", "function", "type", "immutable", "let", "macro", "for", "while", "quote", "if", "else", "elseif", "try", "finally", "catch", "do"];
              var blockClosers = ["end", "else", "elseif", "catch", "finally"];
              var keywordList = ['if', 'else', 'elseif', 'while', 'for', 'begin', 'let', 'end', 'do', 'try', 'catch', 'finally', 'return', 'break', 'continue', 'global', 'local', 'const', 'export', 'import', 'importall', 'using', 'function', 'macro', 'module', 'baremodule', 'type', 'immutable', 'quote', 'typealias', 'abstract', 'bitstype', 'ccall'];
              var builtinList = ['true', 'false', 'enumerate', 'open', 'close', 'nothing', 'NaN', 'Inf', 'print', 'println', 'Int', 'Int8', 'Uint8', 'Int16', 'Uint16', 'Int32', 'Uint32', 'Int64', 'Uint64', 'Int128', 'Uint128', 'Bool', 'Char', 'Float16', 'Float32', 'Float64', 'Array', 'Vector', 'Matrix', 'String', 'UTF8String', 'ASCIIString', 'error', 'warn', 'info', '@printf'];
            
              //var stringPrefixes = new RegExp("^[br]?('|\")")
              var stringPrefixes = /^(`|'|"{3}|([br]?"))/;
              var keywords = wordRegexp(keywordList);
              var builtins = wordRegexp(builtinList);
              var openers = wordRegexp(blockOpeners);
              var closers = wordRegexp(blockClosers);
              var macro = /^@[_A-Za-z][_A-Za-z0-9]*/;
              var symbol = /^:[_A-Za-z][_A-Za-z0-9]*/;
            
              function in_array(state) {
                var ch = cur_scope(state);
                if(ch=="[" || ch=="{") {
                  return true;
                }
                else {
                  return false;
                }
              }
            
              function cur_scope(state) {
                if(state.scopes.length==0) {
                  return null;
                }
                return state.scopes[state.scopes.length - 1];
              }
            
              // tokenizers
              function tokenBase(stream, state) {
                // Handle scope changes
                var leaving_expr = state.leaving_expr;
                if(stream.sol()) {
                  leaving_expr = false;
                }
                state.leaving_expr = false;
                if(leaving_expr) {
                  if(stream.match(/^'+/)) {
                    return 'operator';
                  }
            
                }
            
                if(stream.match(/^\.{2,3}/)) {
                  return 'operator';
                }
            
                if (stream.eatSpace()) {
                  return null;
                }
            
                var ch = stream.peek();
                // Handle Comments
                if (ch === '#') {
                    stream.skipToEnd();
                    return 'comment';
                }
                if(ch==='[') {
                  state.scopes.push("[");
                }
            
                if(ch==='{') {
                  state.scopes.push("{");
                }
            
                var scope=cur_scope(state);
            
                if(scope==='[' && ch===']') {
                  state.scopes.pop();
                  state.leaving_expr=true;
                }
            
                if(scope==='{' && ch==='}') {
                  state.scopes.pop();
                  state.leaving_expr=true;
                }
            
                if(ch===')') {
                  state.leaving_expr = true;
                }
            
                var match;
                if(!in_array(state) && (match=stream.match(openers, false))) {
                  state.scopes.push(match);
                }
            
                if(!in_array(state) && stream.match(closers, false)) {
                  state.scopes.pop();
                }
            
                if(in_array(state)) {
                  if(stream.match(/^end/)) {
                    return 'number';
                  }
            
                }
            
                if(stream.match(/^=>/)) {
                  return 'operator';
                }
            
            
                // Handle Number Literals
                if (stream.match(/^[0-9\.]/, false)) {
                  var imMatcher = RegExp(/^im\b/);
                  var floatLiteral = false;
                  // Floats
                  if (stream.match(/^\d*\.(?!\.)\d+([ef][\+\-]?\d+)?/i)) { floatLiteral = true; }
                  if (stream.match(/^\d+\.(?!\.)\d*/)) { floatLiteral = true; }
                  if (stream.match(/^\.\d+/)) { floatLiteral = true; }
                  if (floatLiteral) {
                      // Float literals may be "imaginary"
                      stream.match(imMatcher);
                      state.leaving_expr = true;
                      return 'number';
                  }
                  // Integers
                  var intLiteral = false;
                  // Hex
                  if (stream.match(/^0x[0-9a-f]+/i)) { intLiteral = true; }
                  // Binary
                  if (stream.match(/^0b[01]+/i)) { intLiteral = true; }
                  // Octal
                  if (stream.match(/^0o[0-7]+/i)) { intLiteral = true; }
                  // Decimal
                  if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) {
                      intLiteral = true;
                  }
                  // Zero by itself with no other piece of number.
                  if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; }
                  if (intLiteral) {
                      // Integer literals may be "long"
                      stream.match(imMatcher);
                      state.leaving_expr = true;
                      return 'number';
                  }
                }
            
                if(stream.match(/^(::)|(<:)/)) {
                  return 'operator';
                }
            
                // Handle symbols
                if(!leaving_expr && stream.match(symbol)) {
                  return 'string';
                }
            
                // Handle operators and Delimiters
                if (stream.match(operators)) {
                  return 'operator';
                }
            
            
                // Handle Strings
                if (stream.match(stringPrefixes)) {
                  state.tokenize = tokenStringFactory(stream.current());
                  return state.tokenize(stream, state);
                }
            
                if (stream.match(macro)) {
                  return 'meta';
                }
            
            
                if (stream.match(delimiters)) {
                  return null;
                }
            
                if (stream.match(keywords)) {
                  return 'keyword';
                }
            
                if (stream.match(builtins)) {
                  return 'builtin';
                }
            
            
                if (stream.match(identifiers)) {
                  state.leaving_expr=true;
                  return 'variable';
                }
                // Handle non-detected items
                stream.next();
                return ERRORCLASS;
              }
            
              function tokenStringFactory(delimiter) {
                while ('rub'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) {
                  delimiter = delimiter.substr(1);
                }
                var singleline = delimiter.length == 1;
                var OUTCLASS = 'string';
            
                function tokenString(stream, state) {
                  while (!stream.eol()) {
                    stream.eatWhile(/[^'"\\]/);
                    if (stream.eat('\\')) {
                        stream.next();
                        if (singleline && stream.eol()) {
                          return OUTCLASS;
                        }
                    } else if (stream.match(delimiter)) {
                        state.tokenize = tokenBase;
                        return OUTCLASS;
                    } else {
                        stream.eat(/['"]/);
                    }
                  }
                  if (singleline) {
                    if (parserConf.singleLineStringErrors) {
                        return ERRORCLASS;
                    } else {
                        state.tokenize = tokenBase;
                    }
                  }
                  return OUTCLASS;
                }
                tokenString.isString = true;
                return tokenString;
              }
            
              function tokenLexer(stream, state) {
                var style = state.tokenize(stream, state);
                var current = stream.current();
            
                // Handle '.' connected identifiers
                if (current === '.') {
                  style = stream.match(identifiers, false) ? null : ERRORCLASS;
                  if (style === null && state.lastStyle === 'meta') {
                      // Apply 'meta' style to '.' connected identifiers when
                      // appropriate.
                    style = 'meta';
                  }
                  return style;
                }
            
                return style;
              }
            
              var external = {
                startState: function() {
                  return {
                    tokenize: tokenBase,
                    scopes: [],
                    leaving_expr: false
                  };
                },
            
                token: function(stream, state) {
                  var style = tokenLexer(stream, state);
                  state.lastStyle = style;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var delta = 0;
                  if(textAfter=="end" || textAfter=="]" || textAfter=="}" || textAfter=="else" || textAfter=="elseif" || textAfter=="catch" || textAfter=="finally") {
                    delta = -1;
                  }
                  return (state.scopes.length + delta) * 4;
                },
            
                lineComment: "#",
                fold: "indent",
                electricChars: "edlsifyh]}"
              };
              return external;
            });
            
            
            CodeMirror.defineMIME("text/x-julia", "julia");
            
            });
            
        • kotlin
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Kotlin mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="kotlin.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Kotlin</a>
              </ul>
            </div>
            
            <article>
            <h2>Kotlin mode</h2>
            
            
            <div><textarea id="code" name="code">
            package org.wasabi.http
            
            import java.util.concurrent.Executors
            import java.net.InetSocketAddress
            import org.wasabi.app.AppConfiguration
            import io.netty.bootstrap.ServerBootstrap
            import io.netty.channel.nio.NioEventLoopGroup
            import io.netty.channel.socket.nio.NioServerSocketChannel
            import org.wasabi.app.AppServer
            
            public class HttpServer(private val appServer: AppServer) {
            
                val bootstrap: ServerBootstrap
                val primaryGroup: NioEventLoopGroup
                val workerGroup:  NioEventLoopGroup
            
                {
                    // Define worker groups
                    primaryGroup = NioEventLoopGroup()
                    workerGroup = NioEventLoopGroup()
            
                    // Initialize bootstrap of server
                    bootstrap = ServerBootstrap()
            
                    bootstrap.group(primaryGroup, workerGroup)
                    bootstrap.channel(javaClass<NioServerSocketChannel>())
                    bootstrap.childHandler(NettyPipelineInitializer(appServer))
                }
            
                public fun start(wait: Boolean = true) {
                    val channel = bootstrap.bind(appServer.configuration.port)?.sync()?.channel()
            
                    if (wait) {
                        channel?.closeFuture()?.sync()
                    }
                }
            
                public fun stop() {
                    // Shutdown all event loops
                    primaryGroup.shutdownGracefully()
                    workerGroup.shutdownGracefully()
            
                    // Wait till all threads are terminated
                    primaryGroup.terminationFuture().sync()
                    workerGroup.terminationFuture().sync()
                }
            }
            </textarea></div>
            
                <script>
                    var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                        mode: {name: "kotlin"},
                        lineNumbers: true,
                        indentUnit: 4
                    });
                </script>
                <h3>Mode for Kotlin (http://kotlin.jetbrains.org/)</h3>
                <p>Developed by Hadi Hariri (https://github.com/hhariri).</p>
                <p><strong>MIME type defined:</strong> <code>text/x-kotlin</code>.</p>
            </article>
            
          • kotlin.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("kotlin", function (config, parserConfig) {
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              var multiLineStrings = parserConfig.multiLineStrings;
            
              var keywords = words(
                      "package continue return object while break class data trait throw super" +
                      " when type this else This try val var fun for is in if do as true false null get set");
              var softKeywords = words("import" +
                  " where by get set abstract enum open annotation override private public internal" +
                  " protected catch out vararg inline finally final ref");
              var blockKeywords = words("catch class do else finally for if where try while enum");
              var atoms = words("null true false this");
            
              var curPunc;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"' || ch == "'") {
                  return startString(ch, stream, state);
                }
                // Wildcard import w/o trailing semicolon (import smth.*)
                if (ch == "." && stream.eat("*")) {
                  return "word";
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                if (/\d/.test(ch)) {
                  if (stream.eat(/eE/)) {
                    stream.eat(/\+\-/);
                    stream.eatWhile(/\d/);
                  }
                  return "number";
                }
                if (ch == "/") {
                  if (stream.eat("*")) {
                    state.tokenize.push(tokenComment);
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                  if (expectExpression(state.lastToken)) {
                    return startString(ch, stream, state);
                  }
                }
                // Commented
                if (ch == "-" && stream.eat(">")) {
                  curPunc = "->";
                  return null;
                }
                if (/[\-+*&%=<>!?|\/~]/.test(ch)) {
                  stream.eatWhile(/[\-+*&%=<>|~]/);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_]/);
            
                var cur = stream.current();
                if (atoms.propertyIsEnumerable(cur)) {
                  return "atom";
                }
                if (softKeywords.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "softKeyword";
                }
            
                if (keywords.propertyIsEnumerable(cur)) {
                  if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
                  return "keyword";
                }
                return "word";
              }
            
              tokenBase.isBase = true;
            
              function startString(quote, stream, state) {
                var tripleQuoted = false;
                if (quote != "/" && stream.eat(quote)) {
                  if (stream.eat(quote)) tripleQuoted = true;
                  else return "string";
                }
                function t(stream, state) {
                  var escaped = false, next, end = !tripleQuoted;
            
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {
                      if (!tripleQuoted) {
                        break;
                      }
                      if (stream.match(quote + quote)) {
                        end = true;
                        break;
                      }
                    }
            
                    if (quote == '"' && next == "$" && !escaped && stream.eat("{")) {
                      state.tokenize.push(tokenBaseUntilBrace());
                      return "string";
                    }
            
                    if (next == "$" && !escaped && !stream.eat(" ")) {
                      state.tokenize.push(tokenBaseUntilSpace());
                      return "string";
                    }
                    escaped = !escaped && next == "\\";
                  }
                  if (multiLineStrings)
                    state.tokenize.push(t);
                  if (end) state.tokenize.pop();
                  return "string";
                }
            
                state.tokenize.push(t);
                return t(stream, state);
              }
            
              function tokenBaseUntilBrace() {
                var depth = 1;
            
                function t(stream, state) {
                  if (stream.peek() == "}") {
                    depth--;
                    if (depth == 0) {
                      state.tokenize.pop();
                      return state.tokenize[state.tokenize.length - 1](stream, state);
                    }
                  } else if (stream.peek() == "{") {
                    depth++;
                  }
                  return tokenBase(stream, state);
                }
            
                t.isBase = true;
                return t;
              }
            
              function tokenBaseUntilSpace() {
                function t(stream, state) {
                  if (stream.eat(/[\w]/)) {
                    var isWord = stream.eatWhile(/[\w]/);
                    if (isWord) {
                      state.tokenize.pop();
                      return "word";
                    }
                  }
                  state.tokenize.pop();
                  return "string";
                }
            
                t.isBase = true;
                return t;
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize.pop();
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function expectExpression(last) {
                return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) ||
                    last == "newstatement" || last == "keyword" || last == "proplabel";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
            
              function pushContext(state, col, type) {
                return state.context = new Context(state.indented, col, type, null, state.context);
              }
            
              function popContext(state) {
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}")
                  state.indented = state.context.indented;
                return state.context = state.context.prev;
              }
            
              // Interface
            
              return {
                startState: function (basecolumn) {
                  return {
                    tokenize: [tokenBase],
                    context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true,
                    lastToken: null
                  };
                },
            
                token: function (stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                    // Automatic semicolon insertion
                    if (ctx.type == "statement" && !expectExpression(state.lastToken)) {
                      popContext(state);
                      ctx = state.context;
                    }
                  }
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  var style = state.tokenize[state.tokenize.length - 1](stream, state);
                  if (style == "comment") return style;
                  if (ctx.align == null) ctx.align = true;
                  if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
                  // Handle indentation for {x -> \n ... }
                  else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") {
                    popContext(state);
                    state.context.align = false;
                  }
                  else if (curPunc == "{") pushContext(state, stream.column(), "}");
                  else if (curPunc == "[") pushContext(state, stream.column(), "]");
                  else if (curPunc == "(") pushContext(state, stream.column(), ")");
                  else if (curPunc == "}") {
                    while (ctx.type == "statement") ctx = popContext(state);
                    if (ctx.type == "}") ctx = popContext(state);
                    while (ctx.type == "statement") ctx = popContext(state);
                  }
                  else if (curPunc == ctx.type) popContext(state);
                  else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
                    pushContext(state, stream.column(), "statement");
                  state.startOfLine = false;
                  state.lastToken = curPunc || style;
                  return style;
                },
            
                indent: function (state, textAfter) {
                  if (!state.tokenize[state.tokenize.length - 1].isBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;
                  if (ctx.type == "statement" && !expectExpression(state.lastToken)) ctx = ctx.prev;
                  var closing = firstChar == ctx.type;
                  if (ctx.type == "statement") {
                    return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit);
                  }
                  else if (ctx.align) return ctx.column + (closing ? 0 : 1);
                  else return ctx.indented + (closing ? 0 : config.indentUnit);
                },
            
                closeBrackets: {triples: "'\""},
                electricChars: "{}"
              };
            });
            
            CodeMirror.defineMIME("text/x-kotlin", "kotlin");
            
            });
            
        • livescript
          • index.html
            <!doctype html>
            
            <title>CodeMirror: LiveScript mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/solarized.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="livescript.js"></script>
            <style>.CodeMirror {font-size: 80%;border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">LiveScript</a>
              </ul>
            </div>
            
            <article>
            <h2>LiveScript mode</h2>
            <form><textarea id="code" name="code">
            # LiveScript mode for CodeMirror
            # The following script, prelude.ls, is used to
            # demonstrate LiveScript mode for CodeMirror.
            #   https://github.com/gkz/prelude-ls
            
            export objToFunc = objToFunc = (obj) ->
              (key) -> obj[key]
            
            export each = (f, xs) -->
              if typeof! xs is \Object
                for , x of xs then f x
              else
                for x in xs then f x
              xs
            
            export map = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              type = typeof! xs
              if type is \Object
                {[key, f x] for key, x of xs}
              else
                result = [f x for x in xs]
                if type is \String then result * '' else result
            
            export filter = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              type = typeof! xs
              if type is \Object
                {[key, x] for key, x of xs when f x}
              else
                result = [x for x in xs when f x]
                if type is \String then result * '' else result
            
            export reject = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              type = typeof! xs
              if type is \Object
                {[key, x] for key, x of xs when not f x}
              else
                result = [x for x in xs when not f x]
                if type is \String then result * '' else result
            
            export partition = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              type = typeof! xs
              if type is \Object
                passed = {}
                failed = {}
                for key, x of xs
                  (if f x then passed else failed)[key] = x
              else
                passed = []
                failed = []
                for x in xs
                  (if f x then passed else failed)push x
                if type is \String
                  passed *= ''
                  failed *= ''
              [passed, failed]
            
            export find = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              if typeof! xs is \Object
                for , x of xs when f x then return x
              else
                for x in xs when f x then return x
              void
            
            export head = export first = (xs) ->
              return void if not xs.length
              xs.0
            
            export tail = (xs) ->
              return void if not xs.length
              xs.slice 1
            
            export last = (xs) ->
              return void if not xs.length
              xs[*-1]
            
            export initial = (xs) ->
              return void if not xs.length
              xs.slice 0 xs.length - 1
            
            export empty = (xs) ->
              if typeof! xs is \Object
                for x of xs then return false
                return yes
              not xs.length
            
            export values = (obj) ->
              [x for , x of obj]
            
            export keys = (obj) ->
              [x for x of obj]
            
            export len = (xs) ->
              xs = values xs if typeof! xs is \Object
              xs.length
            
            export cons = (x, xs) -->
              if typeof! xs is \String then x + xs else [x] ++ xs
            
            export append = (xs, ys) -->
              if typeof! ys is \String then xs + ys else xs ++ ys
            
            export join = (sep, xs) -->
              xs = values xs if typeof! xs is \Object
              xs.join sep
            
            export reverse = (xs) ->
              if typeof! xs is \String
              then (xs / '')reverse! * ''
              else xs.slice!reverse!
            
            export fold = export foldl = (f, memo, xs) -->
              if typeof! xs is \Object
                for , x of xs then memo = f memo, x
              else
                for x in xs then memo = f memo, x
              memo
            
            export fold1 = export foldl1 = (f, xs) --> fold f, xs.0, xs.slice 1
            
            export foldr = (f, memo, xs) --> fold f, memo, xs.slice!reverse!
            
            export foldr1 = (f, xs) -->
              xs.=slice!reverse!
              fold f, xs.0, xs.slice 1
            
            export unfoldr = export unfold = (f, b) -->
              if (f b)?
                [that.0] ++ unfoldr f, that.1
              else
                []
            
            export andList = (xs) ->
              for x in xs when not x
                return false
              true
            
            export orList = (xs) ->
              for x in xs when x
                return true
              false
            
            export any = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              for x in xs when f x
                return yes
              no
            
            export all = (f, xs) -->
              f = objToFunc f if typeof! f isnt \Function
              for x in xs when not f x
                return no
              yes
            
            export unique = (xs) ->
              result = []
              if typeof! xs is \Object
                for , x of xs when x not in result then result.push x
              else
                for x   in xs when x not in result then result.push x
              if typeof! xs is \String then result * '' else result
            
            export sort = (xs) ->
              xs.concat!sort (x, y) ->
                | x > y =>  1
                | x < y => -1
                | _     =>  0
            
            export sortBy = (f, xs) -->
              return [] unless xs.length
              xs.concat!sort f
            
            export compare = (f, x, y) -->
              | (f x) > (f y) =>  1
              | (f x) < (f y) => -1
              | otherwise     =>  0
            
            export sum = (xs) ->
              result = 0
              if typeof! xs is \Object
                for , x of xs then result += x
              else
                for x   in xs then result += x
              result
            
            export product = (xs) ->
              result = 1
              if typeof! xs is \Object
                for , x of xs then result *= x
              else
                for x   in xs then result *= x
              result
            
            export mean = export average = (xs) -> (sum xs) / len xs
            
            export concat = (xss) -> fold append, [], xss
            
            export concatMap = (f, xs) --> fold ((memo, x) -> append memo, f x), [], xs
            
            export listToObj = (xs) ->
              {[x.0, x.1] for x in xs}
            
            export maximum = (xs) -> fold1 (>?), xs
            
            export minimum = (xs) -> fold1 (<?), xs
            
            export scan = export scanl = (f, memo, xs) -->
              last = memo
              if typeof! xs is \Object
              then [memo] ++ [last = f last, x for , x of xs]
              else [memo] ++ [last = f last, x for x in xs]
            
            export scan1 = export scanl1 = (f, xs) --> scan f, xs.0, xs.slice 1
            
            export scanr = (f, memo, xs) -->
              xs.=slice!reverse!
              scan f, memo, xs .reverse!
            
            export scanr1 = (f, xs) -->
              xs.=slice!reverse!
              scan f, xs.0, xs.slice 1 .reverse!
            
            export replicate = (n, x) -->
              result = []
              i = 0
              while i < n, ++i then result.push x
              result
            
            export take = (n, xs) -->
              | n <= 0
                if typeof! xs is \String then '' else []
              | not xs.length => xs
              | otherwise     => xs.slice 0, n
            
            export drop = (n, xs) -->
              | n <= 0        => xs
              | not xs.length => xs
              | otherwise     => xs.slice n
            
            export splitAt = (n, xs) --> [(take n, xs), (drop n, xs)]
            
            export takeWhile = (p, xs) -->
              return xs if not xs.length
              p = objToFunc p if typeof! p isnt \Function
              result = []
              for x in xs
                break if not p x
                result.push x
              if typeof! xs is \String then result * '' else result
            
            export dropWhile = (p, xs) -->
              return xs if not xs.length
              p = objToFunc p if typeof! p isnt \Function
              i = 0
              for x in xs
                break if not p x
                ++i
              drop i, xs
            
            export span = (p, xs) --> [(takeWhile p, xs), (dropWhile p, xs)]
            
            export breakIt = (p, xs) --> span (not) << p, xs
            
            export zip = (xs, ys) -->
              result = []
              for zs, i in [xs, ys]
                for z, j in zs
                  result.push [] if i is 0
                  result[j]?push z
              result
            
            export zipWith = (f,xs, ys) -->
              f = objToFunc f if typeof! f isnt \Function
              if not xs.length or not ys.length
                []
              else
                [f.apply this, zs for zs in zip.call this, xs, ys]
            
            export zipAll = (...xss) ->
              result = []
              for xs, i in xss
                for x, j in xs
                  result.push [] if i is 0
                  result[j]?push x
              result
            
            export zipAllWith = (f, ...xss) ->
              f = objToFunc f if typeof! f isnt \Function
              if not xss.0.length or not xss.1.length
                []
              else
                [f.apply this, xs for xs in zipAll.apply this, xss]
            
            export compose = (...funcs) ->
              ->
                args = arguments
                for f in funcs
                  args = [f.apply this, args]
                args.0
            
            export curry = (f) ->
              curry$ f # using util method curry$ from livescript
            
            export id = (x) -> x
            
            export flip = (f, x, y) --> f y, x
            
            export fix = (f) ->
              ( (g, x) -> -> f(g g) ...arguments ) do
                (g, x) -> -> f(g g) ...arguments
            
            export lines = (str) ->
              return [] if not str.length
              str / \\n
            
            export unlines = (strs) -> strs * \\n
            
            export words = (str) ->
              return [] if not str.length
              str / /[ ]+/
            
            export unwords = (strs) -> strs * ' '
            
            export max = (>?)
            
            export min = (<?)
            
            export negate = (x) -> -x
            
            export abs = Math.abs
            
            export signum = (x) ->
              | x < 0     => -1
              | x > 0     =>  1
              | otherwise =>  0
            
            export quot = (x, y) --> ~~(x / y)
            
            export rem = (%)
            
            export div = (x, y) --> Math.floor x / y
            
            export mod = (%%)
            
            export recip = (1 /)
            
            export pi = Math.PI
            
            export tau = pi * 2
            
            export exp = Math.exp
            
            export sqrt = Math.sqrt
            
            # changed from log as log is a
            # common function for logging things
            export ln = Math.log
            
            export pow = (^)
            
            export sin = Math.sin
            
            export tan = Math.tan
            
            export cos = Math.cos
            
            export asin = Math.asin
            
            export acos = Math.acos
            
            export atan = Math.atan
            
            export atan2 = (x, y) --> Math.atan2 x, y
            
            # sinh
            # tanh
            # cosh
            # asinh
            # atanh
            # acosh
            
            export truncate = (x) -> ~~x
            
            export round = Math.round
            
            export ceiling = Math.ceil
            
            export floor = Math.floor
            
            export isItNaN = (x) -> x isnt x
            
            export even = (x) -> x % 2 == 0
            
            export odd = (x) -> x % 2 != 0
            
            export gcd = (x, y) -->
              x = Math.abs x
              y = Math.abs y
              until y is 0
                z = x % y
                x = y
                y = z
              x
            
            export lcm = (x, y) -->
              Math.abs Math.floor (x / (gcd x, y) * y)
            
            # meta
            export installPrelude = !(target) ->
              unless target.prelude?isInstalled
                target <<< out$ # using out$ generated by livescript
                target <<< target.prelude.isInstalled = true
            
            export prelude = out$
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    theme: "solarized light",
                    lineNumbers: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-livescript</code>.</p>
            
                <p>The LiveScript mode was written by Kenneth Bentley.</p>
            
              </article>
            
          • livescript.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Link to the project's GitHub page:
             * https://github.com/duralog/CodeMirror
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode('livescript', function(){
                var tokenBase = function(stream, state) {
                  var next_rule = state.next || "start";
                  if (next_rule) {
                    state.next = state.next;
                    var nr = Rules[next_rule];
                    if (nr.splice) {
                      for (var i$ = 0; i$ < nr.length; ++i$) {
                        var r = nr[i$];
                        if (r.regex && stream.match(r.regex)) {
                          state.next = r.next || state.next;
                          return r.token;
                        }
                      }
                      stream.next();
                      return 'error';
                    }
                    if (stream.match(r = Rules[next_rule])) {
                      if (r.regex && stream.match(r.regex)) {
                        state.next = r.next;
                        return r.token;
                      } else {
                        stream.next();
                        return 'error';
                      }
                    }
                  }
                  stream.next();
                  return 'error';
                };
                var external = {
                  startState: function(){
                    return {
                      next: 'start',
                      lastToken: null
                    };
                  },
                  token: function(stream, state){
                    while (stream.pos == stream.start)
                      var style = tokenBase(stream, state);
                    state.lastToken = {
                      style: style,
                      indent: stream.indentation(),
                      content: stream.current()
                    };
                    return style.replace(/\./g, ' ');
                  },
                  indent: function(state){
                    var indentation = state.lastToken.indent;
                    if (state.lastToken.content.match(indenter)) {
                      indentation += 2;
                    }
                    return indentation;
                  }
                };
                return external;
              });
            
              var identifier = '(?![\\d\\s])[$\\w\\xAA-\\uFFDC](?:(?!\\s)[$\\w\\xAA-\\uFFDC]|-[A-Za-z])*';
              var indenter = RegExp('(?:[({[=:]|[-~]>|\\b(?:e(?:lse|xport)|d(?:o|efault)|t(?:ry|hen)|finally|import(?:\\s*all)?|const|var|let|new|catch(?:\\s*' + identifier + ')?))\\s*$');
              var keywordend = '(?![$\\w]|-[A-Za-z]|\\s*:(?![:=]))';
              var stringfill = {
                token: 'string',
                regex: '.+'
              };
              var Rules = {
                start: [
                  {
                    token: 'comment.doc',
                    regex: '/\\*',
                    next: 'comment'
                  }, {
                    token: 'comment',
                    regex: '#.*'
                  }, {
                    token: 'keyword',
                    regex: '(?:t(?:h(?:is|row|en)|ry|ypeof!?)|c(?:on(?:tinue|st)|a(?:se|tch)|lass)|i(?:n(?:stanceof)?|mp(?:ort(?:\\s+all)?|lements)|[fs])|d(?:e(?:fault|lete|bugger)|o)|f(?:or(?:\\s+own)?|inally|unction)|s(?:uper|witch)|e(?:lse|x(?:tends|port)|val)|a(?:nd|rguments)|n(?:ew|ot)|un(?:less|til)|w(?:hile|ith)|o[fr]|return|break|let|var|loop)' + keywordend
                  }, {
                    token: 'constant.language',
                    regex: '(?:true|false|yes|no|on|off|null|void|undefined)' + keywordend
                  }, {
                    token: 'invalid.illegal',
                    regex: '(?:p(?:ackage|r(?:ivate|otected)|ublic)|i(?:mplements|nterface)|enum|static|yield)' + keywordend
                  }, {
                    token: 'language.support.class',
                    regex: '(?:R(?:e(?:gExp|ferenceError)|angeError)|S(?:tring|yntaxError)|E(?:rror|valError)|Array|Boolean|Date|Function|Number|Object|TypeError|URIError)' + keywordend
                  }, {
                    token: 'language.support.function',
                    regex: '(?:is(?:NaN|Finite)|parse(?:Int|Float)|Math|JSON|(?:en|de)codeURI(?:Component)?)' + keywordend
                  }, {
                    token: 'variable.language',
                    regex: '(?:t(?:hat|il|o)|f(?:rom|allthrough)|it|by|e)' + keywordend
                  }, {
                    token: 'identifier',
                    regex: identifier + '\\s*:(?![:=])'
                  }, {
                    token: 'variable',
                    regex: identifier
                  }, {
                    token: 'keyword.operator',
                    regex: '(?:\\.{3}|\\s+\\?)'
                  }, {
                    token: 'keyword.variable',
                    regex: '(?:@+|::|\\.\\.)',
                    next: 'key'
                  }, {
                    token: 'keyword.operator',
                    regex: '\\.\\s*',
                    next: 'key'
                  }, {
                    token: 'string',
                    regex: '\\\\\\S[^\\s,;)}\\]]*'
                  }, {
                    token: 'string.doc',
                    regex: '\'\'\'',
                    next: 'qdoc'
                  }, {
                    token: 'string.doc',
                    regex: '"""',
                    next: 'qqdoc'
                  }, {
                    token: 'string',
                    regex: '\'',
                    next: 'qstring'
                  }, {
                    token: 'string',
                    regex: '"',
                    next: 'qqstring'
                  }, {
                    token: 'string',
                    regex: '`',
                    next: 'js'
                  }, {
                    token: 'string',
                    regex: '<\\[',
                    next: 'words'
                  }, {
                    token: 'string.regex',
                    regex: '//',
                    next: 'heregex'
                  }, {
                    token: 'string.regex',
                    regex: '\\/(?:[^[\\/\\n\\\\]*(?:(?:\\\\.|\\[[^\\]\\n\\\\]*(?:\\\\.[^\\]\\n\\\\]*)*\\])[^[\\/\\n\\\\]*)*)\\/[gimy$]{0,4}',
                    next: 'key'
                  }, {
                    token: 'constant.numeric',
                    regex: '(?:0x[\\da-fA-F][\\da-fA-F_]*|(?:[2-9]|[12]\\d|3[0-6])r[\\da-zA-Z][\\da-zA-Z_]*|(?:\\d[\\d_]*(?:\\.\\d[\\d_]*)?|\\.\\d[\\d_]*)(?:e[+-]?\\d[\\d_]*)?[\\w$]*)'
                  }, {
                    token: 'lparen',
                    regex: '[({[]'
                  }, {
                    token: 'rparen',
                    regex: '[)}\\]]',
                    next: 'key'
                  }, {
                    token: 'keyword.operator',
                    regex: '\\S+'
                  }, {
                    token: 'text',
                    regex: '\\s+'
                  }
                ],
                heregex: [
                  {
                    token: 'string.regex',
                    regex: '.*?//[gimy$?]{0,4}',
                    next: 'start'
                  }, {
                    token: 'string.regex',
                    regex: '\\s*#{'
                  }, {
                    token: 'comment.regex',
                    regex: '\\s+(?:#.*)?'
                  }, {
                    token: 'string.regex',
                    regex: '\\S+'
                  }
                ],
                key: [
                  {
                    token: 'keyword.operator',
                    regex: '[.?@!]+'
                  }, {
                    token: 'identifier',
                    regex: identifier,
                    next: 'start'
                  }, {
                    token: 'text',
                    regex: '',
                    next: 'start'
                  }
                ],
                comment: [
                  {
                    token: 'comment.doc',
                    regex: '.*?\\*/',
                    next: 'start'
                  }, {
                    token: 'comment.doc',
                    regex: '.+'
                  }
                ],
                qdoc: [
                  {
                    token: 'string',
                    regex: ".*?'''",
                    next: 'key'
                  }, stringfill
                ],
                qqdoc: [
                  {
                    token: 'string',
                    regex: '.*?"""',
                    next: 'key'
                  }, stringfill
                ],
                qstring: [
                  {
                    token: 'string',
                    regex: '[^\\\\\']*(?:\\\\.[^\\\\\']*)*\'',
                    next: 'key'
                  }, stringfill
                ],
                qqstring: [
                  {
                    token: 'string',
                    regex: '[^\\\\"]*(?:\\\\.[^\\\\"]*)*"',
                    next: 'key'
                  }, stringfill
                ],
                js: [
                  {
                    token: 'string',
                    regex: '[^\\\\`]*(?:\\\\.[^\\\\`]*)*`',
                    next: 'key'
                  }, stringfill
                ],
                words: [
                  {
                    token: 'string',
                    regex: '.*?\\]>',
                    next: 'key'
                  }, stringfill
                ]
              };
              for (var idx in Rules) {
                var r = Rules[idx];
                if (r.splice) {
                  for (var i = 0, len = r.length; i < len; ++i) {
                    var rr = r[i];
                    if (typeof rr.regex === 'string') {
                      Rules[idx][i].regex = new RegExp('^' + rr.regex);
                    }
                  }
                } else if (typeof rr.regex === 'string') {
                  Rules[idx].regex = new RegExp('^' + r.regex);
                }
              }
            
              CodeMirror.defineMIME('text/x-livescript', 'livescript');
            
            });
            
        • lua
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Lua mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/neat.css">
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="../../lib/codemirror.js"></script>
            <script src="lua.js"></script>
            <style>.CodeMirror {border: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Lua</a>
              </ul>
            </div>
            
            <article>
            <h2>Lua mode</h2>
            <form><textarea id="code" name="code">
            --[[
            example useless code to show lua syntax highlighting
            this is multiline comment
            ]]
            
            function blahblahblah(x)
            
              local table = {
                "asd" = 123,
                "x" = 0.34,  
              }
              if x ~= 3 then
                print( x )
              elseif x == "string"
                my_custom_function( 0x34 )
              else
                unknown_function( "some string" )
              end
            
              --single line comment
              
            end
            
            function blablabla3()
            
              for k,v in ipairs( table ) do
                --abcde..
                y=[=[
              x=[[
                  x is a multi line string
               ]]
              but its definition is iside a highest level string!
              ]=]
                print(" \"\" ")
            
                s = math.sin( x )
              end
            
            end
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    matchBrackets: true,
                    theme: "neat"
                  });
                </script>
            
                <p>Loosely based on Franciszek
                Wawrzak's <a href="http://codemirror.net/1/contrib/lua">CodeMirror
                1 mode</a>. One configuration parameter is
                supported, <code>specials</code>, to which you can provide an
                array of strings to have those identifiers highlighted with
                the <code>lua-special</code> style.</p>
                <p><strong>MIME types defined:</strong> <code>text/x-lua</code>.</p>
            
              </article>
            
          • lua.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's
            // CodeMirror 1 mode.
            // highlights keywords, strings, comments (no leveling supported! ("[==[")), tokens, basic indenting
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("lua", function(config, parserConfig) {
              var indentUnit = config.indentUnit;
            
              function prefixRE(words) {
                return new RegExp("^(?:" + words.join("|") + ")", "i");
              }
              function wordRE(words) {
                return new RegExp("^(?:" + words.join("|") + ")$", "i");
              }
              var specials = wordRE(parserConfig.specials || []);
            
              // long list of standard functions from lua manual
              var builtins = wordRE([
                "_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load",
                "loadfile","loadstring","module","next","pairs","pcall","print","rawequal","rawget","rawset","require",
                "select","setfenv","setmetatable","tonumber","tostring","type","unpack","xpcall",
            
                "coroutine.create","coroutine.resume","coroutine.running","coroutine.status","coroutine.wrap","coroutine.yield",
            
                "debug.debug","debug.getfenv","debug.gethook","debug.getinfo","debug.getlocal","debug.getmetatable",
                "debug.getregistry","debug.getupvalue","debug.setfenv","debug.sethook","debug.setlocal","debug.setmetatable",
                "debug.setupvalue","debug.traceback",
            
                "close","flush","lines","read","seek","setvbuf","write",
            
                "io.close","io.flush","io.input","io.lines","io.open","io.output","io.popen","io.read","io.stderr","io.stdin",
                "io.stdout","io.tmpfile","io.type","io.write",
            
                "math.abs","math.acos","math.asin","math.atan","math.atan2","math.ceil","math.cos","math.cosh","math.deg",
                "math.exp","math.floor","math.fmod","math.frexp","math.huge","math.ldexp","math.log","math.log10","math.max",
                "math.min","math.modf","math.pi","math.pow","math.rad","math.random","math.randomseed","math.sin","math.sinh",
                "math.sqrt","math.tan","math.tanh",
            
                "os.clock","os.date","os.difftime","os.execute","os.exit","os.getenv","os.remove","os.rename","os.setlocale",
                "os.time","os.tmpname",
            
                "package.cpath","package.loaded","package.loaders","package.loadlib","package.path","package.preload",
                "package.seeall",
            
                "string.byte","string.char","string.dump","string.find","string.format","string.gmatch","string.gsub",
                "string.len","string.lower","string.match","string.rep","string.reverse","string.sub","string.upper",
            
                "table.concat","table.insert","table.maxn","table.remove","table.sort"
              ]);
              var keywords = wordRE(["and","break","elseif","false","nil","not","or","return",
                                     "true","function", "end", "if", "then", "else", "do",
                                     "while", "repeat", "until", "for", "in", "local" ]);
            
              var indentTokens = wordRE(["function", "if","repeat","do", "\\(", "{"]);
              var dedentTokens = wordRE(["end", "until", "\\)", "}"]);
              var dedentPartial = prefixRE(["end", "until", "\\)", "}", "else", "elseif"]);
            
              function readBracket(stream) {
                var level = 0;
                while (stream.eat("=")) ++level;
                stream.eat("[");
                return level;
              }
            
              function normal(stream, state) {
                var ch = stream.next();
                if (ch == "-" && stream.eat("-")) {
                  if (stream.eat("[") && stream.eat("["))
                    return (state.cur = bracketed(readBracket(stream), "comment"))(stream, state);
                  stream.skipToEnd();
                  return "comment";
                }
                if (ch == "\"" || ch == "'")
                  return (state.cur = string(ch))(stream, state);
                if (ch == "[" && /[\[=]/.test(stream.peek()))
                  return (state.cur = bracketed(readBracket(stream), "string"))(stream, state);
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w.%]/);
                  return "number";
                }
                if (/[\w_]/.test(ch)) {
                  stream.eatWhile(/[\w\\\-_.]/);
                  return "variable";
                }
                return null;
              }
            
              function bracketed(level, style) {
                return function(stream, state) {
                  var curlev = null, ch;
                  while ((ch = stream.next()) != null) {
                    if (curlev == null) {if (ch == "]") curlev = 0;}
                    else if (ch == "=") ++curlev;
                    else if (ch == "]" && curlev == level) { state.cur = normal; break; }
                    else curlev = null;
                  }
                  return style;
                };
              }
            
              function string(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped) break;
                    escaped = !escaped && ch == "\\";
                  }
                  if (!escaped) state.cur = normal;
                  return "string";
                };
              }
            
              return {
                startState: function(basecol) {
                  return {basecol: basecol || 0, indentDepth: 0, cur: normal};
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  var style = state.cur(stream, state);
                  var word = stream.current();
                  if (style == "variable") {
                    if (keywords.test(word)) style = "keyword";
                    else if (builtins.test(word)) style = "builtin";
                    else if (specials.test(word)) style = "variable-2";
                  }
                  if ((style != "comment") && (style != "string")){
                    if (indentTokens.test(word)) ++state.indentDepth;
                    else if (dedentTokens.test(word)) --state.indentDepth;
                  }
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var closing = dedentPartial.test(textAfter);
                  return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0));
                },
            
                lineComment: "--",
                blockCommentStart: "--[[",
                blockCommentEnd: "]]"
              };
            });
            
            CodeMirror.defineMIME("text/x-lua", "lua");
            
            });
            
        • markdown
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Markdown mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/continuelist.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="markdown.js"></script>
            <style type="text/css">
                  .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                  .cm-s-default .cm-trailing-space-a:before,
                  .cm-s-default .cm-trailing-space-b:before {position: absolute; content: "\00B7"; color: #777;}
                  .cm-s-default .cm-trailing-space-new-line:before {position: absolute; content: "\21B5"; color: #777;}
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Markdown</a>
              </ul>
            </div>
            
            <article>
            <h2>Markdown mode</h2>
            <form><textarea id="code" name="code">
            Markdown: Basics
            ================
            
            &lt;ul id="ProjectSubmenu"&gt;
                &lt;li&gt;&lt;a href="/projects/markdown/" title="Markdown Project Page"&gt;Main&lt;/a&gt;&lt;/li&gt;
                &lt;li&gt;&lt;a class="selected" title="Markdown Basics"&gt;Basics&lt;/a&gt;&lt;/li&gt;
                &lt;li&gt;&lt;a href="/projects/markdown/syntax" title="Markdown Syntax Documentation"&gt;Syntax&lt;/a&gt;&lt;/li&gt;
                &lt;li&gt;&lt;a href="/projects/markdown/license" title="Pricing and License Information"&gt;License&lt;/a&gt;&lt;/li&gt;
                &lt;li&gt;&lt;a href="/projects/markdown/dingus" title="Online Markdown Web Form"&gt;Dingus&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
            
            
            Getting the Gist of Markdown's Formatting Syntax
            ------------------------------------------------
            
            This page offers a brief overview of what it's like to use Markdown.
            The [syntax page] [s] provides complete, detailed documentation for
            every feature, but Markdown should be very easy to pick up simply by
            looking at a few examples of it in action. The examples on this page
            are written in a before/after style, showing example syntax and the
            HTML output produced by Markdown.
            
            It's also helpful to simply try Markdown out; the [Dingus] [d] is a
            web application that allows you type your own Markdown-formatted text
            and translate it to XHTML.
            
            **Note:** This document is itself written using Markdown; you
            can [see the source for it by adding '.text' to the URL] [src].
            
              [s]: /projects/markdown/syntax  "Markdown Syntax"
              [d]: /projects/markdown/dingus  "Markdown Dingus"
              [src]: /projects/markdown/basics.text
            
            
            ## Paragraphs, Headers, Blockquotes ##
            
            A paragraph is simply one or more consecutive lines of text, separated
            by one or more blank lines. (A blank line is any line that looks like
            a blank line -- a line containing nothing but spaces or tabs is
            considered blank.) Normal paragraphs should not be indented with
            spaces or tabs.
            
            Markdown offers two styles of headers: *Setext* and *atx*.
            Setext-style headers for `&lt;h1&gt;` and `&lt;h2&gt;` are created by
            "underlining" with equal signs (`=`) and hyphens (`-`), respectively.
            To create an atx-style header, you put 1-6 hash marks (`#`) at the
            beginning of the line -- the number of hashes equals the resulting
            HTML header level.
            
            Blockquotes are indicated using email-style '`&gt;`' angle brackets.
            
            Markdown:
            
                A First Level Header
                ====================
                
                A Second Level Header
                ---------------------
            
                Now is the time for all good men to come to
                the aid of their country. This is just a
                regular paragraph.
            
                The quick brown fox jumped over the lazy
                dog's back.
                
                ### Header 3
            
                &gt; This is a blockquote.
                &gt; 
                &gt; This is the second paragraph in the blockquote.
                &gt;
                &gt; ## This is an H2 in a blockquote
            
            
            Output:
            
                &lt;h1&gt;A First Level Header&lt;/h1&gt;
                
                &lt;h2&gt;A Second Level Header&lt;/h2&gt;
                
                &lt;p&gt;Now is the time for all good men to come to
                the aid of their country. This is just a
                regular paragraph.&lt;/p&gt;
                
                &lt;p&gt;The quick brown fox jumped over the lazy
                dog's back.&lt;/p&gt;
                
                &lt;h3&gt;Header 3&lt;/h3&gt;
                
                &lt;blockquote&gt;
                    &lt;p&gt;This is a blockquote.&lt;/p&gt;
                    
                    &lt;p&gt;This is the second paragraph in the blockquote.&lt;/p&gt;
                    
                    &lt;h2&gt;This is an H2 in a blockquote&lt;/h2&gt;
                &lt;/blockquote&gt;
            
            
            
            ### Phrase Emphasis ###
            
            Markdown uses asterisks and underscores to indicate spans of emphasis.
            
            Markdown:
            
                Some of these words *are emphasized*.
                Some of these words _are emphasized also_.
                
                Use two asterisks for **strong emphasis**.
                Or, if you prefer, __use two underscores instead__.
            
            Output:
            
                &lt;p&gt;Some of these words &lt;em&gt;are emphasized&lt;/em&gt;.
                Some of these words &lt;em&gt;are emphasized also&lt;/em&gt;.&lt;/p&gt;
                
                &lt;p&gt;Use two asterisks for &lt;strong&gt;strong emphasis&lt;/strong&gt;.
                Or, if you prefer, &lt;strong&gt;use two underscores instead&lt;/strong&gt;.&lt;/p&gt;
               
            
            
            ## Lists ##
            
            Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`,
            `+`, and `-`) as list markers. These three markers are
            interchangable; this:
            
                *   Candy.
                *   Gum.
                *   Booze.
            
            this:
            
                +   Candy.
                +   Gum.
                +   Booze.
            
            and this:
            
                -   Candy.
                -   Gum.
                -   Booze.
            
            all produce the same output:
            
                &lt;ul&gt;
                &lt;li&gt;Candy.&lt;/li&gt;
                &lt;li&gt;Gum.&lt;/li&gt;
                &lt;li&gt;Booze.&lt;/li&gt;
                &lt;/ul&gt;
            
            Ordered (numbered) lists use regular numbers, followed by periods, as
            list markers:
            
                1.  Red
                2.  Green
                3.  Blue
            
            Output:
            
                &lt;ol&gt;
                &lt;li&gt;Red&lt;/li&gt;
                &lt;li&gt;Green&lt;/li&gt;
                &lt;li&gt;Blue&lt;/li&gt;
                &lt;/ol&gt;
            
            If you put blank lines between items, you'll get `&lt;p&gt;` tags for the
            list item text. You can create multi-paragraph list items by indenting
            the paragraphs by 4 spaces or 1 tab:
            
                *   A list item.
                
                    With multiple paragraphs.
            
                *   Another item in the list.
            
            Output:
            
                &lt;ul&gt;
                &lt;li&gt;&lt;p&gt;A list item.&lt;/p&gt;
                &lt;p&gt;With multiple paragraphs.&lt;/p&gt;&lt;/li&gt;
                &lt;li&gt;&lt;p&gt;Another item in the list.&lt;/p&gt;&lt;/li&gt;
                &lt;/ul&gt;
                
            
            
            ### Links ###
            
            Markdown supports two styles for creating links: *inline* and
            *reference*. With both styles, you use square brackets to delimit the
            text you want to turn into a link.
            
            Inline-style links use parentheses immediately after the link text.
            For example:
            
                This is an [example link](http://example.com/).
            
            Output:
            
                &lt;p&gt;This is an &lt;a href="http://example.com/"&gt;
                example link&lt;/a&gt;.&lt;/p&gt;
            
            Optionally, you may include a title attribute in the parentheses:
            
                This is an [example link](http://example.com/ "With a Title").
            
            Output:
            
                &lt;p&gt;This is an &lt;a href="http://example.com/" title="With a Title"&gt;
                example link&lt;/a&gt;.&lt;/p&gt;
            
            Reference-style links allow you to refer to your links by names, which
            you define elsewhere in your document:
            
                I get 10 times more traffic from [Google][1] than from
                [Yahoo][2] or [MSN][3].
            
                [1]: http://google.com/        "Google"
                [2]: http://search.yahoo.com/  "Yahoo Search"
                [3]: http://search.msn.com/    "MSN Search"
            
            Output:
            
                &lt;p&gt;I get 10 times more traffic from &lt;a href="http://google.com/"
                title="Google"&gt;Google&lt;/a&gt; than from &lt;a href="http://search.yahoo.com/"
                title="Yahoo Search"&gt;Yahoo&lt;/a&gt; or &lt;a href="http://search.msn.com/"
                title="MSN Search"&gt;MSN&lt;/a&gt;.&lt;/p&gt;
            
            The title attribute is optional. Link names may contain letters,
            numbers and spaces, but are *not* case sensitive:
            
                I start my morning with a cup of coffee and
                [The New York Times][NY Times].
            
                [ny times]: http://www.nytimes.com/
            
            Output:
            
                &lt;p&gt;I start my morning with a cup of coffee and
                &lt;a href="http://www.nytimes.com/"&gt;The New York Times&lt;/a&gt;.&lt;/p&gt;
            
            
            ### Images ###
            
            Image syntax is very much like link syntax.
            
            Inline (titles are optional):
            
                ![alt text](/path/to/img.jpg "Title")
            
            Reference-style:
            
                ![alt text][id]
            
                [id]: /path/to/img.jpg "Title"
            
            Both of the above examples produce the same output:
            
                &lt;img src="/path/to/img.jpg" alt="alt text" title="Title" /&gt;
            
            
            
            ### Code ###
            
            In a regular paragraph, you can create code span by wrapping text in
            backtick quotes. Any ampersands (`&amp;`) and angle brackets (`&lt;` or
            `&gt;`) will automatically be translated into HTML entities. This makes
            it easy to use Markdown to write about HTML example code:
            
                I strongly recommend against using any `&lt;blink&gt;` tags.
            
                I wish SmartyPants used named entities like `&amp;mdash;`
                instead of decimal-encoded entites like `&amp;#8212;`.
            
            Output:
            
                &lt;p&gt;I strongly recommend against using any
                &lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;
                
                &lt;p&gt;I wish SmartyPants used named entities like
                &lt;code&gt;&amp;amp;mdash;&lt;/code&gt; instead of decimal-encoded
                entites like &lt;code&gt;&amp;amp;#8212;&lt;/code&gt;.&lt;/p&gt;
            
            
            To specify an entire block of pre-formatted code, indent every line of
            the block by 4 spaces or 1 tab. Just like with code spans, `&amp;`, `&lt;`,
            and `&gt;` characters will be escaped automatically.
            
            Markdown:
            
                If you want your page to validate under XHTML 1.0 Strict,
                you've got to put paragraph tags in your blockquotes:
            
                    &lt;blockquote&gt;
                        &lt;p&gt;For example.&lt;/p&gt;
                    &lt;/blockquote&gt;
            
            Output:
            
                &lt;p&gt;If you want your page to validate under XHTML 1.0 Strict,
                you've got to put paragraph tags in your blockquotes:&lt;/p&gt;
                
                &lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;
                    &amp;lt;p&amp;gt;For example.&amp;lt;/p&amp;gt;
                &amp;lt;/blockquote&amp;gt;
                &lt;/code&gt;&lt;/pre&gt;
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: 'markdown',
                    lineNumbers: true,
                    theme: "default",
                    extraKeys: {"Enter": "newlineAndIndentContinueMarkdownList"}
                  });
                </script>
            
                <p>Optionally depends on the XML mode for properly highlighted inline XML blocks.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-markdown</code>.</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#markdown_*">normal</a>,  <a href="../../test/index.html#verbose,markdown_*">verbose</a>.</p>
            
              </article>
            
          • markdown.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../xml/xml"), require("../meta"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../xml/xml", "../meta"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
            
              var htmlFound = CodeMirror.modes.hasOwnProperty("xml");
              var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? {name: "xml", htmlMode: true} : "text/plain");
            
              function getMode(name) {
                if (CodeMirror.findModeByName) {
                  var found = CodeMirror.findModeByName(name);
                  if (found) name = found.mime || found.mimes[0];
                }
                var mode = CodeMirror.getMode(cmCfg, name);
                return mode.name == "null" ? null : mode;
              }
            
              // Should characters that affect highlighting be highlighted separate?
              // Does not include characters that will be output (such as `1.` and `-` for lists)
              if (modeCfg.highlightFormatting === undefined)
                modeCfg.highlightFormatting = false;
            
              // Maximum number of nested blockquotes. Set to 0 for infinite nesting.
              // Excess `>` will emit `error` token.
              if (modeCfg.maxBlockquoteDepth === undefined)
                modeCfg.maxBlockquoteDepth = 0;
            
              // Should underscores in words open/close em/strong?
              if (modeCfg.underscoresBreakWords === undefined)
                modeCfg.underscoresBreakWords = true;
            
              // Turn on fenced code blocks? ("```" to start/end)
              if (modeCfg.fencedCodeBlocks === undefined) modeCfg.fencedCodeBlocks = false;
            
              // Turn on task lists? ("- [ ] " and "- [x] ")
              if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
            
              // Turn on strikethrough syntax
              if (modeCfg.strikethrough === undefined)
                modeCfg.strikethrough = false;
            
              var codeDepth = 0;
            
              var header   = 'header'
              ,   code     = 'comment'
              ,   quote    = 'quote'
              ,   list1    = 'variable-2'
              ,   list2    = 'variable-3'
              ,   list3    = 'keyword'
              ,   hr       = 'hr'
              ,   image    = 'tag'
              ,   formatting = 'formatting'
              ,   linkinline = 'link'
              ,   linkemail = 'link'
              ,   linktext = 'link'
              ,   linkhref = 'string'
              ,   em       = 'em'
              ,   strong   = 'strong'
              ,   strikethrough = 'strikethrough';
            
              var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/
              ,   ulRE = /^[*\-+]\s+/
              ,   olRE = /^[0-9]+\.\s+/
              ,   taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE
              ,   atxHeaderRE = /^#+ ?/
              ,   setextHeaderRE = /^(?:\={1,}|-{1,})$/
              ,   textRE = /^[^#!\[\]*_\\<>` "'(~]+/;
            
              function switchInline(stream, state, f) {
                state.f = state.inline = f;
                return f(stream, state);
              }
            
              function switchBlock(stream, state, f) {
                state.f = state.block = f;
                return f(stream, state);
              }
            
            
              // Blocks
            
              function blankLine(state) {
                // Reset linkTitle state
                state.linkTitle = false;
                // Reset EM state
                state.em = false;
                // Reset STRONG state
                state.strong = false;
                // Reset strikethrough state
                state.strikethrough = false;
                // Reset state.quote
                state.quote = 0;
                if (!htmlFound && state.f == htmlBlock) {
                  state.f = inlineNormal;
                  state.block = blockNormal;
                }
                // Reset state.trailingSpace
                state.trailingSpace = 0;
                state.trailingSpaceNewLine = false;
                // Mark this line as blank
                state.thisLineHasContent = false;
                return null;
              }
            
              function blockNormal(stream, state) {
            
                var sol = stream.sol();
            
                var prevLineIsList = state.list !== false;
                if (prevLineIsList) {
                  if (state.indentationDiff >= 0) { // Continued list
                    if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block
                      state.indentation -= state.indentationDiff;
                    }
                    state.list = null;
                  } else if (state.indentation > 0) {
                    state.list = null;
                    state.listDepth = Math.floor(state.indentation / 4);
                  } else { // No longer a list
                    state.list = false;
                    state.listDepth = 0;
                  }
                }
            
                var match = null;
                if (state.indentationDiff >= 4) {
                  state.indentation -= 4;
                  stream.skipToEnd();
                  return code;
                } else if (stream.eatSpace()) {
                  return null;
                } else if (match = stream.match(atxHeaderRE)) {
                  state.header = Math.min(6, match[0].indexOf(" ") !== -1 ? match[0].length - 1 : match[0].length);
                  if (modeCfg.highlightFormatting) state.formatting = "header";
                  state.f = state.inline;
                  return getType(state);
                } else if (state.prevLineHasContent && (match = stream.match(setextHeaderRE))) {
                  state.header = match[0].charAt(0) == '=' ? 1 : 2;
                  if (modeCfg.highlightFormatting) state.formatting = "header";
                  state.f = state.inline;
                  return getType(state);
                } else if (stream.eat('>')) {
                  state.indentation++;
                  state.quote = sol ? 1 : state.quote + 1;
                  if (modeCfg.highlightFormatting) state.formatting = "quote";
                  stream.eatSpace();
                  return getType(state);
                } else if (stream.peek() === '[') {
                  return switchInline(stream, state, footnoteLink);
                } else if (stream.match(hrRE, true)) {
                  return hr;
                } else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) {
                  var listType = null;
                  if (stream.match(ulRE, true)) {
                    listType = 'ul';
                  } else {
                    stream.match(olRE, true);
                    listType = 'ol';
                  }
                  state.indentation += 4;
                  state.list = true;
                  state.listDepth++;
                  if (modeCfg.taskLists && stream.match(taskListRE, false)) {
                    state.taskList = true;
                  }
                  state.f = state.inline;
                  if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
                  return getType(state);
                } else if (modeCfg.fencedCodeBlocks && stream.match(/^```[ \t]*([\w+#]*)/, true)) {
                  // try switching mode
                  state.localMode = getMode(RegExp.$1);
                  if (state.localMode) state.localState = state.localMode.startState();
                  state.f = state.block = local;
                  if (modeCfg.highlightFormatting) state.formatting = "code-block";
                  state.code = true;
                  return getType(state);
                }
            
                return switchInline(stream, state, state.inline);
              }
            
              function htmlBlock(stream, state) {
                var style = htmlMode.token(stream, state.htmlState);
                if ((htmlFound && state.htmlState.tagStart === null && !state.htmlState.context) ||
                    (state.md_inside && stream.current().indexOf(">") > -1)) {
                  state.f = inlineNormal;
                  state.block = blockNormal;
                  state.htmlState = null;
                }
                return style;
              }
            
              function local(stream, state) {
                if (stream.sol() && stream.match("```", false)) {
                  state.localMode = state.localState = null;
                  state.f = state.block = leavingLocal;
                  return null;
                } else if (state.localMode) {
                  return state.localMode.token(stream, state.localState);
                } else {
                  stream.skipToEnd();
                  return code;
                }
              }
            
              function leavingLocal(stream, state) {
                stream.match("```");
                state.block = blockNormal;
                state.f = inlineNormal;
                if (modeCfg.highlightFormatting) state.formatting = "code-block";
                state.code = true;
                var returnType = getType(state);
                state.code = false;
                return returnType;
              }
            
              // Inline
              function getType(state) {
                var styles = [];
            
                if (state.formatting) {
                  styles.push(formatting);
            
                  if (typeof state.formatting === "string") state.formatting = [state.formatting];
            
                  for (var i = 0; i < state.formatting.length; i++) {
                    styles.push(formatting + "-" + state.formatting[i]);
            
                    if (state.formatting[i] === "header") {
                      styles.push(formatting + "-" + state.formatting[i] + "-" + state.header);
                    }
            
                    // Add `formatting-quote` and `formatting-quote-#` for blockquotes
                    // Add `error` instead if the maximum blockquote nesting depth is passed
                    if (state.formatting[i] === "quote") {
                      if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
                        styles.push(formatting + "-" + state.formatting[i] + "-" + state.quote);
                      } else {
                        styles.push("error");
                      }
                    }
                  }
                }
            
                if (state.taskOpen) {
                  styles.push("meta");
                  return styles.length ? styles.join(' ') : null;
                }
                if (state.taskClosed) {
                  styles.push("property");
                  return styles.length ? styles.join(' ') : null;
                }
            
                if (state.linkHref) {
                  styles.push(linkhref);
                  return styles.length ? styles.join(' ') : null;
                }
            
                if (state.strong) { styles.push(strong); }
                if (state.em) { styles.push(em); }
                if (state.strikethrough) { styles.push(strikethrough); }
            
                if (state.linkText) { styles.push(linktext); }
            
                if (state.code) { styles.push(code); }
            
                if (state.header) { styles.push(header); styles.push(header + "-" + state.header); }
            
                if (state.quote) {
                  styles.push(quote);
            
                  // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
                  if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
                    styles.push(quote + "-" + state.quote);
                  } else {
                    styles.push(quote + "-" + modeCfg.maxBlockquoteDepth);
                  }
                }
            
                if (state.list !== false) {
                  var listMod = (state.listDepth - 1) % 3;
                  if (!listMod) {
                    styles.push(list1);
                  } else if (listMod === 1) {
                    styles.push(list2);
                  } else {
                    styles.push(list3);
                  }
                }
            
                if (state.trailingSpaceNewLine) {
                  styles.push("trailing-space-new-line");
                } else if (state.trailingSpace) {
                  styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b"));
                }
            
                return styles.length ? styles.join(' ') : null;
              }
            
              function handleText(stream, state) {
                if (stream.match(textRE, true)) {
                  return getType(state);
                }
                return undefined;
              }
            
              function inlineNormal(stream, state) {
                var style = state.text(stream, state);
                if (typeof style !== 'undefined')
                  return style;
            
                if (state.list) { // List marker (*, +, -, 1., etc)
                  state.list = null;
                  return getType(state);
                }
            
                if (state.taskList) {
                  var taskOpen = stream.match(taskListRE, true)[1] !== "x";
                  if (taskOpen) state.taskOpen = true;
                  else state.taskClosed = true;
                  if (modeCfg.highlightFormatting) state.formatting = "task";
                  state.taskList = false;
                  return getType(state);
                }
            
                state.taskOpen = false;
                state.taskClosed = false;
            
                if (state.header && stream.match(/^#+$/, true)) {
                  if (modeCfg.highlightFormatting) state.formatting = "header";
                  return getType(state);
                }
            
                // Get sol() value now, before character is consumed
                var sol = stream.sol();
            
                var ch = stream.next();
            
                if (ch === '\\') {
                  stream.next();
                  if (modeCfg.highlightFormatting) {
                    var type = getType(state);
                    return type ? type + " formatting-escape" : "formatting-escape";
                  }
                }
            
                // Matches link titles present on next line
                if (state.linkTitle) {
                  state.linkTitle = false;
                  var matchCh = ch;
                  if (ch === '(') {
                    matchCh = ')';
                  }
                  matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
                  var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
                  if (stream.match(new RegExp(regex), true)) {
                    return linkhref;
                  }
                }
            
                // If this block is changed, it may need to be updated in GFM mode
                if (ch === '`') {
                  var previousFormatting = state.formatting;
                  if (modeCfg.highlightFormatting) state.formatting = "code";
                  var t = getType(state);
                  var before = stream.pos;
                  stream.eatWhile('`');
                  var difference = 1 + stream.pos - before;
                  if (!state.code) {
                    codeDepth = difference;
                    state.code = true;
                    return getType(state);
                  } else {
                    if (difference === codeDepth) { // Must be exact
                      state.code = false;
                      return t;
                    }
                    state.formatting = previousFormatting;
                    return getType(state);
                  }
                } else if (state.code) {
                  return getType(state);
                }
            
                if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
                  stream.match(/\[[^\]]*\]/);
                  state.inline = state.f = linkHref;
                  return image;
                }
            
                if (ch === '[' && stream.match(/.*\](\(.*\)| ?\[.*\])/, false)) {
                  state.linkText = true;
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  return getType(state);
                }
            
                if (ch === ']' && state.linkText && stream.match(/\(.*\)| ?\[.*\]/, false)) {
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  var type = getType(state);
                  state.linkText = false;
                  state.inline = state.f = linkHref;
                  return type;
                }
            
                if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
                  state.f = state.inline = linkInline;
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  var type = getType(state);
                  if (type){
                    type += " ";
                  } else {
                    type = "";
                  }
                  return type + linkinline;
                }
            
                if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
                  state.f = state.inline = linkInline;
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  var type = getType(state);
                  if (type){
                    type += " ";
                  } else {
                    type = "";
                  }
                  return type + linkemail;
                }
            
                if (ch === '<' && stream.match(/^\w/, false)) {
                  if (stream.string.indexOf(">") != -1) {
                    var atts = stream.string.substring(1,stream.string.indexOf(">"));
                    if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) {
                      state.md_inside = true;
                    }
                  }
                  stream.backUp(1);
                  state.htmlState = CodeMirror.startState(htmlMode);
                  return switchBlock(stream, state, htmlBlock);
                }
            
                if (ch === '<' && stream.match(/^\/\w*?>/)) {
                  state.md_inside = false;
                  return "tag";
                }
            
                var ignoreUnderscore = false;
                if (!modeCfg.underscoresBreakWords) {
                  if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) {
                    var prevPos = stream.pos - 2;
                    if (prevPos >= 0) {
                      var prevCh = stream.string.charAt(prevPos);
                      if (prevCh !== '_' && prevCh.match(/(\w)/, false)) {
                        ignoreUnderscore = true;
                      }
                    }
                  }
                }
                if (ch === '*' || (ch === '_' && !ignoreUnderscore)) {
                  if (sol && stream.peek() === ' ') {
                    // Do nothing, surrounded by newline and space
                  } else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG
                    if (modeCfg.highlightFormatting) state.formatting = "strong";
                    var t = getType(state);
                    state.strong = false;
                    return t;
                  } else if (!state.strong && stream.eat(ch)) { // Add STRONG
                    state.strong = ch;
                    if (modeCfg.highlightFormatting) state.formatting = "strong";
                    return getType(state);
                  } else if (state.em === ch) { // Remove EM
                    if (modeCfg.highlightFormatting) state.formatting = "em";
                    var t = getType(state);
                    state.em = false;
                    return t;
                  } else if (!state.em) { // Add EM
                    state.em = ch;
                    if (modeCfg.highlightFormatting) state.formatting = "em";
                    return getType(state);
                  }
                } else if (ch === ' ') {
                  if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces
                    if (stream.peek() === ' ') { // Surrounded by spaces, ignore
                      return getType(state);
                    } else { // Not surrounded by spaces, back up pointer
                      stream.backUp(1);
                    }
                  }
                }
            
                if (modeCfg.strikethrough) {
                  if (ch === '~' && stream.eatWhile(ch)) {
                    if (state.strikethrough) {// Remove strikethrough
                      if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
                      var t = getType(state);
                      state.strikethrough = false;
                      return t;
                    } else if (stream.match(/^[^\s]/, false)) {// Add strikethrough
                      state.strikethrough = true;
                      if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
                      return getType(state);
                    }
                  } else if (ch === ' ') {
                    if (stream.match(/^~~/, true)) { // Probably surrounded by space
                      if (stream.peek() === ' ') { // Surrounded by spaces, ignore
                        return getType(state);
                      } else { // Not surrounded by spaces, back up pointer
                        stream.backUp(2);
                      }
                    }
                  }
                }
            
                if (ch === ' ') {
                  if (stream.match(/ +$/, false)) {
                    state.trailingSpace++;
                  } else if (state.trailingSpace) {
                    state.trailingSpaceNewLine = true;
                  }
                }
            
                return getType(state);
              }
            
              function linkInline(stream, state) {
                var ch = stream.next();
            
                if (ch === ">") {
                  state.f = state.inline = inlineNormal;
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  var type = getType(state);
                  if (type){
                    type += " ";
                  } else {
                    type = "";
                  }
                  return type + linkinline;
                }
            
                stream.match(/^[^>]+/, true);
            
                return linkinline;
              }
            
              function linkHref(stream, state) {
                // Check if space, and return NULL if so (to avoid marking the space)
                if(stream.eatSpace()){
                  return null;
                }
                var ch = stream.next();
                if (ch === '(' || ch === '[') {
                  state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]");
                  if (modeCfg.highlightFormatting) state.formatting = "link-string";
                  state.linkHref = true;
                  return getType(state);
                }
                return 'error';
              }
            
              function getLinkHrefInside(endChar) {
                return function(stream, state) {
                  var ch = stream.next();
            
                  if (ch === endChar) {
                    state.f = state.inline = inlineNormal;
                    if (modeCfg.highlightFormatting) state.formatting = "link-string";
                    var returnState = getType(state);
                    state.linkHref = false;
                    return returnState;
                  }
            
                  if (stream.match(inlineRE(endChar), true)) {
                    stream.backUp(1);
                  }
            
                  state.linkHref = true;
                  return getType(state);
                };
              }
            
              function footnoteLink(stream, state) {
                if (stream.match(/^[^\]]*\]:/, false)) {
                  state.f = footnoteLinkInside;
                  stream.next(); // Consume [
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  state.linkText = true;
                  return getType(state);
                }
                return switchInline(stream, state, inlineNormal);
              }
            
              function footnoteLinkInside(stream, state) {
                if (stream.match(/^\]:/, true)) {
                  state.f = state.inline = footnoteUrl;
                  if (modeCfg.highlightFormatting) state.formatting = "link";
                  var returnType = getType(state);
                  state.linkText = false;
                  return returnType;
                }
            
                stream.match(/^[^\]]+/, true);
            
                return linktext;
              }
            
              function footnoteUrl(stream, state) {
                // Check if space, and return NULL if so (to avoid marking the space)
                if(stream.eatSpace()){
                  return null;
                }
                // Match URL
                stream.match(/^[^\s]+/, true);
                // Check for link title
                if (stream.peek() === undefined) { // End of line, set flag to check next line
                  state.linkTitle = true;
                } else { // More content on line, check if link title
                  stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true);
                }
                state.f = state.inline = inlineNormal;
                return linkhref;
              }
            
              var savedInlineRE = [];
              function inlineRE(endChar) {
                if (!savedInlineRE[endChar]) {
                  // Escape endChar for RegExp (taken from http://stackoverflow.com/a/494122/526741)
                  endChar = (endChar+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
                  // Match any non-endChar, escaped character, as well as the closing
                  // endChar.
                  savedInlineRE[endChar] = new RegExp('^(?:[^\\\\]|\\\\.)*?(' + endChar + ')');
                }
                return savedInlineRE[endChar];
              }
            
              var mode = {
                startState: function() {
                  return {
                    f: blockNormal,
            
                    prevLineHasContent: false,
                    thisLineHasContent: false,
            
                    block: blockNormal,
                    htmlState: null,
                    indentation: 0,
            
                    inline: inlineNormal,
                    text: handleText,
            
                    formatting: false,
                    linkText: false,
                    linkHref: false,
                    linkTitle: false,
                    em: false,
                    strong: false,
                    header: 0,
                    taskList: false,
                    list: false,
                    listDepth: 0,
                    quote: 0,
                    trailingSpace: 0,
                    trailingSpaceNewLine: false,
                    strikethrough: false
                  };
                },
            
                copyState: function(s) {
                  return {
                    f: s.f,
            
                    prevLineHasContent: s.prevLineHasContent,
                    thisLineHasContent: s.thisLineHasContent,
            
                    block: s.block,
                    htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
                    indentation: s.indentation,
            
                    localMode: s.localMode,
                    localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,
            
                    inline: s.inline,
                    text: s.text,
                    formatting: false,
                    linkTitle: s.linkTitle,
                    em: s.em,
                    strong: s.strong,
                    strikethrough: s.strikethrough,
                    header: s.header,
                    taskList: s.taskList,
                    list: s.list,
                    listDepth: s.listDepth,
                    quote: s.quote,
                    trailingSpace: s.trailingSpace,
                    trailingSpaceNewLine: s.trailingSpaceNewLine,
                    md_inside: s.md_inside
                  };
                },
            
                token: function(stream, state) {
            
                  // Reset state.formatting
                  state.formatting = false;
            
                  if (stream.sol()) {
                    var forceBlankLine = !!state.header;
            
                    // Reset state.header
                    state.header = 0;
            
                    if (stream.match(/^\s*$/, true) || forceBlankLine) {
                      state.prevLineHasContent = false;
                      blankLine(state);
                      return forceBlankLine ? this.token(stream, state) : null;
                    } else {
                      state.prevLineHasContent = state.thisLineHasContent;
                      state.thisLineHasContent = true;
                    }
            
                    // Reset state.taskList
                    state.taskList = false;
            
                    // Reset state.code
                    state.code = false;
            
                    // Reset state.trailingSpace
                    state.trailingSpace = 0;
                    state.trailingSpaceNewLine = false;
            
                    state.f = state.block;
                    var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, '    ').length;
                    var difference = Math.floor((indentation - state.indentation) / 4) * 4;
                    if (difference > 4) difference = 4;
                    var adjustedIndentation = state.indentation + difference;
                    state.indentationDiff = adjustedIndentation - state.indentation;
                    state.indentation = adjustedIndentation;
                    if (indentation > 0) return null;
                  }
                  return state.f(stream, state);
                },
            
                innerMode: function(state) {
                  if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode};
                  if (state.localState) return {state: state.localState, mode: state.localMode};
                  return {state: state, mode: mode};
                },
            
                blankLine: blankLine,
            
                getType: getType,
            
                fold: "markdown"
              };
              return mode;
            }, "xml");
            
            CodeMirror.defineMIME("text/x-markdown", "markdown");
            
            });
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4}, "markdown");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
              var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: "markdown", highlightFormatting: true});
              function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); }
            
              FT("formatting_emAsterisk",
                 "[em&formatting&formatting-em *][em foo][em&formatting&formatting-em *]");
            
              FT("formatting_emUnderscore",
                 "[em&formatting&formatting-em _][em foo][em&formatting&formatting-em _]");
            
              FT("formatting_strongAsterisk",
                 "[strong&formatting&formatting-strong **][strong foo][strong&formatting&formatting-strong **]");
            
              FT("formatting_strongUnderscore",
                 "[strong&formatting&formatting-strong __][strong foo][strong&formatting&formatting-strong __]");
            
              FT("formatting_codeBackticks",
                 "[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]");
            
              FT("formatting_doubleBackticks",
                 "[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]");
            
              FT("formatting_atxHeader",
                 "[header&header-1&formatting&formatting-header&formatting-header-1 # ][header&header-1 foo # bar ][header&header-1&formatting&formatting-header&formatting-header-1 #]");
            
              FT("formatting_setextHeader",
                 "foo",
                 "[header&header-1&formatting&formatting-header&formatting-header-1 =]");
            
              FT("formatting_blockquote",
                 "[quote&quote-1&formatting&formatting-quote&formatting-quote-1 > ][quote&quote-1 foo]");
            
              FT("formatting_list",
                 "[variable-2&formatting&formatting-list&formatting-list-ul - ][variable-2 foo]");
              FT("formatting_list",
                 "[variable-2&formatting&formatting-list&formatting-list-ol 1. ][variable-2 foo]");
            
              FT("formatting_link",
                 "[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string (][string http://example.com/][string&formatting&formatting-link-string )]");
            
              FT("formatting_linkReference",
                 "[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string [][string bar][string&formatting&formatting-link-string ]]]",
                 "[link&formatting&formatting-link [][link bar][link&formatting&formatting-link ]]:] [string http://example.com/]");
            
              FT("formatting_linkWeb",
                 "[link&formatting&formatting-link <][link http://example.com/][link&formatting&formatting-link >]");
            
              FT("formatting_linkEmail",
                 "[link&formatting&formatting-link <][link user@example.com][link&formatting&formatting-link >]");
            
              FT("formatting_escape",
                 "[formatting-escape \\*]");
            
              MT("plainText",
                 "foo");
            
              // Don't style single trailing space
              MT("trailingSpace1",
                 "foo ");
            
              // Two or more trailing spaces should be styled with line break character
              MT("trailingSpace2",
                 "foo[trailing-space-a  ][trailing-space-new-line  ]");
            
              MT("trailingSpace3",
                 "foo[trailing-space-a  ][trailing-space-b  ][trailing-space-new-line  ]");
            
              MT("trailingSpace4",
                 "foo[trailing-space-a  ][trailing-space-b  ][trailing-space-a  ][trailing-space-new-line  ]");
            
              // Code blocks using 4 spaces (regardless of CodeMirror.tabSize value)
              MT("codeBlocksUsing4Spaces",
                 "    [comment foo]");
            
              // Code blocks using 4 spaces with internal indentation
              MT("codeBlocksUsing4SpacesIndentation",
                 "    [comment bar]",
                 "        [comment hello]",
                 "            [comment world]",
                 "    [comment foo]",
                 "bar");
            
              // Code blocks using 4 spaces with internal indentation
              MT("codeBlocksUsing4SpacesIndentation",
                 " foo",
                 "    [comment bar]",
                 "        [comment hello]",
                 "    [comment world]");
            
              // Code blocks should end even after extra indented lines
              MT("codeBlocksWithTrailingIndentedLine",
                 "    [comment foo]",
                 "        [comment bar]",
                 "    [comment baz]",
                 "    ",
                 "hello");
            
              // Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value)
              MT("codeBlocksUsing1Tab",
                 "\t[comment foo]");
            
              // Inline code using backticks
              MT("inlineCodeUsingBackticks",
                 "foo [comment `bar`]");
            
              // Block code using single backtick (shouldn't work)
              MT("blockCodeSingleBacktick",
                 "[comment `]",
                 "foo",
                 "[comment `]");
            
              // Unclosed backticks
              // Instead of simply marking as CODE, it would be nice to have an
              // incomplete flag for CODE, that is styled slightly different.
              MT("unclosedBackticks",
                 "foo [comment `bar]");
            
              // Per documentation: "To include a literal backtick character within a
              // code span, you can use multiple backticks as the opening and closing
              // delimiters"
              MT("doubleBackticks",
                 "[comment ``foo ` bar``]");
            
              // Tests based on Dingus
              // http://daringfireball.net/projects/markdown/dingus
              //
              // Multiple backticks within an inline code block
              MT("consecutiveBackticks",
                 "[comment `foo```bar`]");
            
              // Multiple backticks within an inline code block with a second code block
              MT("consecutiveBackticks",
                 "[comment `foo```bar`] hello [comment `world`]");
            
              // Unclosed with several different groups of backticks
              MT("unclosedBackticks",
                 "[comment ``foo ``` bar` hello]");
            
              // Closed with several different groups of backticks
              MT("closedBackticks",
                 "[comment ``foo ``` bar` hello``] world");
            
              // atx headers
              // http://daringfireball.net/projects/markdown/syntax#header
            
              MT("atxH1",
                 "[header&header-1 # foo]");
            
              MT("atxH2",
                 "[header&header-2 ## foo]");
            
              MT("atxH3",
                 "[header&header-3 ### foo]");
            
              MT("atxH4",
                 "[header&header-4 #### foo]");
            
              MT("atxH5",
                 "[header&header-5 ##### foo]");
            
              MT("atxH6",
                 "[header&header-6 ###### foo]");
            
              // H6 - 7x '#' should still be H6, per Dingus
              // http://daringfireball.net/projects/markdown/dingus
              MT("atxH6NotH7",
                 "[header&header-6 ####### foo]");
            
              // Inline styles should be parsed inside headers
              MT("atxH1inline",
                 "[header&header-1 # foo ][header&header-1&em *bar*]");
            
              // Setext headers - H1, H2
              // Per documentation, "Any number of underlining =’s or -’s will work."
              // http://daringfireball.net/projects/markdown/syntax#header
              // Ideally, the text would be marked as `header` as well, but this is
              // not really feasible at the moment. So, instead, we're testing against
              // what works today, to avoid any regressions.
              //
              // Check if single underlining = works
              MT("setextH1",
                 "foo",
                 "[header&header-1 =]");
            
              // Check if 3+ ='s work
              MT("setextH1",
                 "foo",
                 "[header&header-1 ===]");
            
              // Check if single underlining - works
              MT("setextH2",
                 "foo",
                 "[header&header-2 -]");
            
              // Check if 3+ -'s work
              MT("setextH2",
                 "foo",
                 "[header&header-2 ---]");
            
              // Single-line blockquote with trailing space
              MT("blockquoteSpace",
                 "[quote&quote-1 > foo]");
            
              // Single-line blockquote
              MT("blockquoteNoSpace",
                 "[quote&quote-1 >foo]");
            
              // No blank line before blockquote
              MT("blockquoteNoBlankLine",
                 "foo",
                 "[quote&quote-1 > bar]");
            
              // Nested blockquote
              MT("blockquoteSpace",
                 "[quote&quote-1 > foo]",
                 "[quote&quote-1 >][quote&quote-2 > foo]",
                 "[quote&quote-1 >][quote&quote-2 >][quote&quote-3 > foo]");
            
              // Single-line blockquote followed by normal paragraph
              MT("blockquoteThenParagraph",
                 "[quote&quote-1 >foo]",
                 "",
                 "bar");
            
              // Multi-line blockquote (lazy mode)
              MT("multiBlockquoteLazy",
                 "[quote&quote-1 >foo]",
                 "[quote&quote-1 bar]");
            
              // Multi-line blockquote followed by normal paragraph (lazy mode)
              MT("multiBlockquoteLazyThenParagraph",
                 "[quote&quote-1 >foo]",
                 "[quote&quote-1 bar]",
                 "",
                 "hello");
            
              // Multi-line blockquote (non-lazy mode)
              MT("multiBlockquote",
                 "[quote&quote-1 >foo]",
                 "[quote&quote-1 >bar]");
            
              // Multi-line blockquote followed by normal paragraph (non-lazy mode)
              MT("multiBlockquoteThenParagraph",
                 "[quote&quote-1 >foo]",
                 "[quote&quote-1 >bar]",
                 "",
                 "hello");
            
              // Check list types
            
              MT("listAsterisk",
                 "foo",
                 "bar",
                 "",
                 "[variable-2 * foo]",
                 "[variable-2 * bar]");
            
              MT("listPlus",
                 "foo",
                 "bar",
                 "",
                 "[variable-2 + foo]",
                 "[variable-2 + bar]");
            
              MT("listDash",
                 "foo",
                 "bar",
                 "",
                 "[variable-2 - foo]",
                 "[variable-2 - bar]");
            
              MT("listNumber",
                 "foo",
                 "bar",
                 "",
                 "[variable-2 1. foo]",
                 "[variable-2 2. bar]");
            
              // Lists require a preceding blank line (per Dingus)
              MT("listBogus",
                 "foo",
                 "1. bar",
                 "2. hello");
            
              // List after header
              MT("listAfterHeader",
                 "[header&header-1 # foo]",
                 "[variable-2 - bar]");
            
              // Formatting in lists (*)
              MT("listAsteriskFormatting",
                 "[variable-2 * ][variable-2&em *foo*][variable-2  bar]",
                 "[variable-2 * ][variable-2&strong **foo**][variable-2  bar]",
                 "[variable-2 * ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]",
                 "[variable-2 * ][variable-2&comment `foo`][variable-2  bar]");
            
              // Formatting in lists (+)
              MT("listPlusFormatting",
                 "[variable-2 + ][variable-2&em *foo*][variable-2  bar]",
                 "[variable-2 + ][variable-2&strong **foo**][variable-2  bar]",
                 "[variable-2 + ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]",
                 "[variable-2 + ][variable-2&comment `foo`][variable-2  bar]");
            
              // Formatting in lists (-)
              MT("listDashFormatting",
                 "[variable-2 - ][variable-2&em *foo*][variable-2  bar]",
                 "[variable-2 - ][variable-2&strong **foo**][variable-2  bar]",
                 "[variable-2 - ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]",
                 "[variable-2 - ][variable-2&comment `foo`][variable-2  bar]");
            
              // Formatting in lists (1.)
              MT("listNumberFormatting",
                 "[variable-2 1. ][variable-2&em *foo*][variable-2  bar]",
                 "[variable-2 2. ][variable-2&strong **foo**][variable-2  bar]",
                 "[variable-2 3. ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]",
                 "[variable-2 4. ][variable-2&comment `foo`][variable-2  bar]");
            
              // Paragraph lists
              MT("listParagraph",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]");
            
              // Multi-paragraph lists
              //
              // 4 spaces
              MT("listMultiParagraph",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "    [variable-2 hello]");
            
              // 4 spaces, extra blank lines (should still be list, per Dingus)
              MT("listMultiParagraphExtra",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "",
                 "    [variable-2 hello]");
            
              // 4 spaces, plus 1 space (should still be list, per Dingus)
              MT("listMultiParagraphExtraSpace",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "     [variable-2 hello]",
                 "",
                 "    [variable-2 world]");
            
              // 1 tab
              MT("listTab",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "\t[variable-2 hello]");
            
              // No indent
              MT("listNoIndent",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "hello");
            
              // Blockquote
              MT("blockquote",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "    [variable-2&quote&quote-1 > hello]");
            
              // Code block
              MT("blockquoteCode",
                 "[variable-2 * foo]",
                 "",
                 "[variable-2 * bar]",
                 "",
                 "        [comment > hello]",
                 "",
                 "    [variable-2 world]");
            
              // Code block followed by text
              MT("blockquoteCodeText",
                 "[variable-2 * foo]",
                 "",
                 "    [variable-2 bar]",
                 "",
                 "        [comment hello]",
                 "",
                 "    [variable-2 world]");
            
              // Nested list
            
              MT("listAsteriskNested",
                 "[variable-2 * foo]",
                 "",
                 "    [variable-3 * bar]");
            
              MT("listPlusNested",
                 "[variable-2 + foo]",
                 "",
                 "    [variable-3 + bar]");
            
              MT("listDashNested",
                 "[variable-2 - foo]",
                 "",
                 "    [variable-3 - bar]");
            
              MT("listNumberNested",
                 "[variable-2 1. foo]",
                 "",
                 "    [variable-3 2. bar]");
            
              MT("listMixed",
                 "[variable-2 * foo]",
                 "",
                 "    [variable-3 + bar]",
                 "",
                 "        [keyword - hello]",
                 "",
                 "            [variable-2 1. world]");
            
              MT("listBlockquote",
                 "[variable-2 * foo]",
                 "",
                 "    [variable-3 + bar]",
                 "",
                 "        [quote&quote-1&variable-3 > hello]");
            
              MT("listCode",
                 "[variable-2 * foo]",
                 "",
                 "    [variable-3 + bar]",
                 "",
                 "            [comment hello]");
            
              // Code with internal indentation
              MT("listCodeIndentation",
                 "[variable-2 * foo]",
                 "",
                 "        [comment bar]",
                 "            [comment hello]",
                 "                [comment world]",
                 "        [comment foo]",
                 "    [variable-2 bar]");
            
              // List nesting edge cases
              MT("listNested",
                "[variable-2 * foo]",
                "",
                "    [variable-3 * bar]",
                "",
                "       [variable-2 hello]"
              );
              MT("listNested",
                "[variable-2 * foo]",
                "",
                "    [variable-3 * bar]",
                "",
                "      [variable-3 * foo]"
              );
            
              // Code followed by text
              MT("listCodeText",
                 "[variable-2 * foo]",
                 "",
                 "        [comment bar]",
                 "",
                 "hello");
            
              // Following tests directly from official Markdown documentation
              // http://daringfireball.net/projects/markdown/syntax#hr
            
              MT("hrSpace",
                 "[hr * * *]");
            
              MT("hr",
                 "[hr ***]");
            
              MT("hrLong",
                 "[hr *****]");
            
              MT("hrSpaceDash",
                 "[hr - - -]");
            
              MT("hrDashLong",
                 "[hr ---------------------------------------]");
            
              // Inline link with title
              MT("linkTitle",
                 "[link [[foo]]][string (http://example.com/ \"bar\")] hello");
            
              // Inline link without title
              MT("linkNoTitle",
                 "[link [[foo]]][string (http://example.com/)] bar");
            
              // Inline link with image
              MT("linkImage",
                 "[link [[][tag ![[foo]]][string (http://example.com/)][link ]]][string (http://example.com/)] bar");
            
              // Inline link with Em
              MT("linkEm",
                 "[link [[][link&em *foo*][link ]]][string (http://example.com/)] bar");
            
              // Inline link with Strong
              MT("linkStrong",
                 "[link [[][link&strong **foo**][link ]]][string (http://example.com/)] bar");
            
              // Inline link with EmStrong
              MT("linkEmStrong",
                 "[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string (http://example.com/)] bar");
            
              // Image with title
              MT("imageTitle",
                 "[tag ![[foo]]][string (http://example.com/ \"bar\")] hello");
            
              // Image without title
              MT("imageNoTitle",
                 "[tag ![[foo]]][string (http://example.com/)] bar");
            
              // Image with asterisks
              MT("imageAsterisks",
                 "[tag ![[*foo*]]][string (http://example.com/)] bar");
            
              // Not a link. Should be normal text due to square brackets being used
              // regularly in text, especially in quoted material, and no space is allowed
              // between square brackets and parentheses (per Dingus).
              MT("notALink",
                 "[[foo]] (bar)");
            
              // Reference-style links
              MT("linkReference",
                 "[link [[foo]]][string [[bar]]] hello");
            
              // Reference-style links with Em
              MT("linkReferenceEm",
                 "[link [[][link&em *foo*][link ]]][string [[bar]]] hello");
            
              // Reference-style links with Strong
              MT("linkReferenceStrong",
                 "[link [[][link&strong **foo**][link ]]][string [[bar]]] hello");
            
              // Reference-style links with EmStrong
              MT("linkReferenceEmStrong",
                 "[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string [[bar]]] hello");
            
              // Reference-style links with optional space separator (per docuentation)
              // "You can optionally use a space to separate the sets of brackets"
              MT("linkReferenceSpace",
                 "[link [[foo]]] [string [[bar]]] hello");
            
              // Should only allow a single space ("...use *a* space...")
              MT("linkReferenceDoubleSpace",
                 "[[foo]]  [[bar]] hello");
            
              // Reference-style links with implicit link name
              MT("linkImplicit",
                 "[link [[foo]]][string [[]]] hello");
            
              // @todo It would be nice if, at some point, the document was actually
              // checked to see if the referenced link exists
            
              // Link label, for reference-style links (taken from documentation)
            
              MT("labelNoTitle",
                 "[link [[foo]]:] [string http://example.com/]");
            
              MT("labelIndented",
                 "   [link [[foo]]:] [string http://example.com/]");
            
              MT("labelSpaceTitle",
                 "[link [[foo bar]]:] [string http://example.com/ \"hello\"]");
            
              MT("labelDoubleTitle",
                 "[link [[foo bar]]:] [string http://example.com/ \"hello\"] \"world\"");
            
              MT("labelTitleDoubleQuotes",
                 "[link [[foo]]:] [string http://example.com/  \"bar\"]");
            
              MT("labelTitleSingleQuotes",
                 "[link [[foo]]:] [string http://example.com/  'bar']");
            
              MT("labelTitleParenthese",
                 "[link [[foo]]:] [string http://example.com/  (bar)]");
            
              MT("labelTitleInvalid",
                 "[link [[foo]]:] [string http://example.com/] bar");
            
              MT("labelLinkAngleBrackets",
                 "[link [[foo]]:] [string <http://example.com/>  \"bar\"]");
            
              MT("labelTitleNextDoubleQuotes",
                 "[link [[foo]]:] [string http://example.com/]",
                 "[string \"bar\"] hello");
            
              MT("labelTitleNextSingleQuotes",
                 "[link [[foo]]:] [string http://example.com/]",
                 "[string 'bar'] hello");
            
              MT("labelTitleNextParenthese",
                 "[link [[foo]]:] [string http://example.com/]",
                 "[string (bar)] hello");
            
              MT("labelTitleNextMixed",
                 "[link [[foo]]:] [string http://example.com/]",
                 "(bar\" hello");
            
              MT("linkWeb",
                 "[link <http://example.com/>] foo");
            
              MT("linkWebDouble",
                 "[link <http://example.com/>] foo [link <http://example.com/>]");
            
              MT("linkEmail",
                 "[link <user@example.com>] foo");
            
              MT("linkEmailDouble",
                 "[link <user@example.com>] foo [link <user@example.com>]");
            
              MT("emAsterisk",
                 "[em *foo*] bar");
            
              MT("emUnderscore",
                 "[em _foo_] bar");
            
              MT("emInWordAsterisk",
                 "foo[em *bar*]hello");
            
              MT("emInWordUnderscore",
                 "foo[em _bar_]hello");
            
              // Per documentation: "...surround an * or _ with spaces, it’ll be
              // treated as a literal asterisk or underscore."
            
              MT("emEscapedBySpaceIn",
                 "foo [em _bar _ hello_] world");
            
              MT("emEscapedBySpaceOut",
                 "foo _ bar[em _hello_]world");
            
              MT("emEscapedByNewline",
                 "foo",
                 "_ bar[em _hello_]world");
            
              // Unclosed emphasis characters
              // Instead of simply marking as EM / STRONG, it would be nice to have an
              // incomplete flag for EM and STRONG, that is styled slightly different.
              MT("emIncompleteAsterisk",
                 "foo [em *bar]");
            
              MT("emIncompleteUnderscore",
                 "foo [em _bar]");
            
              MT("strongAsterisk",
                 "[strong **foo**] bar");
            
              MT("strongUnderscore",
                 "[strong __foo__] bar");
            
              MT("emStrongAsterisk",
                 "[em *foo][em&strong **bar*][strong hello**] world");
            
              MT("emStrongUnderscore",
                 "[em _foo][em&strong __bar_][strong hello__] world");
            
              // "...same character must be used to open and close an emphasis span.""
              MT("emStrongMixed",
                 "[em _foo][em&strong **bar*hello__ world]");
            
              MT("emStrongMixed",
                 "[em *foo][em&strong __bar_hello** world]");
            
              // These characters should be escaped:
              // \   backslash
              // `   backtick
              // *   asterisk
              // _   underscore
              // {}  curly braces
              // []  square brackets
              // ()  parentheses
              // #   hash mark
              // +   plus sign
              // -   minus sign (hyphen)
              // .   dot
              // !   exclamation mark
            
              MT("escapeBacktick",
                 "foo \\`bar\\`");
            
              MT("doubleEscapeBacktick",
                 "foo \\\\[comment `bar\\\\`]");
            
              MT("escapeAsterisk",
                 "foo \\*bar\\*");
            
              MT("doubleEscapeAsterisk",
                 "foo \\\\[em *bar\\\\*]");
            
              MT("escapeUnderscore",
                 "foo \\_bar\\_");
            
              MT("doubleEscapeUnderscore",
                 "foo \\\\[em _bar\\\\_]");
            
              MT("escapeHash",
                 "\\# foo");
            
              MT("doubleEscapeHash",
                 "\\\\# foo");
            
              MT("escapeNewline",
                 "\\",
                 "[em *foo*]");
            
            
              // Tests to make sure GFM-specific things aren't getting through
            
              MT("taskList",
                 "[variable-2 * [ ]] bar]");
            
              MT("fencedCodeBlocks",
                 "[comment ```]",
                 "foo",
                 "[comment ```]");
            
              // Tests that require XML mode
            
              MT("xmlMode",
                 "[tag&bracket <][tag div][tag&bracket >]",
                 "*foo*",
                 "[tag&bracket <][tag http://github.com][tag&bracket />]",
                 "[tag&bracket </][tag div][tag&bracket >]",
                 "[link <http://github.com/>]");
            
              MT("xmlModeWithMarkdownInside",
                 "[tag&bracket <][tag div] [attribute markdown]=[string 1][tag&bracket >]",
                 "[em *foo*]",
                 "[link <http://github.com/>]",
                 "[tag </div>]",
                 "[link <http://github.com/>]",
                 "[tag&bracket <][tag div][tag&bracket >]",
                 "[tag&bracket </][tag div][tag&bracket >]");
            
            })();
            
        • mathematica
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Mathematica mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel=stylesheet href=../../lib/codemirror.css>
            <script src=../../lib/codemirror.js></script>
            <script src=../../addon/edit/matchbrackets.js></script>
            <script src=mathematica.js></script>
            <style type=text/css>
              .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
            </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Mathematica</a>
              </ul>
            </div>
            
            <article>
            <h2>Mathematica mode</h2>
            
            
            <textarea id="mathematicaCode">
            (* example Mathematica code *)
            (* Dualisiert wird anhand einer Polarität an einer
               Quadrik $x^t Q x = 0$ mit regulärer Matrix $Q$ (also
               mit $det(Q) \neq 0$), z.B. die Identitätsmatrix.
               $p$ ist eine Liste von Polynomen - ein Ideal. *)
            dualize::"singular" = "Q must be regular: found Det[Q]==0.";
            dualize[ Q_, p_ ] := Block[
                { m, n, xv, lv, uv, vars, polys, dual },
                If[Det[Q] == 0,
                  Message[dualize::"singular"],
                  m = Length[p];
                  n = Length[Q] - 1;
                  xv = Table[Subscript[x, i], {i, 0, n}];
                  lv = Table[Subscript[l, i], {i, 1, m}];
                  uv = Table[Subscript[u, i], {i, 0, n}];
                  (* Konstruiere Ideal polys. *)
                  If[m == 0,
                    polys = Q.uv,
                    polys = Join[p, Q.uv - Transpose[Outer[D, p, xv]].lv]
                    ];
                  (* Eliminiere die ersten n + 1 + m Variablen xv und lv
                     aus dem Ideal polys. *)
                  vars = Join[xv, lv];
                  dual = GroebnerBasis[polys, uv, vars];
                  (* Ersetze u mit x im Ergebnis. *)
                  ReplaceAll[dual, Rule[u, x]]
                  ]
                ]
            </textarea>
            
            <script>
              var mathematicaEditor = CodeMirror.fromTextArea(document.getElementById('mathematicaCode'), {
                mode: 'text/x-mathematica',
                lineNumbers: true,
                matchBrackets: true
              });
            </script>
            
            <p><strong>MIME types defined:</strong> <code>text/x-mathematica</code> (Mathematica).</p>
            </article>
            
          • mathematica.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Mathematica mode copyright (c) 2015 by Calin Barbat
            // Based on code by Patrick Scheibe (halirutan)
            // See: https://github.com/halirutan/Mathematica-Source-Highlighting/tree/master/src/lang-mma.js
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('mathematica', function(_config, _parserConfig) {
            
              // used pattern building blocks
              var Identifier = '[a-zA-Z\\$][a-zA-Z0-9\\$]*';
              var pBase      = "(?:\\d+)";
              var pFloat     = "(?:\\.\\d+|\\d+\\.\\d*|\\d+)";
              var pFloatBase = "(?:\\.\\w+|\\w+\\.\\w*|\\w+)";
              var pPrecision = "(?:`(?:`?"+pFloat+")?)";
            
              // regular expressions
              var reBaseForm        = new RegExp('(?:'+pBase+'(?:\\^\\^'+pFloatBase+pPrecision+'?(?:\\*\\^[+-]?\\d+)?))');
              var reFloatForm       = new RegExp('(?:' + pFloat + pPrecision + '?(?:\\*\\^[+-]?\\d+)?)');
              var reIdInContext     = new RegExp('(?:`?)(?:' + Identifier + ')(?:`(?:' + Identifier + '))*(?:`?)');
            
              function tokenBase(stream, state) {
                var ch;
            
                // get next character
                ch = stream.next();
            
                // string
                if (ch === '"') {
                  state.tokenize = tokenString;
                  return state.tokenize(stream, state);
                }
            
                // comment
                if (ch === '(') {
                  if (stream.eat('*')) {
                    state.commentLevel++;
                    state.tokenize = tokenComment;
                    return state.tokenize(stream, state);
                  }
                }
            
                // go back one character
                stream.backUp(1);
            
                // look for numbers
                // Numbers in a baseform
                if (stream.match(reBaseForm, true, false)) {
                  return 'number';
                }
            
                // Mathematica numbers. Floats (1.2, .2, 1.) can have optionally a precision (`float) or an accuracy definition
                // (``float). Note: while 1.2` is possible 1.2`` is not. At the end an exponent (float*^+12) can follow.
                if (stream.match(reFloatForm, true, false)) {
                  return 'number';
                }
            
                /* In[23] and Out[34] */
                if (stream.match(/(?:In|Out)\[[0-9]*\]/, true, false)) {
                  return 'atom';
                }
            
                // usage
                if (stream.match(/([a-zA-Z\$]+(?:`?[a-zA-Z0-9\$])*::usage)/, true, false)) {
                  return 'meta';
                }
            
                // message
                if (stream.match(/([a-zA-Z\$]+(?:`?[a-zA-Z0-9\$])*::[a-zA-Z\$][a-zA-Z0-9\$]*):?/, true, false)) {
                  return 'string-2';
                }
            
                // this makes a look-ahead match for something like variable:{_Integer}
                // the match is then forwarded to the mma-patterns tokenizer.
                if (stream.match(/([a-zA-Z\$][a-zA-Z0-9\$]*\s*:)(?:(?:[a-zA-Z\$][a-zA-Z0-9\$]*)|(?:[^:=>~@\^\&\*\)\[\]'\?,\|])).*/, true, false)) {
                  return 'variable-2';
                }
            
                // catch variables which are used together with Blank (_), BlankSequence (__) or BlankNullSequence (___)
                // Cannot start with a number, but can have numbers at any other position. Examples
                // blub__Integer, a1_, b34_Integer32
                if (stream.match(/[a-zA-Z\$][a-zA-Z0-9\$]*_+[a-zA-Z\$][a-zA-Z0-9\$]*/, true, false)) {
                  return 'variable-2';
                }
                if (stream.match(/[a-zA-Z\$][a-zA-Z0-9\$]*_+/, true, false)) {
                  return 'variable-2';
                }
                if (stream.match(/_+[a-zA-Z\$][a-zA-Z0-9\$]*/, true, false)) {
                  return 'variable-2';
                }
            
                // Named characters in Mathematica, like \[Gamma].
                if (stream.match(/\\\[[a-zA-Z\$][a-zA-Z0-9\$]*\]/, true, false)) {
                  return 'variable-3';
                }
            
                // Match all braces separately
                if (stream.match(/(?:\[|\]|{|}|\(|\))/, true, false)) {
                  return 'bracket';
                }
            
                // Catch Slots (#, ##, #3, ##9 and the V10 named slots #name). I have never seen someone using more than one digit after #, so we match
                // only one.
                if (stream.match(/(?:#[a-zA-Z\$][a-zA-Z0-9\$]*|#+[0-9]?)/, true, false)) {
                  return 'variable-2';
                }
            
                // Literals like variables, keywords, functions
                if (stream.match(reIdInContext, true, false)) {
                  return 'keyword';
                }
            
                // operators. Note that operators like @@ or /; are matched separately for each symbol.
                if (stream.match(/(?:\\|\+|\-|\*|\/|,|;|\.|:|@|~|=|>|<|&|\||_|`|'|\^|\?|!|%)/, true, false)) {
                  return 'operator';
                }
            
                // everything else is an error
                return 'error';
              }
            
              function tokenString(stream, state) {
                var next, end = false, escaped = false;
                while ((next = stream.next()) != null) {
                  if (next === '"' && !escaped) {
                    end = true;
                    break;
                  }
                  escaped = !escaped && next === '\\';
                }
                if (end && !escaped) {
                  state.tokenize = tokenBase;
                }
                return 'string';
              };
            
              function tokenComment(stream, state) {
                var prev, next;
                while(state.commentLevel > 0 && (next = stream.next()) != null) {
                  if (prev === '(' && next === '*') state.commentLevel++;
                  if (prev === '*' && next === ')') state.commentLevel--;
                  prev = next;
                }
                if (state.commentLevel <= 0) {
                  state.tokenize = tokenBase;
                }
                return 'comment';
              }
            
              return {
                startState: function() {return {tokenize: tokenBase, commentLevel: 0};},
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  return state.tokenize(stream, state);
                },
                blockCommentStart: "(*",
                blockCommentEnd: "*)"
              };
            });
            
            CodeMirror.defineMIME('text/x-mathematica', {
              name: 'mathematica'
            });
            
            });
            
        • mirc
          • index.html
            <!doctype html>
            
            <title>CodeMirror: mIRC mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/twilight.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="mirc.js"></script>
            <style>.CodeMirror {border: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">mIRC</a>
              </ul>
            </div>
            
            <article>
            <h2>mIRC mode</h2>
            <form><textarea id="code" name="code">
            ;AKA Nick Tracker by Ford_Lawnmower irc.GeekShed.net #Script-Help
            ;*****************************************************************************;
            ;**Start Setup
            ;Change JoinDisplay, below, for On Join AKA Display. On = 1 - Off = 0
            alias -l JoinDisplay { return 1 }
            ;Change MaxNicks, below, to the number of nicknames you want to store for each hostmask. I wouldn't go over 400 with this ;/
            alias -l MaxNicks { return 20 }
            ;Change AKALogo, below, To the text you want displayed before each AKA result.
            alias -l AKALogo { return 06 05A06K07A 06 }
            ;**End Setup
            ;*****************************************************************************;
            On *:Join:#: {
              if ($nick == $me) { .timer 1 1 ialupdateCheck $chan }
              NickNamesAdd $nick $+($network,$wildsite)
              if ($JoinDisplay) { .timerNickNames $+ $nick 1 2 NickNames.display $nick $chan $network $wildsite }
            }
            on *:Nick: { NickNamesAdd $newnick $+($network,$wildsite) $nick }
            alias -l NickNames.display {
              if ($gettok($hget(NickNames,$+($3,$4)),0,126) > 1) {
                echo -g $2 $AKALogo $+(09,$1) $AKALogo 07 $mid($replace($hget(NickNames,$+($3,$4)),$chr(126),$chr(44)),2,-1)
              }
            }
            alias -l NickNamesAdd {
              if ($hget(NickNames,$2)) {
                if (!$regex($hget(NickNames,$2),/~\Q $+ $replacecs($1,\E,\E\\E\Q) $+ \E~/i)) {
                  if ($gettok($hget(NickNames,$2),0,126) <= $MaxNicks) {
                    hadd NickNames $2 $+($hget(NickNames,$2),$1,~)
                  }
                  else {
                    hadd NickNames $2 $+($mid($hget(NickNames,$2),$pos($hget(NickNames,$2),~,2)),$1,~)
                  }
                }
              }
              else {
                hadd -m NickNames $2 $+(~,$1,~,$iif($3,$+($3,~)))
              }
            }
            alias -l Fix.All.MindUser {
              var %Fix.Count = $hfind(NickNames,/[^~]+[0-9]{4}~/,0,r).data
              while (%Fix.Count) {
                if ($Fix.MindUser($hget(NickNames,$hfind(NickNames,/[^~]+[0-9]{4}~/,%Fix.Count,r).data))) {
                  echo -ag Record %Fix.Count - $v1 - Was Cleaned
                  hadd NickNames $hfind(NickNames,/[^~]+[0-9]{4}~/,%Fix.Count,r).data $v1
                }
                dec %Fix.Count
              }
            }
            alias -l Fix.MindUser { return $regsubex($1,/[^~]+[0-9]{4}~/g,$null) }
            menu nicklist,query {
              -
              .AKA
              ..Check $$1: {
                if ($gettok($hget(NickNames,$+($network,$address($1,2))),0,126) > 1) {
                  NickNames.display $1 $active $network $address($1,2)
                }
                else { echo -ag $AKALogo $+(09,$1) 07has not been known by any other nicknames while I have been watching. }
              }
              ..Cleanup $$1:hadd NickNames $+($network,$address($1,2)) $fix.minduser($hget(NickNames,$+($network,$address($1,2))))
              ..Clear $$1:hadd NickNames $+($network,$address($1,2)) $+(~,$1,~)
              ..AKA Search Dialog:dialog $iif($dialog(AKA_Search),-v,-m) AKA_Search AKA_Search
              -
            }
            menu status,channel {
              -
              .AKA
              ..AKA Search Dialog:dialog $iif($dialog(AKA_Search),-v,-m) AKA_Search AKA_Search
              ..Clean All Records:Fix.All.Minduser
              -
            }
            dialog AKA_Search {
              title "AKA Search Engine"
              size -1 -1 206 221
              option dbu
              edit "", 1, 8 5 149 10, autohs
              button "Search", 2, 163 4 32 12
              radio "Search HostMask", 4, 61 22 55 10
              radio "Search Nicknames", 5, 123 22 56 10
              list 6, 8 38 190 169, sort extsel vsbar
              button "Check Selected", 7, 67 206 40 12
              button "Close", 8, 160 206 38 12, cancel
              box "Search Type", 3, 11 17 183 18
              button "Copy to Clipboard", 9, 111 206 46 12
            }
            On *:Dialog:Aka_Search:init:*: { did -c $dname 5 }
            On *:Dialog:Aka_Search:Sclick:2,7,9: {
              if ($did == 2) && ($did($dname,1)) {
                did -r $dname 6
                var %search $+(*,$v1,*), %type $iif($did($dname,5).state,data,item), %matches = $hfind(NickNames,%search,0,w). [ $+ [ %type ] ]
                while (%matches) {
                  did -a $dname 6 $hfind(NickNames,%search,%matches,w). [ $+ [ %type ] ]
                  dec %matches
                }
                did -c $dname 6 1
              }
              elseif ($did == 7) && ($did($dname,6).seltext) { echo -ga $AKALogo 07 $mid($replace($hget(NickNames,$v1),$chr(126),$chr(44)),2,-1) }
              elseif ($did == 9) && ($did($dname,6).seltext) { clipboard $mid($v1,$pos($v1,*,1)) }
            }
            On *:Start:{
              if (!$hget(NickNames)) { hmake NickNames 10 }
              if ($isfile(NickNames.hsh)) { hload  NickNames NickNames.hsh }
            }
            On *:Exit: { if ($hget(NickNames)) { hsave NickNames NickNames.hsh } }
            On *:Disconnect: { if ($hget(NickNames)) { hsave NickNames NickNames.hsh } }
            On *:Unload: { hfree NickNames }
            alias -l ialupdateCheck {
              inc -z $+(%,ialupdateCheck,$network) $calc($nick($1,0) / 4)
              ;If your ial is already being updated on join .who $1 out.
              ;If you are using /names to update ial you will still need this line.
              .who $1
            }
            Raw 352:*: {
              if ($($+(%,ialupdateCheck,$network),2)) haltdef
              NickNamesAdd $6 $+($network,$address($6,2))
            }
            Raw 315:*: {
              if ($($+(%,ialupdateCheck,$network),2)) haltdef
            }
            
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    theme: "twilight",
                    lineNumbers: true,
                    matchBrackets: true,
                    indentUnit: 4,
                    mode: "text/mirc"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/mirc</code>.</p>
            
              </article>
            
          • mirc.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            //mIRC mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMIME("text/mirc", "mirc");
            CodeMirror.defineMode("mirc", function() {
              function parseWords(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
              var specials = parseWords("$! $$ $& $? $+ $abook $abs $active $activecid " +
                                        "$activewid $address $addtok $agent $agentname $agentstat $agentver " +
                                        "$alias $and $anick $ansi2mirc $aop $appactive $appstate $asc $asctime " +
                                        "$asin $atan $avoice $away $awaymsg $awaytime $banmask $base $bfind " +
                                        "$binoff $biton $bnick $bvar $bytes $calc $cb $cd $ceil $chan $chanmodes " +
                                        "$chantypes $chat $chr $cid $clevel $click $cmdbox $cmdline $cnick $color " +
                                        "$com $comcall $comchan $comerr $compact $compress $comval $cos $count " +
                                        "$cr $crc $creq $crlf $ctime $ctimer $ctrlenter $date $day $daylight " +
                                        "$dbuh $dbuw $dccignore $dccport $dde $ddename $debug $decode $decompress " +
                                        "$deltok $devent $dialog $did $didreg $didtok $didwm $disk $dlevel $dll " +
                                        "$dllcall $dname $dns $duration $ebeeps $editbox $emailaddr $encode $error " +
                                        "$eval $event $exist $feof $ferr $fgetc $file $filename $filtered $finddir " +
                                        "$finddirn $findfile $findfilen $findtok $fline $floor $fopen $fread $fserve " +
                                        "$fulladdress $fulldate $fullname $fullscreen $get $getdir $getdot $gettok $gmt " +
                                        "$group $halted $hash $height $hfind $hget $highlight $hnick $hotline " +
                                        "$hotlinepos $ial $ialchan $ibl $idle $iel $ifmatch $ignore $iif $iil " +
                                        "$inelipse $ini $inmidi $inpaste $inpoly $input $inrect $inroundrect " +
                                        "$insong $instok $int $inwave $ip $isalias $isbit $isdde $isdir $isfile " +
                                        "$isid $islower $istok $isupper $keychar $keyrpt $keyval $knick $lactive " +
                                        "$lactivecid $lactivewid $left $len $level $lf $line $lines $link $lock " +
                                        "$lock $locked $log $logstamp $logstampfmt $longfn $longip $lower $ltimer " +
                                        "$maddress $mask $matchkey $matchtok $md5 $me $menu $menubar $menucontext " +
                                        "$menutype $mid $middir $mircdir $mircexe $mircini $mklogfn $mnick $mode " +
                                        "$modefirst $modelast $modespl $mouse $msfile $network $newnick $nick $nofile " +
                                        "$nopath $noqt $not $notags $notify $null $numeric $numok $oline $onpoly " +
                                        "$opnick $or $ord $os $passivedcc $pic $play $pnick $port $portable $portfree " +
                                        "$pos $prefix $prop $protect $puttok $qt $query $rand $r $rawmsg $read $readomo " +
                                        "$readn $regex $regml $regsub $regsubex $remove $remtok $replace $replacex " +
                                        "$reptok $result $rgb $right $round $scid $scon $script $scriptdir $scriptline " +
                                        "$sdir $send $server $serverip $sfile $sha1 $shortfn $show $signal $sin " +
                                        "$site $sline $snick $snicks $snotify $sock $sockbr $sockerr $sockname " +
                                        "$sorttok $sound $sqrt $ssl $sreq $sslready $status $strip $str $stripped " +
                                        "$syle $submenu $switchbar $tan $target $ticks $time $timer $timestamp " +
                                        "$timestampfmt $timezone $tip $titlebar $toolbar $treebar $trust $ulevel " +
                                        "$ulist $upper $uptime $url $usermode $v1 $v2 $var $vcmd $vcmdstat $vcmdver " +
                                        "$version $vnick $vol $wid $width $wildsite $wildtok $window $wrap $xor");
              var keywords = parseWords("abook ajinvite alias aline ame amsg anick aop auser autojoin avoice " +
                                        "away background ban bcopy beep bread break breplace bset btrunc bunset bwrite " +
                                        "channel clear clearall cline clipboard close cnick color comclose comopen " +
                                        "comreg continue copy creq ctcpreply ctcps dcc dccserver dde ddeserver " +
                                        "debug dec describe dialog did didtok disable disconnect dlevel dline dll " +
                                        "dns dqwindow drawcopy drawdot drawfill drawline drawpic drawrect drawreplace " +
                                        "drawrot drawsave drawscroll drawtext ebeeps echo editbox emailaddr enable " +
                                        "events exit fclose filter findtext finger firewall flash flist flood flush " +
                                        "flushini font fopen fseek fsend fserve fullname fwrite ghide gload gmove " +
                                        "gopts goto gplay gpoint gqreq groups gshow gsize gstop gtalk gunload hadd " +
                                        "halt haltdef hdec hdel help hfree hinc hload hmake hop hsave ial ialclear " +
                                        "ialmark identd if ignore iline inc invite iuser join kick linesep links list " +
                                        "load loadbuf localinfo log mdi me menubar mkdir mnick mode msg nick noop notice " +
                                        "notify omsg onotice part partall pdcc perform play playctrl pop protect pvoice " +
                                        "qme qmsg query queryn quit raw reload remini remote remove rename renwin " +
                                        "reseterror resetidle return rlevel rline rmdir run ruser save savebuf saveini " +
                                        "say scid scon server set showmirc signam sline sockaccept sockclose socklist " +
                                        "socklisten sockmark sockopen sockpause sockread sockrename sockudp sockwrite " +
                                        "sound speak splay sreq strip switchbar timer timestamp titlebar tnick tokenize " +
                                        "toolbar topic tray treebar ulist unload unset unsetall updatenl url uwho " +
                                        "var vcadd vcmd vcrem vol while whois window winhelp write writeint if isalnum " +
                                        "isalpha isaop isavoice isban ischan ishop isignore isin isincs isletter islower " +
                                        "isnotify isnum ison isop isprotect isreg isupper isvoice iswm iswmcs " +
                                        "elseif else goto menu nicklist status title icon size option text edit " +
                                        "button check radio box scroll list combo link tab item");
              var functions = parseWords("if elseif else and not or eq ne in ni for foreach while switch");
              var isOperatorChar = /[+\-*&%=<>!?^\/\|]/;
              function chain(stream, state, f) {
                state.tokenize = f;
                return f(stream, state);
              }
              function tokenBase(stream, state) {
                var beforeParams = state.beforeParams;
                state.beforeParams = false;
                var ch = stream.next();
                if (/[\[\]{}\(\),\.]/.test(ch)) {
                  if (ch == "(" && beforeParams) state.inParams = true;
                  else if (ch == ")") state.inParams = false;
                  return null;
                }
                else if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return "number";
                }
                else if (ch == "\\") {
                  stream.eat("\\");
                  stream.eat(/./);
                  return "number";
                }
                else if (ch == "/" && stream.eat("*")) {
                  return chain(stream, state, tokenComment);
                }
                else if (ch == ";" && stream.match(/ *\( *\(/)) {
                  return chain(stream, state, tokenUnparsed);
                }
                else if (ch == ";" && !state.inParams) {
                  stream.skipToEnd();
                  return "comment";
                }
                else if (ch == '"') {
                  stream.eat(/"/);
                  return "keyword";
                }
                else if (ch == "$") {
                  stream.eatWhile(/[$_a-z0-9A-Z\.:]/);
                  if (specials && specials.propertyIsEnumerable(stream.current().toLowerCase())) {
                    return "keyword";
                  }
                  else {
                    state.beforeParams = true;
                    return "builtin";
                  }
                }
                else if (ch == "%") {
                  stream.eatWhile(/[^,^\s^\(^\)]/);
                  state.beforeParams = true;
                  return "string";
                }
                else if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                else {
                  stream.eatWhile(/[\w\$_{}]/);
                  var word = stream.current().toLowerCase();
                  if (keywords && keywords.propertyIsEnumerable(word))
                    return "keyword";
                  if (functions && functions.propertyIsEnumerable(word)) {
                    state.beforeParams = true;
                    return "keyword";
                  }
                  return null;
                }
              }
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
              function tokenUnparsed(stream, state) {
                var maybeEnd = 0, ch;
                while (ch = stream.next()) {
                  if (ch == ";" && maybeEnd == 2) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  if (ch == ")")
                    maybeEnd++;
                  else if (ch != " ")
                    maybeEnd = 0;
                }
                return "meta";
              }
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase,
                    beforeParams: false,
                    inParams: false
                  };
                },
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  return state.tokenize(stream, state);
                }
              };
            });
            
            });
            
        • mllike
          • index.html
            <!doctype html>
            
            <title>CodeMirror: ML-like mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel=stylesheet href=../../lib/codemirror.css>
            <script src=../../lib/codemirror.js></script>
            <script src=../../addon/edit/matchbrackets.js></script>
            <script src=mllike.js></script>
            <style type=text/css>
              .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
            </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">ML-like</a>
              </ul>
            </div>
            
            <article>
            <h2>OCaml mode</h2>
            
            
            <textarea id="ocamlCode">
            (* Summing a list of integers *)
            let rec sum xs =
              match xs with
                | []       -&gt; 0
                | x :: xs' -&gt; x + sum xs'
            
            (* Quicksort *)
            let rec qsort = function
               | [] -&gt; []
               | pivot :: rest -&gt;
                   let is_less x = x &lt; pivot in
                   let left, right = List.partition is_less rest in
                   qsort left @ [pivot] @ qsort right
            
            (* Fibonacci Sequence *)
            let rec fib_aux n a b =
              match n with
              | 0 -&gt; a
              | _ -&gt; fib_aux (n - 1) (a + b) a
            let fib n = fib_aux n 0 1
            
            (* Birthday paradox *)
            let year_size = 365.
            
            let rec birthday_paradox prob people =
                let prob' = (year_size -. float people) /. year_size *. prob  in
                if prob' &lt; 0.5 then
                    Printf.printf "answer = %d\n" (people+1)
                else
                    birthday_paradox prob' (people+1) ;;
            
            birthday_paradox 1.0 1
            
            (* Church numerals *)
            let zero f x = x
            let succ n f x = f (n f x)
            let one = succ zero
            let two = succ (succ zero)
            let add n1 n2 f x = n1 f (n2 f x)
            let to_string n = n (fun k -&gt; "S" ^ k) "0"
            let _ = to_string (add (succ two) two)
            
            (* Elementary functions *)
            let square x = x * x;;
            let rec fact x =
              if x &lt;= 1 then 1 else x * fact (x - 1);;
            
            (* Automatic memory management *)
            let l = 1 :: 2 :: 3 :: [];;
            [1; 2; 3];;
            5 :: l;;
            
            (* Polymorphism: sorting lists *)
            let rec sort = function
              | [] -&gt; []
              | x :: l -&gt; insert x (sort l)
            
            and insert elem = function
              | [] -&gt; [elem]
              | x :: l -&gt;
                  if elem &lt; x then elem :: x :: l else x :: insert elem l;;
            
            (* Imperative features *)
            let add_polynom p1 p2 =
              let n1 = Array.length p1
              and n2 = Array.length p2 in
              let result = Array.create (max n1 n2) 0 in
              for i = 0 to n1 - 1 do result.(i) &lt;- p1.(i) done;
              for i = 0 to n2 - 1 do result.(i) &lt;- result.(i) + p2.(i) done;
              result;;
            add_polynom [| 1; 2 |] [| 1; 2; 3 |];;
            
            (* We may redefine fact using a reference cell and a for loop *)
            let fact n =
              let result = ref 1 in
              for i = 2 to n do
                result := i * !result
               done;
               !result;;
            fact 5;;
            
            (* Triangle (graphics) *)
            let () =
              ignore( Glut.init Sys.argv );
              Glut.initDisplayMode ~double_buffer:true ();
              ignore (Glut.createWindow ~title:"OpenGL Demo");
              let angle t = 10. *. t *. t in
              let render () =
                GlClear.clear [ `color ];
                GlMat.load_identity ();
                GlMat.rotate ~angle: (angle (Sys.time ())) ~z:1. ();
                GlDraw.begins `triangles;
                List.iter GlDraw.vertex2 [-1., -1.; 0., 1.; 1., -1.];
                GlDraw.ends ();
                Glut.swapBuffers () in
              GlMat.mode `modelview;
              Glut.displayFunc ~cb:render;
              Glut.idleFunc ~cb:(Some Glut.postRedisplay);
              Glut.mainLoop ()
            
            (* A Hundred Lines of Caml - http://caml.inria.fr/about/taste.en.html *)
            (* OCaml page on Wikipedia - http://en.wikipedia.org/wiki/OCaml *)
            </textarea>
            
            <h2>F# mode</h2>
            <textarea id="fsharpCode">
            module CodeMirror.FSharp
            
            let rec fib = function
                | 0 -> 0
                | 1 -> 1
                | n -> fib (n - 1) + fib (n - 2)
            
            type Point =
                {
                    x : int
                    y : int
                }
            
            type Color =
                | Red
                | Green
                | Blue
            
            [0 .. 10]
            |> List.map ((+) 2)
            |> List.fold (fun x y -> x + y) 0
            |> printf "%i"
            </textarea>
            
            
            <script>
              var ocamlEditor = CodeMirror.fromTextArea(document.getElementById('ocamlCode'), {
                mode: 'text/x-ocaml',
                lineNumbers: true,
                matchBrackets: true
              });
            
              var fsharpEditor = CodeMirror.fromTextArea(document.getElementById('fsharpCode'), {
                mode: 'text/x-fsharp',
                lineNumbers: true,
                matchBrackets: true
              });
            </script>
            
            <p><strong>MIME types defined:</strong> <code>text/x-ocaml</code> (OCaml) and <code>text/x-fsharp</code> (F#).</p>
            </article>
            
          • mllike.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('mllike', function(_config, parserConfig) {
              var words = {
                'let': 'keyword',
                'rec': 'keyword',
                'in': 'keyword',
                'of': 'keyword',
                'and': 'keyword',
                'if': 'keyword',
                'then': 'keyword',
                'else': 'keyword',
                'for': 'keyword',
                'to': 'keyword',
                'while': 'keyword',
                'do': 'keyword',
                'done': 'keyword',
                'fun': 'keyword',
                'function': 'keyword',
                'val': 'keyword',
                'type': 'keyword',
                'mutable': 'keyword',
                'match': 'keyword',
                'with': 'keyword',
                'try': 'keyword',
                'open': 'builtin',
                'ignore': 'builtin',
                'begin': 'keyword',
                'end': 'keyword'
              };
            
              var extraWords = parserConfig.extraWords || {};
              for (var prop in extraWords) {
                if (extraWords.hasOwnProperty(prop)) {
                  words[prop] = parserConfig.extraWords[prop];
                }
              }
            
              function tokenBase(stream, state) {
                var ch = stream.next();
            
                if (ch === '"') {
                  state.tokenize = tokenString;
                  return state.tokenize(stream, state);
                }
                if (ch === '(') {
                  if (stream.eat('*')) {
                    state.commentLevel++;
                    state.tokenize = tokenComment;
                    return state.tokenize(stream, state);
                  }
                }
                if (ch === '~') {
                  stream.eatWhile(/\w/);
                  return 'variable-2';
                }
                if (ch === '`') {
                  stream.eatWhile(/\w/);
                  return 'quote';
                }
                if (ch === '/' && parserConfig.slashComments && stream.eat('/')) {
                  stream.skipToEnd();
                  return 'comment';
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\d]/);
                  if (stream.eat('.')) {
                    stream.eatWhile(/[\d]/);
                  }
                  return 'number';
                }
                if ( /[+\-*&%=<>!?|]/.test(ch)) {
                  return 'operator';
                }
                stream.eatWhile(/\w/);
                var cur = stream.current();
                return words.hasOwnProperty(cur) ? words[cur] : 'variable';
              }
            
              function tokenString(stream, state) {
                var next, end = false, escaped = false;
                while ((next = stream.next()) != null) {
                  if (next === '"' && !escaped) {
                    end = true;
                    break;
                  }
                  escaped = !escaped && next === '\\';
                }
                if (end && !escaped) {
                  state.tokenize = tokenBase;
                }
                return 'string';
              };
            
              function tokenComment(stream, state) {
                var prev, next;
                while(state.commentLevel > 0 && (next = stream.next()) != null) {
                  if (prev === '(' && next === '*') state.commentLevel++;
                  if (prev === '*' && next === ')') state.commentLevel--;
                  prev = next;
                }
                if (state.commentLevel <= 0) {
                  state.tokenize = tokenBase;
                }
                return 'comment';
              }
            
              return {
                startState: function() {return {tokenize: tokenBase, commentLevel: 0};},
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  return state.tokenize(stream, state);
                },
            
                blockCommentStart: "(*",
                blockCommentEnd: "*)",
                lineComment: parserConfig.slashComments ? "//" : null
              };
            });
            
            CodeMirror.defineMIME('text/x-ocaml', {
              name: 'mllike',
              extraWords: {
                'succ': 'keyword',
                'trace': 'builtin',
                'exit': 'builtin',
                'print_string': 'builtin',
                'print_endline': 'builtin',
                'true': 'atom',
                'false': 'atom',
                'raise': 'keyword'
              }
            });
            
            CodeMirror.defineMIME('text/x-fsharp', {
              name: 'mllike',
              extraWords: {
                'abstract': 'keyword',
                'as': 'keyword',
                'assert': 'keyword',
                'base': 'keyword',
                'class': 'keyword',
                'default': 'keyword',
                'delegate': 'keyword',
                'downcast': 'keyword',
                'downto': 'keyword',
                'elif': 'keyword',
                'exception': 'keyword',
                'extern': 'keyword',
                'finally': 'keyword',
                'global': 'keyword',
                'inherit': 'keyword',
                'inline': 'keyword',
                'interface': 'keyword',
                'internal': 'keyword',
                'lazy': 'keyword',
                'let!': 'keyword',
                'member' : 'keyword',
                'module': 'keyword',
                'namespace': 'keyword',
                'new': 'keyword',
                'null': 'keyword',
                'override': 'keyword',
                'private': 'keyword',
                'public': 'keyword',
                'return': 'keyword',
                'return!': 'keyword',
                'select': 'keyword',
                'static': 'keyword',
                'struct': 'keyword',
                'upcast': 'keyword',
                'use': 'keyword',
                'use!': 'keyword',
                'val': 'keyword',
                'when': 'keyword',
                'yield': 'keyword',
                'yield!': 'keyword',
            
                'List': 'builtin',
                'Seq': 'builtin',
                'Map': 'builtin',
                'Set': 'builtin',
                'int': 'builtin',
                'string': 'builtin',
                'raise': 'builtin',
                'failwith': 'builtin',
                'not': 'builtin',
                'true': 'builtin',
                'false': 'builtin'
              },
              slashComments: true
            });
            
            });
            
        • modelica
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Modelica mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <link rel="stylesheet" href="../../addon/hint/show-hint.css">
            <script src="../../addon/hint/show-hint.js"></script>
            <script src="modelica.js"></script>
            <style>.CodeMirror {border: 2px inset #dee;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Modelica</a>
              </ul>
            </div>
            
            <article>
            <h2>Modelica mode</h2>
            
            <div><textarea id="modelica">
            model BouncingBall
              parameter Real e = 0.7;
              parameter Real g = 9.81;
              Real h(start=1);
              Real v;
              Boolean flying(start=true);
              Boolean impact;
              Real v_new;
            equation
              impact = h <= 0.0;
              der(v) = if flying then -g else 0;
              der(h) = v;
              when {h <= 0.0 and v <= 0.0, impact} then
                v_new = if edge(impact) then -e*pre(v) else 0;
                flying = v_new > 0;
                reinit(v, v_new);
              end when;
              annotation (uses(Modelica(version="3.2")));
            end BouncingBall;
            </textarea></div>
            
                <script>
                  var modelicaEditor = CodeMirror.fromTextArea(document.getElementById("modelica"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-modelica"
                  });
                  var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
                  CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
                </script>
            
                <p>Simple mode that tries to handle Modelica as well as it can.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-modelica</code>
                (Modlica code).</p>
            </article>
            
          • modelica.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Modelica support for CodeMirror, copyright (c) by Lennart Ochel
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })
            
            (function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("modelica", function(config, parserConfig) {
            
                var indentUnit = config.indentUnit;
                var keywords = parserConfig.keywords || {};
                var builtin = parserConfig.builtin || {};
                var atoms = parserConfig.atoms || {};
            
                var isSingleOperatorChar = /[;=\(:\),{}.*<>+\-\/^\[\]]/;
                var isDoubleOperatorChar = /(:=|<=|>=|==|<>|\.\+|\.\-|\.\*|\.\/|\.\^)/;
                var isDigit = /[0-9]/;
                var isNonDigit = /[_a-zA-Z]/;
            
                function tokenLineComment(stream, state) {
                  stream.skipToEnd();
                  state.tokenize = null;
                  return "comment";
                }
            
                function tokenBlockComment(stream, state) {
                  var maybeEnd = false, ch;
                  while (ch = stream.next()) {
                    if (maybeEnd && ch == "/") {
                      state.tokenize = null;
                      break;
                    }
                    maybeEnd = (ch == "*");
                  }
                  return "comment";
                }
            
                function tokenString(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == '"' && !escaped) {
                      state.tokenize = null;
                      state.sol = false;
                      break;
                    }
                    escaped = !escaped && ch == "\\";
                  }
            
                  return "string";
                }
            
                function tokenIdent(stream, state) {
                  stream.eatWhile(isDigit);
                  while (stream.eat(isDigit) || stream.eat(isNonDigit)) { }
            
            
                  var cur = stream.current();
            
                  if(state.sol && (cur == "package" || cur == "model" || cur == "when" || cur == "connector")) state.level++;
                  else if(state.sol && cur == "end" && state.level > 0) state.level--;
            
                  state.tokenize = null;
                  state.sol = false;
            
                  if (keywords.propertyIsEnumerable(cur)) return "keyword";
                  else if (builtin.propertyIsEnumerable(cur)) return "builtin";
                  else if (atoms.propertyIsEnumerable(cur)) return "atom";
                  else return "variable";
                }
            
                function tokenQIdent(stream, state) {
                  while (stream.eat(/[^']/)) { }
            
                  state.tokenize = null;
                  state.sol = false;
            
                  if(stream.eat("'"))
                    return "variable";
                  else
                    return "error";
                }
            
                function tokenUnsignedNuber(stream, state) {
                  stream.eatWhile(isDigit);
                  if (stream.eat('.')) {
                    stream.eatWhile(isDigit);
                  }
                  if (stream.eat('e') || stream.eat('E')) {
                    if (!stream.eat('-'))
                      stream.eat('+');
                    stream.eatWhile(isDigit);
                  }
            
                  state.tokenize = null;
                  state.sol = false;
                  return "number";
                }
            
                // Interface
                return {
                  startState: function() {
                    return {
                      tokenize: null,
                      level: 0,
                      sol: true
                    };
                  },
            
                  token: function(stream, state) {
                    if(state.tokenize != null) {
                      return state.tokenize(stream, state);
                    }
            
                    if(stream.sol()) {
                      state.sol = true;
                    }
            
                    // WHITESPACE
                    if(stream.eatSpace()) {
                      state.tokenize = null;
                      return null;
                    }
            
                    var ch = stream.next();
            
                    // LINECOMMENT
                    if(ch == '/' && stream.eat('/')) {
                      state.tokenize = tokenLineComment;
                    }
                    // BLOCKCOMMENT
                    else if(ch == '/' && stream.eat('*')) {
                      state.tokenize = tokenBlockComment;
                    }
                    // TWO SYMBOL TOKENS
                    else if(isDoubleOperatorChar.test(ch+stream.peek())) {
                      stream.next();
                      state.tokenize = null;
                      return "operator";
                    }
                    // SINGLE SYMBOL TOKENS
                    else if(isSingleOperatorChar.test(ch)) {
                      state.tokenize = null;
                      return "operator";
                    }
                    // IDENT
                    else if(isNonDigit.test(ch)) {
                      state.tokenize = tokenIdent;
                    }
                    // Q-IDENT
                    else if(ch == "'" && stream.peek() && stream.peek() != "'") {
                      state.tokenize = tokenQIdent;
                    }
                    // STRING
                    else if(ch == '"') {
                      state.tokenize = tokenString;
                    }
                    // UNSIGNED_NUBER
                    else if(isDigit.test(ch)) {
                      state.tokenize = tokenUnsignedNuber;
                    }
                    // ERROR
                    else {
                      state.tokenize = null;
                      return "error";
                    }
            
                    return state.tokenize(stream, state);
                  },
            
                  indent: function(state, textAfter) {
                    if (state.tokenize != null) return CodeMirror.Pass;
            
                    var level = state.level;
                    if(/(algorithm)/.test(textAfter)) level--;
                    if(/(equation)/.test(textAfter)) level--;
                    if(/(initial algorithm)/.test(textAfter)) level--;
                    if(/(initial equation)/.test(textAfter)) level--;
                    if(/(end)/.test(textAfter)) level--;
            
                    if(level > 0)
                      return indentUnit*level;
                    else
                      return 0;
                  },
            
                  blockCommentStart: "/*",
                  blockCommentEnd: "*/",
                  lineComment: "//"
                };
              });
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i=0; i<words.length; ++i)
                  obj[words[i]] = true;
                return obj;
              }
            
              var modelicaKeywords = "algorithm and annotation assert block break class connect connector constant constrainedby der discrete each else elseif elsewhen encapsulated end enumeration equation expandable extends external false final flow for function if import impure in initial inner input loop model not operator or outer output package parameter partial protected public pure record redeclare replaceable return stream then true type when while within";
              var modelicaBuiltin = "abs acos actualStream asin atan atan2 cardinality ceil cos cosh delay div edge exp floor getInstanceName homotopy inStream integer log log10 mod pre reinit rem semiLinear sign sin sinh spatialDistribution sqrt tan tanh";
              var modelicaAtoms = "Real Boolean Integer String";
            
              function def(mimes, mode) {
                if (typeof mimes == "string")
                  mimes = [mimes];
            
                var words = [];
            
                function add(obj) {
                  if (obj)
                    for (var prop in obj)
                      if (obj.hasOwnProperty(prop))
                        words.push(prop);
                }
            
                add(mode.keywords);
                add(mode.builtin);
                add(mode.atoms);
            
                if (words.length) {
                  mode.helperType = mimes[0];
                  CodeMirror.registerHelper("hintWords", mimes[0], words);
                }
            
                for (var i=0; i<mimes.length; ++i)
                  CodeMirror.defineMIME(mimes[i], mode);
              }
            
              def(["text/x-modelica"], {
                name: "modelica",
                keywords: words(modelicaKeywords),
                builtin: words(modelicaBuiltin),
                atoms: words(modelicaAtoms)
              });
            });
            
        • mumps
          • index.html
            <!doctype html>
            
            <title>CodeMirror: MUMPS mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="mumps.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">MUMPS</a>
              </ul>
            </div>
            
            <article>
            <h2>MUMPS mode</h2>
            
            
            <div><textarea id="code" name="code">
             ; Lloyd Milligan
             ; 03-30-2015
             ;
             ; MUMPS support for Code Mirror - Excerpts below from routine ^XUS
             ;
            CHECKAV(X1) ;Check A/V code return DUZ or Zero. (Called from XUSRB)
             N %,%1,X,Y,IEN,DA,DIK
             S IEN=0
             ;Start CCOW
             I $E(X1,1,7)="~~TOK~~" D  Q:IEN>0 IEN
             . I $E(X1,8,9)="~1" S IEN=$$CHKASH^XUSRB4($E(X1,8,255))
             . I $E(X1,8,9)="~2" S IEN=$$CHKCCOW^XUSRB4($E(X1,8,255))
             . Q
             ;End CCOW
             S X1=$$UP(X1) S:X1[":" XUTT=1,X1=$TR(X1,":")
             S X=$P(X1,";") Q:X="^" -1 S:XUF %1="Access: "_X
             Q:X'?1.20ANP 0
             S X=$$EN^XUSHSH(X) I '$D(^VA(200,"A",X)) D LBAV Q 0
             S %1="",IEN=$O(^VA(200,"A",X,0)),XUF(.3)=IEN D USER(IEN)
             S X=$P(X1,";",2) S:XUF %1="Verify: "_X S X=$$EN^XUSHSH(X)
             I $P(XUSER(1),"^",2)'=X D LBAV Q 0
             I $G(XUFAC(1)) S DIK="^XUSEC(4,",DA=XUFAC(1) D ^DIK
             Q IEN
             ;
             ; Spell out commands
             ;
            SET2() ;EF. Return error code (also called from XUSRB)
             NEW %,X
             SET XUNOW=$$HTFM^XLFDT($H),DT=$P(XUNOW,".")
             KILL DUZ,XUSER
             SET (DUZ,DUZ(2))=0,(DUZ(0),DUZ("AG"),XUSER(0),XUSER(1),XUTT,%UCI)=""
             SET %=$$INHIBIT^XUSRB() IF %>0 QUIT %
             SET X=$G(^%ZIS(1,XUDEV,"XUS")),XU1=$G(^(1))
             IF $L(X) FOR I=1:1:15 IF $L($P(X,U,I)) SET $P(XOPT,U,I)=$P(X,U,I)
             SET DTIME=600
             IF '$P(XOPT,U,11),$D(^%ZIS(1,XUDEV,90)),^(90)>2800000,^(90)'>DT QUIT 8
             QUIT 0
             ;
             ; Spell out commands and functions
             ;
             IF $PIECE(XUSER(0),U,11),$PIECE(XUSER(0),U,11)'>DT QUIT 11 ;Terminated
             IF $DATA(DUZ("ASH")) QUIT 0 ;If auto handle, Allow to sign-on p434
             IF $PIECE(XUSER(0),U,7) QUIT 5 ;Disuser flag set
             IF '$LENGTH($PIECE(XUSER(1),U,2)) QUIT 21 ;p419, p434
             Q 0
             ;
              </textarea>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                     mode: "mumps",
                     lineNumbers: true,
                     lineWrapping: true
                  });
                </script>
            
              </article>
            
          • mumps.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*
              This MUMPS Language script was constructed using vbscript.js as a template.
            */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("mumps", function() {
                function wordRegexp(words) {
                  return new RegExp("^((" + words.join(")|(") + "))\\b", "i");
                }
            
                var singleOperators = new RegExp("^[\\+\\-\\*/&#!_?\\\\<>=\\'\\[\\]]");
                var doubleOperators = new RegExp("^(('=)|(<=)|(>=)|('>)|('<)|([[)|(]])|(^$))");
                var singleDelimiters = new RegExp("^[\\.,:]");
                var brackets = new RegExp("[()]");
                var identifiers = new RegExp("^[%A-Za-z][A-Za-z0-9]*");
                var commandKeywords = ["break","close","do","else","for","goto", "halt", "hang", "if", "job","kill","lock","merge","new","open", "quit", "read", "set", "tcommit", "trollback", "tstart", "use", "view", "write", "xecute", "b","c","d","e","f","g", "h", "i", "j","k","l","m","n","o", "q", "r", "s", "tc", "tro", "ts", "u", "v", "w", "x"];
                // The following list includes instrinsic functions _and_ special variables
                var intrinsicFuncsWords = ["\\$ascii", "\\$char", "\\$data", "\\$ecode", "\\$estack", "\\$etrap", "\\$extract", "\\$find", "\\$fnumber", "\\$get", "\\$horolog", "\\$io", "\\$increment", "\\$job", "\\$justify", "\\$length", "\\$name", "\\$next", "\\$order", "\\$piece", "\\$qlength", "\\$qsubscript", "\\$query", "\\$quit", "\\$random", "\\$reverse", "\\$select", "\\$stack", "\\$test", "\\$text", "\\$translate", "\\$view", "\\$x", "\\$y", "\\$a", "\\$c", "\\$d", "\\$e", "\\$ec", "\\$es", "\\$et", "\\$f", "\\$fn", "\\$g", "\\$h", "\\$i", "\\$j", "\\$l", "\\$n", "\\$na", "\\$o", "\\$p", "\\$q", "\\$ql", "\\$qs", "\\$r", "\\$re", "\\$s", "\\$st", "\\$t", "\\$tr", "\\$v", "\\$z"];
                var intrinsicFuncs = wordRegexp(intrinsicFuncsWords);
                var command = wordRegexp(commandKeywords);
            
                function tokenBase(stream, state) {
                  if (stream.sol()) {
                    state.label = true;
                    state.commandMode = 0;
                  }
            
                  // The <space> character has meaning in MUMPS. Ignoring consecutive
                  // spaces would interfere with interpreting whether the next non-space
                  // character belongs to the command or argument context.
            
                  // Examine each character and update a mode variable whose interpretation is:
                  //   >0 => command    0 => argument    <0 => command post-conditional
                  var ch = stream.peek();
            
                  if (ch == " " || ch == "\t") { // Pre-process <space>
                    state.label = false;
                    if (state.commandMode == 0)
                      state.commandMode = 1;
                    else if ((state.commandMode < 0) || (state.commandMode == 2))
                      state.commandMode = 0;
                  } else if ((ch != ".") && (state.commandMode > 0)) {
                    if (ch == ":")
                      state.commandMode = -1;   // SIS - Command post-conditional
                    else
                      state.commandMode = 2;
                  }
            
                  // Do not color parameter list as line tag
                  if ((ch === "(") || (ch === "\u0009"))
                    state.label = false;
            
                  // MUMPS comment starts with ";"
                  if (ch === ";") {
                    stream.skipToEnd();
                    return "comment";
                  }
            
                  // Number Literals // SIS/RLM - MUMPS permits canonic number followed by concatenate operator
                  if (stream.match(/^[-+]?\d+(\.\d+)?([eE][-+]?\d+)?/))
                    return "number";
            
                  // Handle Strings
                  if (ch == '"') {
                    if (stream.skipTo('"')) {
                      stream.next();
                      return "string";
                    } else {
                      stream.skipToEnd();
                      return "error";
                    }
                  }
            
                  // Handle operators and Delimiters
                  if (stream.match(doubleOperators) || stream.match(singleOperators))
                    return "operator";
            
                  // Prevents leading "." in DO block from falling through to error
                  if (stream.match(singleDelimiters))
                    return null;
            
                  if (brackets.test(ch)) {
                    stream.next();
                    return "bracket";
                  }
            
                  if (state.commandMode > 0 && stream.match(command))
                    return "variable-2";
            
                  if (stream.match(intrinsicFuncs))
                    return "builtin";
            
                  if (stream.match(identifiers))
                    return "variable";
            
                  // Detect dollar-sign when not a documented intrinsic function
                  // "^" may introduce a GVN or SSVN - Color same as function
                  if (ch === "$" || ch === "^") {
                    stream.next();
                    return "builtin";
                  }
            
                  // MUMPS Indirection
                  if (ch === "@") {
                    stream.next();
                    return "string-2";
                  }
            
                  if (/[\w%]/.test(ch)) {
                    stream.eatWhile(/[\w%]/);
                    return "variable";
                  }
            
                  // Handle non-detected items
                  stream.next();
                  return "error";
                }
            
                return {
                  startState: function() {
                    return {
                      label: false,
                      commandMode: 0
                    };
                  },
            
                  token: function(stream, state) {
                    var style = tokenBase(stream, state);
                    if (state.label) return "tag";
                    return style;
                  }
                };
              });
            
              CodeMirror.defineMIME("text/x-mumps", "mumps");
            });
            
        • nginx
          • index.html
            <!doctype html>
            
            <title>CodeMirror: NGINX mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="nginx.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
                <link rel="stylesheet" href="../../doc/docs.css">
              </head>
            
              <style>
                body {
                  margin: 0em auto;
                }
            
                .CodeMirror, .CodeMirror-scroll {
                  height: 600px;
                }
              </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">NGINX</a>
              </ul>
            </div>
            
            <article>
            <h2>NGINX mode</h2>
            <form><textarea id="code" name="code" style="height: 800px;">
            server {
              listen 173.255.219.235:80;
              server_name website.com.au;
              rewrite / $scheme://www.$host$request_uri permanent; ## Forcibly prepend a www
            }
            
            server {
              listen 173.255.219.235:443;
              server_name website.com.au;
              rewrite / $scheme://www.$host$request_uri permanent; ## Forcibly prepend a www
            }
            
            server {
            
              listen      173.255.219.235:80;
              server_name www.website.com.au;
            
            
            
              root        /data/www;
              index       index.html index.php;
            
              location / {
                index index.html index.php;     ## Allow a static html file to be shown first
                try_files $uri $uri/ @handler;  ## If missing pass the URI to Magento's front handler
                expires 30d;                    ## Assume all files are cachable
              }
            
              ## These locations would be hidden by .htaccess normally
              location /app/                { deny all; }
              location /includes/           { deny all; }
              location /lib/                { deny all; }
              location /media/downloadable/ { deny all; }
              location /pkginfo/            { deny all; }
              location /report/config.xml   { deny all; }
              location /var/                { deny all; }
            
              location /var/export/ { ## Allow admins only to view export folder
                auth_basic           "Restricted"; ## Message shown in login window
                auth_basic_user_file /rs/passwords/testfile; ## See /etc/nginx/htpassword
                autoindex            on;
              }
            
              location  /. { ## Disable .htaccess and other hidden files
                return 404;
              }
            
              location @handler { ## Magento uses a common front handler
                rewrite / /index.php;
              }
            
              location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
                rewrite ^/(.*.php)/ /$1 last;
              }
            
              location ~ \.php$ {
                if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss
            
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_param PATH_INFO $fastcgi_script_name;
                fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include        /rs/confs/nginx/fastcgi_params;
              }
            
            }
            
            
            server {
            
              listen              173.255.219.235:443;
              server_name         website.com.au www.website.com.au;
            
              root   /data/www;
              index index.html index.php;
            
              ssl                 on;
              ssl_certificate     /rs/ssl/ssl.crt;
              ssl_certificate_key /rs/ssl/ssl.key;
            
              ssl_session_timeout  5m;
            
              ssl_protocols  SSLv2 SSLv3 TLSv1;
              ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
              ssl_prefer_server_ciphers   on;
            
            
            
              location / {
                index index.html index.php; ## Allow a static html file to be shown first
                try_files $uri $uri/ @handler; ## If missing pass the URI to Magento's front handler
                expires 30d; ## Assume all files are cachable
              }
            
              ## These locations would be hidden by .htaccess normally
              location /app/                { deny all; }
              location /includes/           { deny all; }
              location /lib/                { deny all; }
              location /media/downloadable/ { deny all; }
              location /pkginfo/            { deny all; }
              location /report/config.xml   { deny all; }
              location /var/                { deny all; }
            
              location /var/export/ { ## Allow admins only to view export folder
                auth_basic           "Restricted"; ## Message shown in login window
                auth_basic_user_file htpasswd; ## See /etc/nginx/htpassword
                autoindex            on;
              }
            
              location  /. { ## Disable .htaccess and other hidden files
                return 404;
              }
            
              location @handler { ## Magento uses a common front handler
                rewrite / /index.php;
              }
            
              location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
                rewrite ^/(.*.php)/ /$1 last;
              }
            
              location ~ .php$ { ## Execute PHP scripts
                if (!-e $request_filename) { rewrite  /index.php last; } ## Catch 404s that try_files miss
            
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_param PATH_INFO $fastcgi_script_name;
                fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include        /rs/confs/nginx/fastcgi_params;
            
                fastcgi_param HTTPS on;
              }
            
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/nginx</code>.</p>
            
              </article>
            
          • nginx.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("nginx", function(config) {
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              var keywords = words(
                /* ngxDirectiveControl */ "break return rewrite set" +
                /* ngxDirective */ " accept_mutex accept_mutex_delay access_log add_after_body add_before_body add_header addition_types aio alias allow ancient_browser ancient_browser_value auth_basic auth_basic_user_file auth_http auth_http_header auth_http_timeout autoindex autoindex_exact_size autoindex_localtime charset charset_types client_body_buffer_size client_body_in_file_only client_body_in_single_buffer client_body_temp_path client_body_timeout client_header_buffer_size client_header_timeout client_max_body_size connection_pool_size create_full_put_path daemon dav_access dav_methods debug_connection debug_points default_type degradation degrade deny devpoll_changes devpoll_events directio directio_alignment empty_gif env epoll_events error_log eventport_events expires fastcgi_bind fastcgi_buffer_size fastcgi_buffers fastcgi_busy_buffers_size fastcgi_cache fastcgi_cache_key fastcgi_cache_methods fastcgi_cache_min_uses fastcgi_cache_path fastcgi_cache_use_stale fastcgi_cache_valid fastcgi_catch_stderr fastcgi_connect_timeout fastcgi_hide_header fastcgi_ignore_client_abort fastcgi_ignore_headers fastcgi_index fastcgi_intercept_errors fastcgi_max_temp_file_size fastcgi_next_upstream fastcgi_param fastcgi_pass_header fastcgi_pass_request_body fastcgi_pass_request_headers fastcgi_read_timeout fastcgi_send_lowat fastcgi_send_timeout fastcgi_split_path_info fastcgi_store fastcgi_store_access fastcgi_temp_file_write_size fastcgi_temp_path fastcgi_upstream_fail_timeout fastcgi_upstream_max_fails flv geoip_city geoip_country google_perftools_profiles gzip gzip_buffers gzip_comp_level gzip_disable gzip_hash gzip_http_version gzip_min_length gzip_no_buffer gzip_proxied gzip_static gzip_types gzip_vary gzip_window if_modified_since ignore_invalid_headers image_filter image_filter_buffer image_filter_jpeg_quality image_filter_transparency imap_auth imap_capabilities imap_client_buffer index ip_hash keepalive_requests keepalive_timeout kqueue_changes kqueue_events large_client_header_buffers limit_conn limit_conn_log_level limit_rate limit_rate_after limit_req limit_req_log_level limit_req_zone limit_zone lingering_time lingering_timeout lock_file log_format log_not_found log_subrequest map_hash_bucket_size map_hash_max_size master_process memcached_bind memcached_buffer_size memcached_connect_timeout memcached_next_upstream memcached_read_timeout memcached_send_timeout memcached_upstream_fail_timeout memcached_upstream_max_fails merge_slashes min_delete_depth modern_browser modern_browser_value msie_padding msie_refresh multi_accept open_file_cache open_file_cache_errors open_file_cache_events open_file_cache_min_uses open_file_cache_valid open_log_file_cache output_buffers override_charset perl perl_modules perl_require perl_set pid pop3_auth pop3_capabilities port_in_redirect postpone_gzipping postpone_output protocol proxy proxy_bind proxy_buffer proxy_buffer_size proxy_buffering proxy_buffers proxy_busy_buffers_size proxy_cache proxy_cache_key proxy_cache_methods proxy_cache_min_uses proxy_cache_path proxy_cache_use_stale proxy_cache_valid proxy_connect_timeout proxy_headers_hash_bucket_size proxy_headers_hash_max_size proxy_hide_header proxy_ignore_client_abort proxy_ignore_headers proxy_intercept_errors proxy_max_temp_file_size proxy_method proxy_next_upstream proxy_pass_error_message proxy_pass_header proxy_pass_request_body proxy_pass_request_headers proxy_read_timeout proxy_redirect proxy_send_lowat proxy_send_timeout proxy_set_body proxy_set_header proxy_ssl_session_reuse proxy_store proxy_store_access proxy_temp_file_write_size proxy_temp_path proxy_timeout proxy_upstream_fail_timeout proxy_upstream_max_fails random_index read_ahead real_ip_header recursive_error_pages request_pool_size reset_timedout_connection resolver resolver_timeout rewrite_log rtsig_overflow_events rtsig_overflow_test rtsig_overflow_threshold rtsig_signo satisfy secure_link_secret send_lowat send_timeout sendfile sendfile_max_chunk server_name_in_redirect server_names_hash_bucket_size server_names_hash_max_size server_tokens set_real_ip_from smtp_auth smtp_capabilities smtp_client_buffer smtp_greeting_delay so_keepalive source_charset ssi ssi_ignore_recycled_buffers ssi_min_file_chunk ssi_silent_errors ssi_types ssi_value_length ssl ssl_certificate ssl_certificate_key ssl_ciphers ssl_client_certificate ssl_crl ssl_dhparam ssl_engine ssl_prefer_server_ciphers ssl_protocols ssl_session_cache ssl_session_timeout ssl_verify_client ssl_verify_depth starttls stub_status sub_filter sub_filter_once sub_filter_types tcp_nodelay tcp_nopush thread_stack_size timeout timer_resolution types_hash_bucket_size types_hash_max_size underscores_in_headers uninitialized_variable_warn use user userid userid_domain userid_expires userid_mark userid_name userid_p3p userid_path userid_service valid_referers variables_hash_bucket_size variables_hash_max_size worker_connections worker_cpu_affinity worker_priority worker_processes worker_rlimit_core worker_rlimit_nofile worker_rlimit_sigpending worker_threads working_directory xclient xml_entities xslt_stylesheet xslt_typesdrew@li229-23"
                );
            
              var keywords_block = words(
                /* ngxDirectiveBlock */ "http mail events server types location upstream charset_map limit_except if geo map"
                );
            
              var keywords_important = words(
                /* ngxDirectiveImportant */ "include root server server_name listen internal proxy_pass memcached_pass fastcgi_pass try_files"
                );
            
              var indentUnit = config.indentUnit, type;
              function ret(style, tp) {type = tp; return style;}
            
              function tokenBase(stream, state) {
            
            
                stream.eatWhile(/[\w\$_]/);
            
                var cur = stream.current();
            
            
                if (keywords.propertyIsEnumerable(cur)) {
                  return "keyword";
                }
                else if (keywords_block.propertyIsEnumerable(cur)) {
                  return "variable-2";
                }
                else if (keywords_important.propertyIsEnumerable(cur)) {
                  return "string-2";
                }
                /**/
            
                var ch = stream.next();
                if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("meta", stream.current());}
                else if (ch == "/" && stream.eat("*")) {
                  state.tokenize = tokenCComment;
                  return tokenCComment(stream, state);
                }
                else if (ch == "<" && stream.eat("!")) {
                  state.tokenize = tokenSGMLComment;
                  return tokenSGMLComment(stream, state);
                }
                else if (ch == "=") ret(null, "compare");
                else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");
                else if (ch == "\"" || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                else if (ch == "#") {
                  stream.skipToEnd();
                  return ret("comment", "comment");
                }
                else if (ch == "!") {
                  stream.match(/^\s*\w*/);
                  return ret("keyword", "important");
                }
                else if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w.%]/);
                  return ret("number", "unit");
                }
                else if (/[,.+>*\/]/.test(ch)) {
                  return ret(null, "select-op");
                }
                else if (/[;{}:\[\]]/.test(ch)) {
                  return ret(null, ch);
                }
                else {
                  stream.eatWhile(/[\w\\\-]/);
                  return ret("variable", "variable");
                }
              }
            
              function tokenCComment(stream, state) {
                var maybeEnd = false, ch;
                while ((ch = stream.next()) != null) {
                  if (maybeEnd && ch == "/") {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return ret("comment", "comment");
              }
            
              function tokenSGMLComment(stream, state) {
                var dashes = 0, ch;
                while ((ch = stream.next()) != null) {
                  if (dashes >= 2 && ch == ">") {
                    state.tokenize = tokenBase;
                    break;
                  }
                  dashes = (ch == "-") ? dashes + 1 : 0;
                }
                return ret("comment", "comment");
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped)
                      break;
                    escaped = !escaped && ch == "\\";
                  }
                  if (!escaped) state.tokenize = tokenBase;
                  return ret("string", "string");
                };
              }
            
              return {
                startState: function(base) {
                  return {tokenize: tokenBase,
                          baseIndent: base || 0,
                          stack: []};
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  type = null;
                  var style = state.tokenize(stream, state);
            
                  var context = state.stack[state.stack.length-1];
                  if (type == "hash" && context == "rule") style = "atom";
                  else if (style == "variable") {
                    if (context == "rule") style = "number";
                    else if (!context || context == "@media{") style = "tag";
                  }
            
                  if (context == "rule" && /^[\{\};]$/.test(type))
                    state.stack.pop();
                  if (type == "{") {
                    if (context == "@media") state.stack[state.stack.length-1] = "@media{";
                    else state.stack.push("{");
                  }
                  else if (type == "}") state.stack.pop();
                  else if (type == "@media") state.stack.push("@media");
                  else if (context == "{" && type != "comment") state.stack.push("rule");
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var n = state.stack.length;
                  if (/^\}/.test(textAfter))
                    n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1;
                  return state.baseIndent + n * indentUnit;
                },
            
                electricChars: "}"
              };
            });
            
            CodeMirror.defineMIME("text/nginx", "text/x-nginx-conf");
            
            });
            
        • ntriples
          • index.html
            <!doctype html>
            
            <title>CodeMirror: NTriples mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="ntriples.js"></script>
            <style type="text/css">
                  .CodeMirror {
                    border: 1px solid #eee;
                  }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">NTriples</a>
              </ul>
            </div>
            
            <article>
            <h2>NTriples mode</h2>
            <form>
            <textarea id="ntriples" name="ntriples">    
            <http://Sub1>     <http://pred1>     <http://obj> .
            <http://Sub2>     <http://pred2#an2> "literal 1" .
            <http://Sub3#an3> <http://pred3>     _:bnode3 .
            _:bnode4          <http://pred4>     "literal 2"@lang .
            _:bnode5          <http://pred5>     "literal 3"^^<http://type> .
            </textarea>
            </form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("ntriples"), {});
                </script>
                <p><strong>MIME types defined:</strong> <code>text/n-triples</code>.</p>
              </article>
            
          • ntriples.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**********************************************************
            * This script provides syntax highlighting support for
            * the Ntriples format.
            * Ntriples format specification:
            *     http://www.w3.org/TR/rdf-testcases/#ntriples
            ***********************************************************/
            
            /*
                The following expression defines the defined ASF grammar transitions.
            
                pre_subject ->
                    {
                    ( writing_subject_uri | writing_bnode_uri )
                        -> pre_predicate
                            -> writing_predicate_uri
                                -> pre_object
                                    -> writing_object_uri | writing_object_bnode |
                                      (
                                        writing_object_literal
                                            -> writing_literal_lang | writing_literal_type
                                      )
                                        -> post_object
                                            -> BEGIN
                     } otherwise {
                         -> ERROR
                     }
            */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("ntriples", function() {
            
              var Location = {
                PRE_SUBJECT         : 0,
                WRITING_SUB_URI     : 1,
                WRITING_BNODE_URI   : 2,
                PRE_PRED            : 3,
                WRITING_PRED_URI    : 4,
                PRE_OBJ             : 5,
                WRITING_OBJ_URI     : 6,
                WRITING_OBJ_BNODE   : 7,
                WRITING_OBJ_LITERAL : 8,
                WRITING_LIT_LANG    : 9,
                WRITING_LIT_TYPE    : 10,
                POST_OBJ            : 11,
                ERROR               : 12
              };
              function transitState(currState, c) {
                var currLocation = currState.location;
                var ret;
            
                // Opening.
                if     (currLocation == Location.PRE_SUBJECT && c == '<') ret = Location.WRITING_SUB_URI;
                else if(currLocation == Location.PRE_SUBJECT && c == '_') ret = Location.WRITING_BNODE_URI;
                else if(currLocation == Location.PRE_PRED    && c == '<') ret = Location.WRITING_PRED_URI;
                else if(currLocation == Location.PRE_OBJ     && c == '<') ret = Location.WRITING_OBJ_URI;
                else if(currLocation == Location.PRE_OBJ     && c == '_') ret = Location.WRITING_OBJ_BNODE;
                else if(currLocation == Location.PRE_OBJ     && c == '"') ret = Location.WRITING_OBJ_LITERAL;
            
                // Closing.
                else if(currLocation == Location.WRITING_SUB_URI     && c == '>') ret = Location.PRE_PRED;
                else if(currLocation == Location.WRITING_BNODE_URI   && c == ' ') ret = Location.PRE_PRED;
                else if(currLocation == Location.WRITING_PRED_URI    && c == '>') ret = Location.PRE_OBJ;
                else if(currLocation == Location.WRITING_OBJ_URI     && c == '>') ret = Location.POST_OBJ;
                else if(currLocation == Location.WRITING_OBJ_BNODE   && c == ' ') ret = Location.POST_OBJ;
                else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '"') ret = Location.POST_OBJ;
                else if(currLocation == Location.WRITING_LIT_LANG && c == ' ') ret = Location.POST_OBJ;
                else if(currLocation == Location.WRITING_LIT_TYPE && c == '>') ret = Location.POST_OBJ;
            
                // Closing typed and language literal.
                else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '@') ret = Location.WRITING_LIT_LANG;
                else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '^') ret = Location.WRITING_LIT_TYPE;
            
                // Spaces.
                else if( c == ' ' &&
                         (
                           currLocation == Location.PRE_SUBJECT ||
                           currLocation == Location.PRE_PRED    ||
                           currLocation == Location.PRE_OBJ     ||
                           currLocation == Location.POST_OBJ
                         )
                       ) ret = currLocation;
            
                // Reset.
                else if(currLocation == Location.POST_OBJ && c == '.') ret = Location.PRE_SUBJECT;
            
                // Error
                else ret = Location.ERROR;
            
                currState.location=ret;
              }
            
              return {
                startState: function() {
                   return {
                       location : Location.PRE_SUBJECT,
                       uris     : [],
                       anchors  : [],
                       bnodes   : [],
                       langs    : [],
                       types    : []
                   };
                },
                token: function(stream, state) {
                  var ch = stream.next();
                  if(ch == '<') {
                     transitState(state, ch);
                     var parsedURI = '';
                     stream.eatWhile( function(c) { if( c != '#' && c != '>' ) { parsedURI += c; return true; } return false;} );
                     state.uris.push(parsedURI);
                     if( stream.match('#', false) ) return 'variable';
                     stream.next();
                     transitState(state, '>');
                     return 'variable';
                  }
                  if(ch == '#') {
                    var parsedAnchor = '';
                    stream.eatWhile(function(c) { if(c != '>' && c != ' ') { parsedAnchor+= c; return true; } return false;});
                    state.anchors.push(parsedAnchor);
                    return 'variable-2';
                  }
                  if(ch == '>') {
                      transitState(state, '>');
                      return 'variable';
                  }
                  if(ch == '_') {
                      transitState(state, ch);
                      var parsedBNode = '';
                      stream.eatWhile(function(c) { if( c != ' ' ) { parsedBNode += c; return true; } return false;});
                      state.bnodes.push(parsedBNode);
                      stream.next();
                      transitState(state, ' ');
                      return 'builtin';
                  }
                  if(ch == '"') {
                      transitState(state, ch);
                      stream.eatWhile( function(c) { return c != '"'; } );
                      stream.next();
                      if( stream.peek() != '@' && stream.peek() != '^' ) {
                          transitState(state, '"');
                      }
                      return 'string';
                  }
                  if( ch == '@' ) {
                      transitState(state, '@');
                      var parsedLang = '';
                      stream.eatWhile(function(c) { if( c != ' ' ) { parsedLang += c; return true; } return false;});
                      state.langs.push(parsedLang);
                      stream.next();
                      transitState(state, ' ');
                      return 'string-2';
                  }
                  if( ch == '^' ) {
                      stream.next();
                      transitState(state, '^');
                      var parsedType = '';
                      stream.eatWhile(function(c) { if( c != '>' ) { parsedType += c; return true; } return false;} );
                      state.types.push(parsedType);
                      stream.next();
                      transitState(state, '>');
                      return 'variable';
                  }
                  if( ch == ' ' ) {
                      transitState(state, ch);
                  }
                  if( ch == '.' ) {
                      transitState(state, ch);
                  }
                }
              };
            });
            
            CodeMirror.defineMIME("text/n-triples", "ntriples");
            
            });
            
        • octave
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Octave mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="octave.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Octave</a>
              </ul>
            </div>
            
            <article>
            <h2>Octave mode</h2>
            
                <div><textarea id="code" name="code">
            %numbers
            [1234 1234i 1234j]
            [.234 .234j 2.23i]
            [23e2 12E1j 123D-4 0x234]
            
            %strings
            'asda''a'
            "asda""a"
            
            %identifiers
            a + as123 - __asd__
            
            %operators
            -
            +
            =
            ==
            >
            <
            >=
            <=
            &
            ~
            ...
            break zeros default margin round ones rand
            ceil floor size clear zeros eye mean std cov
            error eval function
            abs acos atan asin cos cosh exp log prod sum
            log10 max min sign sin sinh sqrt tan reshape
            return
            case switch
            else elseif end if otherwise
            do for while
            try catch
            classdef properties events methods
            global persistent
            
            %one line comment
            %{ multi 
            line commment %}
            
                </textarea></div>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "octave",
                           version: 2,
                           singleLineStringErrors: false},
                    lineNumbers: true,
                    indentUnit: 4,
                    matchBrackets: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-octave</code>.</p>
            </article>
            
          • octave.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("octave", function() {
              function wordRegexp(words) {
                return new RegExp("^((" + words.join(")|(") + "))\\b");
              }
            
              var singleOperators = new RegExp("^[\\+\\-\\*/&|\\^~<>!@'\\\\]");
              var singleDelimiters = new RegExp('^[\\(\\[\\{\\},:=;]');
              var doubleOperators = new RegExp("^((==)|(~=)|(<=)|(>=)|(<<)|(>>)|(\\.[\\+\\-\\*/\\^\\\\]))");
              var doubleDelimiters = new RegExp("^((!=)|(\\+=)|(\\-=)|(\\*=)|(/=)|(&=)|(\\|=)|(\\^=))");
              var tripleDelimiters = new RegExp("^((>>=)|(<<=))");
              var expressionEnd = new RegExp("^[\\]\\)]");
              var identifiers = new RegExp("^[_A-Za-z\xa1-\uffff][_A-Za-z0-9\xa1-\uffff]*");
            
              var builtins = wordRegexp([
                'error', 'eval', 'function', 'abs', 'acos', 'atan', 'asin', 'cos',
                'cosh', 'exp', 'log', 'prod', 'sum', 'log10', 'max', 'min', 'sign', 'sin', 'sinh',
                'sqrt', 'tan', 'reshape', 'break', 'zeros', 'default', 'margin', 'round', 'ones',
                'rand', 'syn', 'ceil', 'floor', 'size', 'clear', 'zeros', 'eye', 'mean', 'std', 'cov',
                'det', 'eig', 'inv', 'norm', 'rank', 'trace', 'expm', 'logm', 'sqrtm', 'linspace', 'plot',
                'title', 'xlabel', 'ylabel', 'legend', 'text', 'grid', 'meshgrid', 'mesh', 'num2str',
                'fft', 'ifft', 'arrayfun', 'cellfun', 'input', 'fliplr', 'flipud', 'ismember'
              ]);
            
              var keywords = wordRegexp([
                'return', 'case', 'switch', 'else', 'elseif', 'end', 'endif', 'endfunction',
                'if', 'otherwise', 'do', 'for', 'while', 'try', 'catch', 'classdef', 'properties', 'events',
                'methods', 'global', 'persistent', 'endfor', 'endwhile', 'printf', 'sprintf', 'disp', 'until',
                'continue', 'pkg'
              ]);
            
            
              // tokenizers
              function tokenTranspose(stream, state) {
                if (!stream.sol() && stream.peek() === '\'') {
                  stream.next();
                  state.tokenize = tokenBase;
                  return 'operator';
                }
                state.tokenize = tokenBase;
                return tokenBase(stream, state);
              }
            
            
              function tokenComment(stream, state) {
                if (stream.match(/^.*%}/)) {
                  state.tokenize = tokenBase;
                  return 'comment';
                };
                stream.skipToEnd();
                return 'comment';
              }
            
              function tokenBase(stream, state) {
                // whitespaces
                if (stream.eatSpace()) return null;
            
                // Handle one line Comments
                if (stream.match('%{')){
                  state.tokenize = tokenComment;
                  stream.skipToEnd();
                  return 'comment';
                }
            
                if (stream.match(/^[%#]/)){
                  stream.skipToEnd();
                  return 'comment';
                }
            
                // Handle Number Literals
                if (stream.match(/^[0-9\.+-]/, false)) {
                  if (stream.match(/^[+-]?0x[0-9a-fA-F]+[ij]?/)) {
                    stream.tokenize = tokenBase;
                    return 'number'; };
                  if (stream.match(/^[+-]?\d*\.\d+([EeDd][+-]?\d+)?[ij]?/)) { return 'number'; };
                  if (stream.match(/^[+-]?\d+([EeDd][+-]?\d+)?[ij]?/)) { return 'number'; };
                }
                if (stream.match(wordRegexp(['nan','NaN','inf','Inf']))) { return 'number'; };
            
                // Handle Strings
                if (stream.match(/^"([^"]|(""))*"/)) { return 'string'; } ;
                if (stream.match(/^'([^']|(''))*'/)) { return 'string'; } ;
            
                // Handle words
                if (stream.match(keywords)) { return 'keyword'; } ;
                if (stream.match(builtins)) { return 'builtin'; } ;
                if (stream.match(identifiers)) { return 'variable'; } ;
            
                if (stream.match(singleOperators) || stream.match(doubleOperators)) { return 'operator'; };
                if (stream.match(singleDelimiters) || stream.match(doubleDelimiters) || stream.match(tripleDelimiters)) { return null; };
            
                if (stream.match(expressionEnd)) {
                  state.tokenize = tokenTranspose;
                  return null;
                };
            
            
                // Handle non-detected items
                stream.next();
                return 'error';
              };
            
            
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase
                  };
                },
            
                token: function(stream, state) {
                  var style = state.tokenize(stream, state);
                  if (style === 'number' || style === 'variable'){
                    state.tokenize = tokenTranspose;
                  }
                  return style;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-octave", "octave");
            
            });
            
        • pascal
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Pascal mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="pascal.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Pascal</a>
              </ul>
            </div>
            
            <article>
            <h2>Pascal mode</h2>
            
            
            <div><textarea id="code" name="code">
            (* Example Pascal code *)
            
            while a <> b do writeln('Waiting');
             
            if a > b then 
              writeln('Condition met')
            else 
              writeln('Condition not met');
             
            for i := 1 to 10 do 
              writeln('Iteration: ', i:1);
             
            repeat
              a := a + 1
            until a = 10;
             
            case i of
              0: write('zero');
              1: write('one');
              2: write('two')
            end;
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "text/x-pascal"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-pascal</code>.</p>
              </article>
            
          • pascal.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("pascal", function() {
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
              var keywords = words("and array begin case const div do downto else end file for forward integer " +
                                   "boolean char function goto if in label mod nil not of or packed procedure " +
                                   "program record repeat set string then to type until var while with");
              var atoms = {"null": true};
            
              var isOperatorChar = /[+\-*&%=<>!?|\/]/;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == "#" && state.startOfLine) {
                  stream.skipToEnd();
                  return "meta";
                }
                if (ch == '"' || ch == "'") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                if (ch == "(" && stream.eat("*")) {
                  state.tokenize = tokenComment;
                  return tokenComment(stream, state);
                }
                if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
                  return null;
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return "number";
                }
                if (ch == "/") {
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                }
                if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                stream.eatWhile(/[\w\$_]/);
                var cur = stream.current();
                if (keywords.propertyIsEnumerable(cur)) return "keyword";
                if (atoms.propertyIsEnumerable(cur)) return "atom";
                return "variable";
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {end = true; break;}
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !escaped) state.tokenize = null;
                  return "string";
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == ")" && maybeEnd) {
                    state.tokenize = null;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              // Interface
            
              return {
                startState: function() {
                  return {tokenize: null};
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment" || style == "meta") return style;
                  return style;
                },
            
                electricChars: "{}"
              };
            });
            
            CodeMirror.defineMIME("text/x-pascal", "pascal");
            
            });
            
        • pegjs
          • index.html
            <!doctype html>
            <html>
              <head>
                <title>CodeMirror: PEG.js Mode</title>
                <meta charset="utf-8"/>
                <link rel=stylesheet href="../../doc/docs.css">
            
                <link rel="stylesheet" href="../../lib/codemirror.css">
                <script src="../../lib/codemirror.js"></script>
                <script src="../javascript/javascript.js"></script>
                <script src="pegjs.js"></script>
                <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
              </head>
              <body>
                <div id=nav>
                  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
                  <ul>
                    <li><a href="../../index.html">Home</a>
                    <li><a href="../../doc/manual.html">Manual</a>
                    <li><a href="https://github.com/codemirror/codemirror">Code</a>
                  </ul>
                  <ul>
                    <li><a href="../index.html">Language modes</a>
                    <li><a class=active href="#">PEG.js Mode</a>
                  </ul>
                </div>
            
                <article>
                  <h2>PEG.js Mode</h2>
                  <form><textarea id="code" name="code">
            /*
             * Classic example grammar, which recognizes simple arithmetic expressions like
             * "2*(3+4)". The parser generated from this grammar then computes their value.
             */
            
            start
              = additive
            
            additive
              = left:multiplicative "+" right:additive { return left + right; }
              / multiplicative
            
            multiplicative
              = left:primary "*" right:multiplicative { return left * right; }
              / primary
            
            primary
              = integer
              / "(" additive:additive ")" { return additive; }
            
            integer "integer"
              = digits:[0-9]+ { return parseInt(digits.join(""), 10); }
            
            letter = [a-z]+</textarea></form>
                  <script>
                    var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                      mode: {name: "pegjs"},
                      lineNumbers: true
                    });
                  </script>
                  <h3>The PEG.js Mode</h3>
                  <p> Created by Forbes Lindesay.</p>
                </article>
              </body>
            </html>
            
          • pegjs.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../javascript/javascript"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../javascript/javascript"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("pegjs", function (config) {
              var jsMode = CodeMirror.getMode(config, "javascript");
            
              function identifier(stream) {
                return stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/);
              }
            
              return {
                startState: function () {
                  return {
                    inString: false,
                    stringType: null,
                    inComment: false,
                    inChracterClass: false,
                    braced: 0,
                    lhs: true,
                    localState: null
                  };
                },
                token: function (stream, state) {
                  if (stream)
            
                  //check for state changes
                  if (!state.inString && !state.inComment && ((stream.peek() == '"') || (stream.peek() == "'"))) {
                    state.stringType = stream.peek();
                    stream.next(); // Skip quote
                    state.inString = true; // Update state
                  }
                  if (!state.inString && !state.inComment && stream.match(/^\/\*/)) {
                    state.inComment = true;
                  }
            
                  //return state
                  if (state.inString) {
                    while (state.inString && !stream.eol()) {
                      if (stream.peek() === state.stringType) {
                        stream.next(); // Skip quote
                        state.inString = false; // Clear flag
                      } else if (stream.peek() === '\\') {
                        stream.next();
                        stream.next();
                      } else {
                        stream.match(/^.[^\\\"\']*/);
                      }
                    }
                    return state.lhs ? "property string" : "string"; // Token style
                  } else if (state.inComment) {
                    while (state.inComment && !stream.eol()) {
                      if (stream.match(/\*\//)) {
                        state.inComment = false; // Clear flag
                      } else {
                        stream.match(/^.[^\*]*/);
                      }
                    }
                    return "comment";
                  } else if (state.inChracterClass) {
                      while (state.inChracterClass && !stream.eol()) {
                        if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) {
                          state.inChracterClass = false;
                        }
                      }
                  } else if (stream.peek() === '[') {
                    stream.next();
                    state.inChracterClass = true;
                    return 'bracket';
                  } else if (stream.match(/^\/\//)) {
                    stream.skipToEnd();
                    return "comment";
                  } else if (state.braced || stream.peek() === '{') {
                    if (state.localState === null) {
                      state.localState = jsMode.startState();
                    }
                    var token = jsMode.token(stream, state.localState);
                    var text = stream.current();
                    if (!token) {
                      for (var i = 0; i < text.length; i++) {
                        if (text[i] === '{') {
                          state.braced++;
                        } else if (text[i] === '}') {
                          state.braced--;
                        }
                      };
                    }
                    return token;
                  } else if (identifier(stream)) {
                    if (stream.peek() === ':') {
                      return 'variable';
                    }
                    return 'variable-2';
                  } else if (['[', ']', '(', ')'].indexOf(stream.peek()) != -1) {
                    stream.next();
                    return 'bracket';
                  } else if (!stream.eatSpace()) {
                    stream.next();
                  }
                  return null;
                }
              };
            }, "javascript");
            
            });
            
        • perl
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Perl mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="perl.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Perl</a>
              </ul>
            </div>
            
            <article>
            <h2>Perl mode</h2>
            
            
            <div><textarea id="code" name="code">
            #!/usr/bin/perl
            
            use Something qw(func1 func2);
            
            # strings
            my $s1 = qq'single line';
            our $s2 = q(multi-
                          line);
            
            =item Something
            	Example.
            =cut
            
            my $html=<<'HTML'
            <html>
            <title>hi!</title>
            </html>
            HTML
            
            print "first,".join(',', 'second', qq~third~);
            
            if($s1 =~ m[(?<!\s)(l.ne)\z]o) {
            	$h->{$1}=$$.' predefined variables';
            	$s2 =~ s/\-line//ox;
            	$s1 =~ s[
            		  line ]
            		[
            		  block
            		]ox;
            }
            
            1; # numbers and comments
            
            __END__
            something...
            
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-perl</code>.</p>
              </article>
            
          • perl.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08)
            // This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com)
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("perl",function(){
                    // http://perldoc.perl.org
                    var PERL={                                      //   null - magic touch
                                                                    //   1 - keyword
                                                                    //   2 - def
                                                                    //   3 - atom
                                                                    //   4 - operator
                                                                    //   5 - variable-2 (predefined)
                                                                    //   [x,y] - x=1,2,3; y=must be defined if x{...}
                                                            //      PERL operators
                            '->'                            :   4,
                            '++'                            :   4,
                            '--'                            :   4,
                            '**'                            :   4,
                                                                    //   ! ~ \ and unary + and -
                            '=~'                            :   4,
                            '!~'                            :   4,
                            '*'                             :   4,
                            '/'                             :   4,
                            '%'                             :   4,
                            'x'                             :   4,
                            '+'                             :   4,
                            '-'                             :   4,
                            '.'                             :   4,
                            '<<'                            :   4,
                            '>>'                            :   4,
                                                                    //   named unary operators
                            '<'                             :   4,
                            '>'                             :   4,
                            '<='                            :   4,
                            '>='                            :   4,
                            'lt'                            :   4,
                            'gt'                            :   4,
                            'le'                            :   4,
                            'ge'                            :   4,
                            '=='                            :   4,
                            '!='                            :   4,
                            '<=>'                           :   4,
                            'eq'                            :   4,
                            'ne'                            :   4,
                            'cmp'                           :   4,
                            '~~'                            :   4,
                            '&'                             :   4,
                            '|'                             :   4,
                            '^'                             :   4,
                            '&&'                            :   4,
                            '||'                            :   4,
                            '//'                            :   4,
                            '..'                            :   4,
                            '...'                           :   4,
                            '?'                             :   4,
                            ':'                             :   4,
                            '='                             :   4,
                            '+='                            :   4,
                            '-='                            :   4,
                            '*='                            :   4,  //   etc. ???
                            ','                             :   4,
                            '=>'                            :   4,
                            '::'                            :   4,
                                                                    //   list operators (rightward)
                            'not'                           :   4,
                            'and'                           :   4,
                            'or'                            :   4,
                            'xor'                           :   4,
                                                            //      PERL predefined variables (I know, what this is a paranoid idea, but may be needed for people, who learn PERL, and for me as well, ...and may be for you?;)
                            'BEGIN'                         :   [5,1],
                            'END'                           :   [5,1],
                            'PRINT'                         :   [5,1],
                            'PRINTF'                        :   [5,1],
                            'GETC'                          :   [5,1],
                            'READ'                          :   [5,1],
                            'READLINE'                      :   [5,1],
                            'DESTROY'                       :   [5,1],
                            'TIE'                           :   [5,1],
                            'TIEHANDLE'                     :   [5,1],
                            'UNTIE'                         :   [5,1],
                            'STDIN'                         :    5,
                            'STDIN_TOP'                     :    5,
                            'STDOUT'                        :    5,
                            'STDOUT_TOP'                    :    5,
                            'STDERR'                        :    5,
                            'STDERR_TOP'                    :    5,
                            '$ARG'                          :    5,
                            '$_'                            :    5,
                            '@ARG'                          :    5,
                            '@_'                            :    5,
                            '$LIST_SEPARATOR'               :    5,
                            '$"'                            :    5,
                            '$PROCESS_ID'                   :    5,
                            '$PID'                          :    5,
                            '$$'                            :    5,
                            '$REAL_GROUP_ID'                :    5,
                            '$GID'                          :    5,
                            '$('                            :    5,
                            '$EFFECTIVE_GROUP_ID'           :    5,
                            '$EGID'                         :    5,
                            '$)'                            :    5,
                            '$PROGRAM_NAME'                 :    5,
                            '$0'                            :    5,
                            '$SUBSCRIPT_SEPARATOR'          :    5,
                            '$SUBSEP'                       :    5,
                            '$;'                            :    5,
                            '$REAL_USER_ID'                 :    5,
                            '$UID'                          :    5,
                            '$<'                            :    5,
                            '$EFFECTIVE_USER_ID'            :    5,
                            '$EUID'                         :    5,
                            '$>'                            :    5,
                            '$a'                            :    5,
                            '$b'                            :    5,
                            '$COMPILING'                    :    5,
                            '$^C'                           :    5,
                            '$DEBUGGING'                    :    5,
                            '$^D'                           :    5,
                            '${^ENCODING}'                  :    5,
                            '$ENV'                          :    5,
                            '%ENV'                          :    5,
                            '$SYSTEM_FD_MAX'                :    5,
                            '$^F'                           :    5,
                            '@F'                            :    5,
                            '${^GLOBAL_PHASE}'              :    5,
                            '$^H'                           :    5,
                            '%^H'                           :    5,
                            '@INC'                          :    5,
                            '%INC'                          :    5,
                            '$INPLACE_EDIT'                 :    5,
                            '$^I'                           :    5,
                            '$^M'                           :    5,
                            '$OSNAME'                       :    5,
                            '$^O'                           :    5,
                            '${^OPEN}'                      :    5,
                            '$PERLDB'                       :    5,
                            '$^P'                           :    5,
                            '$SIG'                          :    5,
                            '%SIG'                          :    5,
                            '$BASETIME'                     :    5,
                            '$^T'                           :    5,
                            '${^TAINT}'                     :    5,
                            '${^UNICODE}'                   :    5,
                            '${^UTF8CACHE}'                 :    5,
                            '${^UTF8LOCALE}'                :    5,
                            '$PERL_VERSION'                 :    5,
                            '$^V'                           :    5,
                            '${^WIN32_SLOPPY_STAT}'         :    5,
                            '$EXECUTABLE_NAME'              :    5,
                            '$^X'                           :    5,
                            '$1'                            :    5, // - regexp $1, $2...
                            '$MATCH'                        :    5,
                            '$&'                            :    5,
                            '${^MATCH}'                     :    5,
                            '$PREMATCH'                     :    5,
                            '$`'                            :    5,
                            '${^PREMATCH}'                  :    5,
                            '$POSTMATCH'                    :    5,
                            "$'"                            :    5,
                            '${^POSTMATCH}'                 :    5,
                            '$LAST_PAREN_MATCH'             :    5,
                            '$+'                            :    5,
                            '$LAST_SUBMATCH_RESULT'         :    5,
                            '$^N'                           :    5,
                            '@LAST_MATCH_END'               :    5,
                            '@+'                            :    5,
                            '%LAST_PAREN_MATCH'             :    5,
                            '%+'                            :    5,
                            '@LAST_MATCH_START'             :    5,
                            '@-'                            :    5,
                            '%LAST_MATCH_START'             :    5,
                            '%-'                            :    5,
                            '$LAST_REGEXP_CODE_RESULT'      :    5,
                            '$^R'                           :    5,
                            '${^RE_DEBUG_FLAGS}'            :    5,
                            '${^RE_TRIE_MAXBUF}'            :    5,
                            '$ARGV'                         :    5,
                            '@ARGV'                         :    5,
                            'ARGV'                          :    5,
                            'ARGVOUT'                       :    5,
                            '$OUTPUT_FIELD_SEPARATOR'       :    5,
                            '$OFS'                          :    5,
                            '$,'                            :    5,
                            '$INPUT_LINE_NUMBER'            :    5,
                            '$NR'                           :    5,
                            '$.'                            :    5,
                            '$INPUT_RECORD_SEPARATOR'       :    5,
                            '$RS'                           :    5,
                            '$/'                            :    5,
                            '$OUTPUT_RECORD_SEPARATOR'      :    5,
                            '$ORS'                          :    5,
                            '$\\'                           :    5,
                            '$OUTPUT_AUTOFLUSH'             :    5,
                            '$|'                            :    5,
                            '$ACCUMULATOR'                  :    5,
                            '$^A'                           :    5,
                            '$FORMAT_FORMFEED'              :    5,
                            '$^L'                           :    5,
                            '$FORMAT_PAGE_NUMBER'           :    5,
                            '$%'                            :    5,
                            '$FORMAT_LINES_LEFT'            :    5,
                            '$-'                            :    5,
                            '$FORMAT_LINE_BREAK_CHARACTERS' :    5,
                            '$:'                            :    5,
                            '$FORMAT_LINES_PER_PAGE'        :    5,
                            '$='                            :    5,
                            '$FORMAT_TOP_NAME'              :    5,
                            '$^'                            :    5,
                            '$FORMAT_NAME'                  :    5,
                            '$~'                            :    5,
                            '${^CHILD_ERROR_NATIVE}'        :    5,
                            '$EXTENDED_OS_ERROR'            :    5,
                            '$^E'                           :    5,
                            '$EXCEPTIONS_BEING_CAUGHT'      :    5,
                            '$^S'                           :    5,
                            '$WARNING'                      :    5,
                            '$^W'                           :    5,
                            '${^WARNING_BITS}'              :    5,
                            '$OS_ERROR'                     :    5,
                            '$ERRNO'                        :    5,
                            '$!'                            :    5,
                            '%OS_ERROR'                     :    5,
                            '%ERRNO'                        :    5,
                            '%!'                            :    5,
                            '$CHILD_ERROR'                  :    5,
                            '$?'                            :    5,
                            '$EVAL_ERROR'                   :    5,
                            '$@'                            :    5,
                            '$OFMT'                         :    5,
                            '$#'                            :    5,
                            '$*'                            :    5,
                            '$ARRAY_BASE'                   :    5,
                            '$['                            :    5,
                            '$OLD_PERL_VERSION'             :    5,
                            '$]'                            :    5,
                                                            //      PERL blocks
                            'if'                            :[1,1],
                            elsif                           :[1,1],
                            'else'                          :[1,1],
                            'while'                         :[1,1],
                            unless                          :[1,1],
                            'for'                           :[1,1],
                            foreach                         :[1,1],
                                                            //      PERL functions
                            'abs'                           :1,     // - absolute value function
                            accept                          :1,     // - accept an incoming socket connect
                            alarm                           :1,     // - schedule a SIGALRM
                            'atan2'                         :1,     // - arctangent of Y/X in the range -PI to PI
                            bind                            :1,     // - binds an address to a socket
                            binmode                         :1,     // - prepare binary files for I/O
                            bless                           :1,     // - create an object
                            bootstrap                       :1,     //
                            'break'                         :1,     // - break out of a "given" block
                            caller                          :1,     // - get context of the current subroutine call
                            chdir                           :1,     // - change your current working directory
                            chmod                           :1,     // - changes the permissions on a list of files
                            chomp                           :1,     // - remove a trailing record separator from a string
                            chop                            :1,     // - remove the last character from a string
                            chown                           :1,     // - change the owership on a list of files
                            chr                             :1,     // - get character this number represents
                            chroot                          :1,     // - make directory new root for path lookups
                            close                           :1,     // - close file (or pipe or socket) handle
                            closedir                        :1,     // - close directory handle
                            connect                         :1,     // - connect to a remote socket
                            'continue'                      :[1,1], // - optional trailing block in a while or foreach
                            'cos'                           :1,     // - cosine function
                            crypt                           :1,     // - one-way passwd-style encryption
                            dbmclose                        :1,     // - breaks binding on a tied dbm file
                            dbmopen                         :1,     // - create binding on a tied dbm file
                            'default'                       :1,     //
                            defined                         :1,     // - test whether a value, variable, or function is defined
                            'delete'                        :1,     // - deletes a value from a hash
                            die                             :1,     // - raise an exception or bail out
                            'do'                            :1,     // - turn a BLOCK into a TERM
                            dump                            :1,     // - create an immediate core dump
                            each                            :1,     // - retrieve the next key/value pair from a hash
                            endgrent                        :1,     // - be done using group file
                            endhostent                      :1,     // - be done using hosts file
                            endnetent                       :1,     // - be done using networks file
                            endprotoent                     :1,     // - be done using protocols file
                            endpwent                        :1,     // - be done using passwd file
                            endservent                      :1,     // - be done using services file
                            eof                             :1,     // - test a filehandle for its end
                            'eval'                          :1,     // - catch exceptions or compile and run code
                            'exec'                          :1,     // - abandon this program to run another
                            exists                          :1,     // - test whether a hash key is present
                            exit                            :1,     // - terminate this program
                            'exp'                           :1,     // - raise I to a power
                            fcntl                           :1,     // - file control system call
                            fileno                          :1,     // - return file descriptor from filehandle
                            flock                           :1,     // - lock an entire file with an advisory lock
                            fork                            :1,     // - create a new process just like this one
                            format                          :1,     // - declare a picture format with use by the write() function
                            formline                        :1,     // - internal function used for formats
                            getc                            :1,     // - get the next character from the filehandle
                            getgrent                        :1,     // - get next group record
                            getgrgid                        :1,     // - get group record given group user ID
                            getgrnam                        :1,     // - get group record given group name
                            gethostbyaddr                   :1,     // - get host record given its address
                            gethostbyname                   :1,     // - get host record given name
                            gethostent                      :1,     // - get next hosts record
                            getlogin                        :1,     // - return who logged in at this tty
                            getnetbyaddr                    :1,     // - get network record given its address
                            getnetbyname                    :1,     // - get networks record given name
                            getnetent                       :1,     // - get next networks record
                            getpeername                     :1,     // - find the other end of a socket connection
                            getpgrp                         :1,     // - get process group
                            getppid                         :1,     // - get parent process ID
                            getpriority                     :1,     // - get current nice value
                            getprotobyname                  :1,     // - get protocol record given name
                            getprotobynumber                :1,     // - get protocol record numeric protocol
                            getprotoent                     :1,     // - get next protocols record
                            getpwent                        :1,     // - get next passwd record
                            getpwnam                        :1,     // - get passwd record given user login name
                            getpwuid                        :1,     // - get passwd record given user ID
                            getservbyname                   :1,     // - get services record given its name
                            getservbyport                   :1,     // - get services record given numeric port
                            getservent                      :1,     // - get next services record
                            getsockname                     :1,     // - retrieve the sockaddr for a given socket
                            getsockopt                      :1,     // - get socket options on a given socket
                            given                           :1,     //
                            glob                            :1,     // - expand filenames using wildcards
                            gmtime                          :1,     // - convert UNIX time into record or string using Greenwich time
                            'goto'                          :1,     // - create spaghetti code
                            grep                            :1,     // - locate elements in a list test true against a given criterion
                            hex                             :1,     // - convert a string to a hexadecimal number
                            'import'                        :1,     // - patch a module's namespace into your own
                            index                           :1,     // - find a substring within a string
                            'int'                           :1,     // - get the integer portion of a number
                            ioctl                           :1,     // - system-dependent device control system call
                            'join'                          :1,     // - join a list into a string using a separator
                            keys                            :1,     // - retrieve list of indices from a hash
                            kill                            :1,     // - send a signal to a process or process group
                            last                            :1,     // - exit a block prematurely
                            lc                              :1,     // - return lower-case version of a string
                            lcfirst                         :1,     // - return a string with just the next letter in lower case
                            length                          :1,     // - return the number of bytes in a string
                            'link'                          :1,     // - create a hard link in the filesytem
                            listen                          :1,     // - register your socket as a server
                            local                           : 2,    // - create a temporary value for a global variable (dynamic scoping)
                            localtime                       :1,     // - convert UNIX time into record or string using local time
                            lock                            :1,     // - get a thread lock on a variable, subroutine, or method
                            'log'                           :1,     // - retrieve the natural logarithm for a number
                            lstat                           :1,     // - stat a symbolic link
                            m                               :null,  // - match a string with a regular expression pattern
                            map                             :1,     // - apply a change to a list to get back a new list with the changes
                            mkdir                           :1,     // - create a directory
                            msgctl                          :1,     // - SysV IPC message control operations
                            msgget                          :1,     // - get SysV IPC message queue
                            msgrcv                          :1,     // - receive a SysV IPC message from a message queue
                            msgsnd                          :1,     // - send a SysV IPC message to a message queue
                            my                              : 2,    // - declare and assign a local variable (lexical scoping)
                            'new'                           :1,     //
                            next                            :1,     // - iterate a block prematurely
                            no                              :1,     // - unimport some module symbols or semantics at compile time
                            oct                             :1,     // - convert a string to an octal number
                            open                            :1,     // - open a file, pipe, or descriptor
                            opendir                         :1,     // - open a directory
                            ord                             :1,     // - find a character's numeric representation
                            our                             : 2,    // - declare and assign a package variable (lexical scoping)
                            pack                            :1,     // - convert a list into a binary representation
                            'package'                       :1,     // - declare a separate global namespace
                            pipe                            :1,     // - open a pair of connected filehandles
                            pop                             :1,     // - remove the last element from an array and return it
                            pos                             :1,     // - find or set the offset for the last/next m//g search
                            print                           :1,     // - output a list to a filehandle
                            printf                          :1,     // - output a formatted list to a filehandle
                            prototype                       :1,     // - get the prototype (if any) of a subroutine
                            push                            :1,     // - append one or more elements to an array
                            q                               :null,  // - singly quote a string
                            qq                              :null,  // - doubly quote a string
                            qr                              :null,  // - Compile pattern
                            quotemeta                       :null,  // - quote regular expression magic characters
                            qw                              :null,  // - quote a list of words
                            qx                              :null,  // - backquote quote a string
                            rand                            :1,     // - retrieve the next pseudorandom number
                            read                            :1,     // - fixed-length buffered input from a filehandle
                            readdir                         :1,     // - get a directory from a directory handle
                            readline                        :1,     // - fetch a record from a file
                            readlink                        :1,     // - determine where a symbolic link is pointing
                            readpipe                        :1,     // - execute a system command and collect standard output
                            recv                            :1,     // - receive a message over a Socket
                            redo                            :1,     // - start this loop iteration over again
                            ref                             :1,     // - find out the type of thing being referenced
                            rename                          :1,     // - change a filename
                            require                         :1,     // - load in external functions from a library at runtime
                            reset                           :1,     // - clear all variables of a given name
                            'return'                        :1,     // - get out of a function early
                            reverse                         :1,     // - flip a string or a list
                            rewinddir                       :1,     // - reset directory handle
                            rindex                          :1,     // - right-to-left substring search
                            rmdir                           :1,     // - remove a directory
                            s                               :null,  // - replace a pattern with a string
                            say                             :1,     // - print with newline
                            scalar                          :1,     // - force a scalar context
                            seek                            :1,     // - reposition file pointer for random-access I/O
                            seekdir                         :1,     // - reposition directory pointer
                            select                          :1,     // - reset default output or do I/O multiplexing
                            semctl                          :1,     // - SysV semaphore control operations
                            semget                          :1,     // - get set of SysV semaphores
                            semop                           :1,     // - SysV semaphore operations
                            send                            :1,     // - send a message over a socket
                            setgrent                        :1,     // - prepare group file for use
                            sethostent                      :1,     // - prepare hosts file for use
                            setnetent                       :1,     // - prepare networks file for use
                            setpgrp                         :1,     // - set the process group of a process
                            setpriority                     :1,     // - set a process's nice value
                            setprotoent                     :1,     // - prepare protocols file for use
                            setpwent                        :1,     // - prepare passwd file for use
                            setservent                      :1,     // - prepare services file for use
                            setsockopt                      :1,     // - set some socket options
                            shift                           :1,     // - remove the first element of an array, and return it
                            shmctl                          :1,     // - SysV shared memory operations
                            shmget                          :1,     // - get SysV shared memory segment identifier
                            shmread                         :1,     // - read SysV shared memory
                            shmwrite                        :1,     // - write SysV shared memory
                            shutdown                        :1,     // - close down just half of a socket connection
                            'sin'                           :1,     // - return the sine of a number
                            sleep                           :1,     // - block for some number of seconds
                            socket                          :1,     // - create a socket
                            socketpair                      :1,     // - create a pair of sockets
                            'sort'                          :1,     // - sort a list of values
                            splice                          :1,     // - add or remove elements anywhere in an array
                            'split'                         :1,     // - split up a string using a regexp delimiter
                            sprintf                         :1,     // - formatted print into a string
                            'sqrt'                          :1,     // - square root function
                            srand                           :1,     // - seed the random number generator
                            stat                            :1,     // - get a file's status information
                            state                           :1,     // - declare and assign a state variable (persistent lexical scoping)
                            study                           :1,     // - optimize input data for repeated searches
                            'sub'                           :1,     // - declare a subroutine, possibly anonymously
                            'substr'                        :1,     // - get or alter a portion of a stirng
                            symlink                         :1,     // - create a symbolic link to a file
                            syscall                         :1,     // - execute an arbitrary system call
                            sysopen                         :1,     // - open a file, pipe, or descriptor
                            sysread                         :1,     // - fixed-length unbuffered input from a filehandle
                            sysseek                         :1,     // - position I/O pointer on handle used with sysread and syswrite
                            system                          :1,     // - run a separate program
                            syswrite                        :1,     // - fixed-length unbuffered output to a filehandle
                            tell                            :1,     // - get current seekpointer on a filehandle
                            telldir                         :1,     // - get current seekpointer on a directory handle
                            tie                             :1,     // - bind a variable to an object class
                            tied                            :1,     // - get a reference to the object underlying a tied variable
                            time                            :1,     // - return number of seconds since 1970
                            times                           :1,     // - return elapsed time for self and child processes
                            tr                              :null,  // - transliterate a string
                            truncate                        :1,     // - shorten a file
                            uc                              :1,     // - return upper-case version of a string
                            ucfirst                         :1,     // - return a string with just the next letter in upper case
                            umask                           :1,     // - set file creation mode mask
                            undef                           :1,     // - remove a variable or function definition
                            unlink                          :1,     // - remove one link to a file
                            unpack                          :1,     // - convert binary structure into normal perl variables
                            unshift                         :1,     // - prepend more elements to the beginning of a list
                            untie                           :1,     // - break a tie binding to a variable
                            use                             :1,     // - load in a module at compile time
                            utime                           :1,     // - set a file's last access and modify times
                            values                          :1,     // - return a list of the values in a hash
                            vec                             :1,     // - test or set particular bits in a string
                            wait                            :1,     // - wait for any child process to die
                            waitpid                         :1,     // - wait for a particular child process to die
                            wantarray                       :1,     // - get void vs scalar vs list context of current subroutine call
                            warn                            :1,     // - print debugging info
                            when                            :1,     //
                            write                           :1,     // - print a picture record
                            y                               :null}; // - transliterate a string
            
                    var RXstyle="string-2";
                    var RXmodifiers=/[goseximacplud]/;              // NOTE: "m", "s", "y" and "tr" need to correct real modifiers for each regexp type
            
                    function tokenChain(stream,state,chain,style,tail){     // NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;)
                            state.chain=null;                               //                                                          12   3tail
                            state.style=null;
                            state.tail=null;
                            state.tokenize=function(stream,state){
                                    var e=false,c,i=0;
                                    while(c=stream.next()){
                                            if(c===chain[i]&&!e){
                                                    if(chain[++i]!==undefined){
                                                            state.chain=chain[i];
                                                            state.style=style;
                                                            state.tail=tail;}
                                                    else if(tail)
                                                            stream.eatWhile(tail);
                                                    state.tokenize=tokenPerl;
                                                    return style;}
                                            e=!e&&c=="\\";}
                                    return style;};
                            return state.tokenize(stream,state);}
            
                    function tokenSOMETHING(stream,state,string){
                            state.tokenize=function(stream,state){
                                    if(stream.string==string)
                                            state.tokenize=tokenPerl;
                                    stream.skipToEnd();
                                    return "string";};
                            return state.tokenize(stream,state);}
            
                    function tokenPerl(stream,state){
                            if(stream.eatSpace())
                                    return null;
                            if(state.chain)
                                    return tokenChain(stream,state,state.chain,state.style,state.tail);
                            if(stream.match(/^\-?[\d\.]/,false))
                                    if(stream.match(/^(\-?(\d*\.\d+(e[+-]?\d+)?|\d+\.\d*)|0x[\da-fA-F]+|0b[01]+|\d+(e[+-]?\d+)?)/))
                                            return 'number';
                            if(stream.match(/^<<(?=\w)/)){                  // NOTE: <<SOMETHING\n...\nSOMETHING\n
                                    stream.eatWhile(/\w/);
                                    return tokenSOMETHING(stream,state,stream.current().substr(2));}
                            if(stream.sol()&&stream.match(/^\=item(?!\w)/)){// NOTE: \n=item...\n=cut\n
                                    return tokenSOMETHING(stream,state,'=cut');}
                            var ch=stream.next();
                            if(ch=='"'||ch=="'"){                           // NOTE: ' or " or <<'SOMETHING'\n...\nSOMETHING\n or <<"SOMETHING"\n...\nSOMETHING\n
                                    if(prefix(stream, 3)=="<<"+ch){
                                            var p=stream.pos;
                                            stream.eatWhile(/\w/);
                                            var n=stream.current().substr(1);
                                            if(n&&stream.eat(ch))
                                                    return tokenSOMETHING(stream,state,n);
                                            stream.pos=p;}
                                    return tokenChain(stream,state,[ch],"string");}
                            if(ch=="q"){
                                    var c=look(stream, -2);
                                    if(!(c&&/\w/.test(c))){
                                            c=look(stream, 0);
                                            if(c=="x"){
                                                    c=look(stream, 1);
                                                    if(c=="("){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}
                                                    if(c=="["){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}
                                                    if(c=="{"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}
                                                    if(c=="<"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}
                                                    if(/[\^'"!~\/]/.test(c)){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}
                                            else if(c=="q"){
                                                    c=look(stream, 1);
                                                    if(c=="("){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[")"],"string");}
                                                    if(c=="["){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["]"],"string");}
                                                    if(c=="{"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["}"],"string");}
                                                    if(c=="<"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[">"],"string");}
                                                    if(/[\^'"!~\/]/.test(c)){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,[stream.eat(c)],"string");}}
                                            else if(c=="w"){
                                                    c=look(stream, 1);
                                                    if(c=="("){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[")"],"bracket");}
                                                    if(c=="["){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["]"],"bracket");}
                                                    if(c=="{"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["}"],"bracket");}
                                                    if(c=="<"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[">"],"bracket");}
                                                    if(/[\^'"!~\/]/.test(c)){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,[stream.eat(c)],"bracket");}}
                                            else if(c=="r"){
                                                    c=look(stream, 1);
                                                    if(c=="("){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}
                                                    if(c=="["){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}
                                                    if(c=="{"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}
                                                    if(c=="<"){
                                                            eatSuffix(stream, 2);
                                                            return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}
                                                    if(/[\^'"!~\/]/.test(c)){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}
                                            else if(/[\^'"!~\/(\[{<]/.test(c)){
                                                    if(c=="("){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,[")"],"string");}
                                                    if(c=="["){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,["]"],"string");}
                                                    if(c=="{"){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,["}"],"string");}
                                                    if(c=="<"){
                                                            eatSuffix(stream, 1);
                                                            return tokenChain(stream,state,[">"],"string");}
                                                    if(/[\^'"!~\/]/.test(c)){
                                                            return tokenChain(stream,state,[stream.eat(c)],"string");}}}}
                            if(ch=="m"){
                                    var c=look(stream, -2);
                                    if(!(c&&/\w/.test(c))){
                                            c=stream.eat(/[(\[{<\^'"!~\/]/);
                                            if(c){
                                                    if(/[\^'"!~\/]/.test(c)){
                                                            return tokenChain(stream,state,[c],RXstyle,RXmodifiers);}
                                                    if(c=="("){
                                                            return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}
                                                    if(c=="["){
                                                            return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}
                                                    if(c=="{"){
                                                            return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}
                                                    if(c=="<"){
                                                            return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}}}}
                            if(ch=="s"){
                                    var c=/[\/>\]})\w]/.test(look(stream, -2));
                                    if(!c){
                                            c=stream.eat(/[(\[{<\^'"!~\/]/);
                                            if(c){
                                                    if(c=="[")
                                                            return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
                                                    if(c=="{")
                                                            return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
                                                    if(c=="<")
                                                            return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
                                                    if(c=="(")
                                                            return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
                                                    return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}
                            if(ch=="y"){
                                    var c=/[\/>\]})\w]/.test(look(stream, -2));
                                    if(!c){
                                            c=stream.eat(/[(\[{<\^'"!~\/]/);
                                            if(c){
                                                    if(c=="[")
                                                            return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
                                                    if(c=="{")
                                                            return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
                                                    if(c=="<")
                                                            return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
                                                    if(c=="(")
                                                            return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
                                                    return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}
                            if(ch=="t"){
                                    var c=/[\/>\]})\w]/.test(look(stream, -2));
                                    if(!c){
                                            c=stream.eat("r");if(c){
                                            c=stream.eat(/[(\[{<\^'"!~\/]/);
                                            if(c){
                                                    if(c=="[")
                                                            return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
                                                    if(c=="{")
                                                            return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
                                                    if(c=="<")
                                                            return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
                                                    if(c=="(")
                                                            return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
                                                    return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}}
                            if(ch=="`"){
                                    return tokenChain(stream,state,[ch],"variable-2");}
                            if(ch=="/"){
                                    if(!/~\s*$/.test(prefix(stream)))
                                            return "operator";
                                    else
                                            return tokenChain(stream,state,[ch],RXstyle,RXmodifiers);}
                            if(ch=="$"){
                                    var p=stream.pos;
                                    if(stream.eatWhile(/\d/)||stream.eat("{")&&stream.eatWhile(/\d/)&&stream.eat("}"))
                                            return "variable-2";
                                    else
                                            stream.pos=p;}
                            if(/[$@%]/.test(ch)){
                                    var p=stream.pos;
                                    if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(look(stream, -2))&&stream.eat(/[=|\\\-#?@;:&`~\^!\[\]*'"$+.,\/<>()]/)){
                                            var c=stream.current();
                                            if(PERL[c])
                                                    return "variable-2";}
                                    stream.pos=p;}
                            if(/[$@%&]/.test(ch)){
                                    if(stream.eatWhile(/[\w$\[\]]/)||stream.eat("{")&&stream.eatWhile(/[\w$\[\]]/)&&stream.eat("}")){
                                            var c=stream.current();
                                            if(PERL[c])
                                                    return "variable-2";
                                            else
                                                    return "variable";}}
                            if(ch=="#"){
                                    if(look(stream, -2)!="$"){
                                            stream.skipToEnd();
                                            return "comment";}}
                            if(/[:+\-\^*$&%@=<>!?|\/~\.]/.test(ch)){
                                    var p=stream.pos;
                                    stream.eatWhile(/[:+\-\^*$&%@=<>!?|\/~\.]/);
                                    if(PERL[stream.current()])
                                            return "operator";
                                    else
                                            stream.pos=p;}
                            if(ch=="_"){
                                    if(stream.pos==1){
                                            if(suffix(stream, 6)=="_END__"){
                                                    return tokenChain(stream,state,['\0'],"comment");}
                                            else if(suffix(stream, 7)=="_DATA__"){
                                                    return tokenChain(stream,state,['\0'],"variable-2");}
                                            else if(suffix(stream, 7)=="_C__"){
                                                    return tokenChain(stream,state,['\0'],"string");}}}
                            if(/\w/.test(ch)){
                                    var p=stream.pos;
                                    if(look(stream, -2)=="{"&&(look(stream, 0)=="}"||stream.eatWhile(/\w/)&&look(stream, 0)=="}"))
                                            return "string";
                                    else
                                            stream.pos=p;}
                            if(/[A-Z]/.test(ch)){
                                    var l=look(stream, -2);
                                    var p=stream.pos;
                                    stream.eatWhile(/[A-Z_]/);
                                    if(/[\da-z]/.test(look(stream, 0))){
                                            stream.pos=p;}
                                    else{
                                            var c=PERL[stream.current()];
                                            if(!c)
                                                    return "meta";
                                            if(c[1])
                                                    c=c[0];
                                            if(l!=":"){
                                                    if(c==1)
                                                            return "keyword";
                                                    else if(c==2)
                                                            return "def";
                                                    else if(c==3)
                                                            return "atom";
                                                    else if(c==4)
                                                            return "operator";
                                                    else if(c==5)
                                                            return "variable-2";
                                                    else
                                                            return "meta";}
                                            else
                                                    return "meta";}}
                            if(/[a-zA-Z_]/.test(ch)){
                                    var l=look(stream, -2);
                                    stream.eatWhile(/\w/);
                                    var c=PERL[stream.current()];
                                    if(!c)
                                            return "meta";
                                    if(c[1])
                                            c=c[0];
                                    if(l!=":"){
                                            if(c==1)
                                                    return "keyword";
                                            else if(c==2)
                                                    return "def";
                                            else if(c==3)
                                                    return "atom";
                                            else if(c==4)
                                                    return "operator";
                                            else if(c==5)
                                                    return "variable-2";
                                            else
                                                    return "meta";}
                                    else
                                            return "meta";}
                            return null;}
            
                    return {
                        startState: function() {
                            return {
                                tokenize: tokenPerl,
                                chain: null,
                                style: null,
                                tail: null
                            };
                        },
                        token: function(stream, state) {
                            return (state.tokenize || tokenPerl)(stream, state);
                        },
                        lineComment: '#'
                    };
            });
            
            CodeMirror.registerHelper("wordChars", "perl", /[\w$]/);
            
            CodeMirror.defineMIME("text/x-perl", "perl");
            
            // it's like "peek", but need for look-ahead or look-behind if index < 0
            function look(stream, c){
              return stream.string.charAt(stream.pos+(c||0));
            }
            
            // return a part of prefix of current stream from current position
            function prefix(stream, c){
              if(c){
                var x=stream.pos-c;
                return stream.string.substr((x>=0?x:0),c);}
              else{
                return stream.string.substr(0,stream.pos-1);
              }
            }
            
            // return a part of suffix of current stream from current position
            function suffix(stream, c){
              var y=stream.string.length;
              var x=y-stream.pos+1;
              return stream.string.substr(stream.pos,(c&&c<y?c:x));
            }
            
            // eating and vomiting a part of stream from current position
            function eatSuffix(stream, c){
              var x=stream.pos+c;
              var y;
              if(x<=0)
                stream.pos=0;
              else if(x>=(y=stream.string.length-1))
                stream.pos=y;
              else
                stream.pos=x;
            }
            
            });
            
        • php
          • index.html
            <!doctype html>
            
            <title>CodeMirror: PHP mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../css/css.js"></script>
            <script src="../clike/clike.js"></script>
            <script src="php.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">PHP</a>
              </ul>
            </div>
            
            <article>
            <h2>PHP mode</h2>
            <form><textarea id="code" name="code">
            <?php
            $a = array('a' => 1, 'b' => 2, 3 => 'c');
            
            echo "$a[a] ${a[3] /* } comment */} {$a[b]} \$a[a]";
            
            function hello($who) {
            	return "Hello $who!";
            }
            ?>
            <p>The program says <?= hello("World") ?>.</p>
            <script>
            	alert("And here is some JS code"); // also colored
            </script>
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "application/x-httpd-php",
                    indentUnit: 4,
                    indentWithTabs: true
                  });
                </script>
            
                <p>Simple HTML/PHP mode based on
                the <a href="../clike/">C-like</a> mode. Depends on XML,
                JavaScript, CSS, HTMLMixed, and C-like modes.</p>
            
                <p><strong>MIME types defined:</strong> <code>application/x-httpd-php</code> (HTML with PHP code), <code>text/x-php</code> (plain, non-wrapped PHP code).</p>
              </article>
            
          • php.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../clike/clike"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../clike/clike"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              function keywords(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              // Helper for stringWithEscapes
              function matchSequence(list, end) {
                if (list.length == 0) return stringWithEscapes(end);
                return function (stream, state) {
                  var patterns = list[0];
                  for (var i = 0; i < patterns.length; i++) if (stream.match(patterns[i][0])) {
                    state.tokenize = matchSequence(list.slice(1), end);
                    return patterns[i][1];
                  }
                  state.tokenize = stringWithEscapes(end);
                  return "string";
                };
              }
              function stringWithEscapes(closing) {
                return function(stream, state) { return stringWithEscapes_(stream, state, closing); };
              }
              function stringWithEscapes_(stream, state, closing) {
                // "Complex" syntax
                if (stream.match("${", false) || stream.match("{$", false)) {
                  state.tokenize = null;
                  return "string";
                }
            
                // Simple syntax
                if (stream.match(/^\$[a-zA-Z_][a-zA-Z0-9_]*/)) {
                  // After the variable name there may appear array or object operator.
                  if (stream.match("[", false)) {
                    // Match array operator
                    state.tokenize = matchSequence([
                      [["[", null]],
                      [[/\d[\w\.]*/, "number"],
                       [/\$[a-zA-Z_][a-zA-Z0-9_]*/, "variable-2"],
                       [/[\w\$]+/, "variable"]],
                      [["]", null]]
                    ], closing);
                  }
                  if (stream.match(/\-\>\w/, false)) {
                    // Match object operator
                    state.tokenize = matchSequence([
                      [["->", null]],
                      [[/[\w]+/, "variable"]]
                    ], closing);
                  }
                  return "variable-2";
                }
            
                var escaped = false;
                // Normal string
                while (!stream.eol() &&
                       (escaped || (!stream.match("{$", false) &&
                                    !stream.match(/^(\$[a-zA-Z_][a-zA-Z0-9_]*|\$\{)/, false)))) {
                  if (!escaped && stream.match(closing)) {
                    state.tokenize = null;
                    state.tokStack.pop(); state.tokStack.pop();
                    break;
                  }
                  escaped = stream.next() == "\\" && !escaped;
                }
                return "string";
              }
            
              var phpKeywords = "abstract and array as break case catch class clone const continue declare default " +
                "do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final " +
                "for foreach function global goto if implements interface instanceof namespace " +
                "new or private protected public static switch throw trait try use var while xor " +
                "die echo empty exit eval include include_once isset list require require_once return " +
                "print unset __halt_compiler self static parent yield insteadof finally";
              var phpAtoms = "true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__";
              var phpBuiltin = "func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_pause curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysqli_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count";
              CodeMirror.registerHelper("hintWords", "php", [phpKeywords, phpAtoms, phpBuiltin].join(" ").split(" "));
              CodeMirror.registerHelper("wordChars", "php", /[\w$]/);
            
              var phpConfig = {
                name: "clike",
                helperType: "php",
                keywords: keywords(phpKeywords),
                blockKeywords: keywords("catch do else elseif for foreach if switch try while finally"),
                atoms: keywords(phpAtoms),
                builtin: keywords(phpBuiltin),
                multiLineStrings: true,
                hooks: {
                  "$": function(stream) {
                    stream.eatWhile(/[\w\$_]/);
                    return "variable-2";
                  },
                  "<": function(stream, state) {
                    if (stream.match(/<</)) {
                      stream.eatWhile(/[\w\.]/);
                      var delim = stream.current().slice(3);
                      if (delim) {
                        (state.tokStack || (state.tokStack = [])).push(delim, 0);
                        state.tokenize = stringWithEscapes(delim);
                        return "string";
                      }
                    }
                    return false;
                  },
                  "#": function(stream) {
                    while (!stream.eol() && !stream.match("?>", false)) stream.next();
                    return "comment";
                  },
                  "/": function(stream) {
                    if (stream.eat("/")) {
                      while (!stream.eol() && !stream.match("?>", false)) stream.next();
                      return "comment";
                    }
                    return false;
                  },
                  '"': function(_stream, state) {
                    (state.tokStack || (state.tokStack = [])).push('"', 0);
                    state.tokenize = stringWithEscapes('"');
                    return "string";
                  },
                  "{": function(_stream, state) {
                    if (state.tokStack && state.tokStack.length)
                      state.tokStack[state.tokStack.length - 1]++;
                    return false;
                  },
                  "}": function(_stream, state) {
                    if (state.tokStack && state.tokStack.length > 0 &&
                        !--state.tokStack[state.tokStack.length - 1]) {
                      state.tokenize = stringWithEscapes(state.tokStack[state.tokStack.length - 2]);
                    }
                    return false;
                  }
                }
              };
            
              CodeMirror.defineMode("php", function(config, parserConfig) {
                var htmlMode = CodeMirror.getMode(config, "text/html");
                var phpMode = CodeMirror.getMode(config, phpConfig);
            
                function dispatch(stream, state) {
                  var isPHP = state.curMode == phpMode;
                  if (stream.sol() && state.pending && state.pending != '"' && state.pending != "'") state.pending = null;
                  if (!isPHP) {
                    if (stream.match(/^<\?\w*/)) {
                      state.curMode = phpMode;
                      state.curState = state.php;
                      return "meta";
                    }
                    if (state.pending == '"' || state.pending == "'") {
                      while (!stream.eol() && stream.next() != state.pending) {}
                      var style = "string";
                    } else if (state.pending && stream.pos < state.pending.end) {
                      stream.pos = state.pending.end;
                      var style = state.pending.style;
                    } else {
                      var style = htmlMode.token(stream, state.curState);
                    }
                    if (state.pending) state.pending = null;
                    var cur = stream.current(), openPHP = cur.search(/<\?/), m;
                    if (openPHP != -1) {
                      if (style == "string" && (m = cur.match(/[\'\"]$/)) && !/\?>/.test(cur)) state.pending = m[0];
                      else state.pending = {end: stream.pos, style: style};
                      stream.backUp(cur.length - openPHP);
                    }
                    return style;
                  } else if (isPHP && state.php.tokenize == null && stream.match("?>")) {
                    state.curMode = htmlMode;
                    state.curState = state.html;
                    return "meta";
                  } else {
                    return phpMode.token(stream, state.curState);
                  }
                }
            
                return {
                  startState: function() {
                    var html = CodeMirror.startState(htmlMode), php = CodeMirror.startState(phpMode);
                    return {html: html,
                            php: php,
                            curMode: parserConfig.startOpen ? phpMode : htmlMode,
                            curState: parserConfig.startOpen ? php : html,
                            pending: null};
                  },
            
                  copyState: function(state) {
                    var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),
                        php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;
                    if (state.curMode == htmlMode) cur = htmlNew;
                    else cur = phpNew;
                    return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,
                            pending: state.pending};
                  },
            
                  token: dispatch,
            
                  indent: function(state, textAfter) {
                    if ((state.curMode != phpMode && /^\s*<\//.test(textAfter)) ||
                        (state.curMode == phpMode && /^\?>/.test(textAfter)))
                      return htmlMode.indent(state.html, textAfter);
                    return state.curMode.indent(state.curState, textAfter);
                  },
            
                  blockCommentStart: "/*",
                  blockCommentEnd: "*/",
                  lineComment: "//",
            
                  innerMode: function(state) { return {state: state.curState, mode: state.curMode}; }
                };
              }, "htmlmixed", "clike");
            
              CodeMirror.defineMIME("application/x-httpd-php", "php");
              CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true});
              CodeMirror.defineMIME("text/x-php", phpConfig);
            });
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 2}, "php");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT('simple_test',
                 '[meta <?php] ' +
                 '[keyword echo] [string "aaa"]; ' +
                 '[meta ?>]');
            
              MT('variable_interpolation_non_alphanumeric',
                 '[meta <?php]',
                 '[keyword echo] [string "aaa$~$!$@$#$$$%$^$&$*$($)$.$<$>$/$\\$}$\\\"$:$;$?$|$[[$]]$+$=aaa"]',
                 '[meta ?>]');
            
              MT('variable_interpolation_digits',
                 '[meta <?php]',
                 '[keyword echo] [string "aaa$1$2$3$4$5$6$7$8$9$0aaa"]',
                 '[meta ?>]');
            
              MT('variable_interpolation_simple_syntax_1',
                 '[meta <?php]',
                 '[keyword echo] [string "aaa][variable-2 $aaa][string .aaa"];',
                 '[meta ?>]');
            
              MT('variable_interpolation_simple_syntax_2',
                 '[meta <?php]',
                 '[keyword echo] [string "][variable-2 $aaaa][[','[number 2]',         ']][string aa"];',
                 '[keyword echo] [string "][variable-2 $aaaa][[','[number 2345]',      ']][string aa"];',
                 '[keyword echo] [string "][variable-2 $aaaa][[','[number 2.3]',       ']][string aa"];',
                 '[keyword echo] [string "][variable-2 $aaaa][[','[variable aaaaa]',   ']][string aa"];',
                 '[keyword echo] [string "][variable-2 $aaaa][[','[variable-2 $aaaaa]',']][string aa"];',
            
                 '[keyword echo] [string "1aaa][variable-2 $aaaa][[','[number 2]',         ']][string aa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa][[','[number 2345]',      ']][string aa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa][[','[number 2.3]',       ']][string aa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa][[','[variable aaaaa]',   ']][string aa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa][[','[variable-2 $aaaaa]',']][string aa"];',
                 '[meta ?>]');
            
              MT('variable_interpolation_simple_syntax_3',
                 '[meta <?php]',
                 '[keyword echo] [string "aaa][variable-2 $aaaa]->[variable aaaaa][string .aaaaaa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa][string ->][variable-2 $aaaaa][string .aaaaaa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa]->[variable aaaaa][string [[2]].aaaaaa"];',
                 '[keyword echo] [string "aaa][variable-2 $aaaa]->[variable aaaaa][string ->aaaa2.aaaaaa"];',
                 '[meta ?>]');
            
              MT('variable_interpolation_escaping',
                 '[meta <?php] [comment /* Escaping */]',
                 '[keyword echo] [string "aaa\\$aaaa->aaa.aaa"];',
                 '[keyword echo] [string "aaa\\$aaaa[[2]]aaa.aaa"];',
                 '[keyword echo] [string "aaa\\$aaaa[[asd]]aaa.aaa"];',
                 '[keyword echo] [string "aaa{\\$aaaa->aaa.aaa"];',
                 '[keyword echo] [string "aaa{\\$aaaa[[2]]aaa.aaa"];',
                 '[keyword echo] [string "aaa{\\aaaaa[[asd]]aaa.aaa"];',
                 '[keyword echo] [string "aaa\\${aaaa->aaa.aaa"];',
                 '[keyword echo] [string "aaa\\${aaaa[[2]]aaa.aaa"];',
                 '[keyword echo] [string "aaa\\${aaaa[[asd]]aaa.aaa"];',
                 '[meta ?>]');
            
              MT('variable_interpolation_complex_syntax_1',
                 '[meta <?php]',
                 '[keyword echo] [string "aaa][variable-2 $]{[variable aaaa]}[string ->aaa.aaa"];',
                 '[keyword echo] [string "aaa][variable-2 $]{[variable-2 $aaaa]}[string ->aaa.aaa"];',
                 '[keyword echo] [string "aaa][variable-2 $]{[variable-2 $aaaa][[','  [number 42]',']]}[string ->aaa.aaa"];',
                 '[keyword echo] [string "aaa][variable-2 $]{[variable aaaa][meta ?>]aaaaaa');
            
              MT('variable_interpolation_complex_syntax_2',
                 '[meta <?php] [comment /* Monsters */]',
                 '[keyword echo] [string "][variable-2 $]{[variable aaa][comment /*}?>} $aaa<?php } */]}[string ->aaa.aaa"];',
                 '[keyword echo] [string "][variable-2 $]{[variable aaa][comment /*}?>*/][[','  [string "aaa][variable-2 $aaa][string {}][variable-2 $]{[variable aaa]}[string "]',']]}[string ->aaa.aaa"];',
                 '[keyword echo] [string "][variable-2 $]{[variable aaa][comment /*} } $aaa } */]}[string ->aaa.aaa"];');
            
            
              function build_recursive_monsters(nt, t, n){
                var monsters = [t];
                for (var i = 1; i <= n; ++i)
                  monsters[i] = nt.join(monsters[i - 1]);
                return monsters;
              }
            
              var m1 = build_recursive_monsters(
                ['[string "][variable-2 $]{[variable aaa] [operator +] ', '}[string "]'],
                '[comment /* }?>} */] [string "aaa][variable-2 $aaa][string .aaa"]',
                10
              );
            
              MT('variable_interpolation_complex_syntax_3_1',
                 '[meta <?php] [comment /* Recursive monsters */]',
                 '[keyword echo] ' + m1[4] + ';',
                 '[keyword echo] ' + m1[7] + ';',
                 '[keyword echo] ' + m1[8] + ';',
                 '[keyword echo] ' + m1[5] + ';',
                 '[keyword echo] ' + m1[1] + ';',
                 '[keyword echo] ' + m1[6] + ';',
                 '[keyword echo] ' + m1[9] + ';',
                 '[keyword echo] ' + m1[0] + ';',
                 '[keyword echo] ' + m1[10] + ';',
                 '[keyword echo] ' + m1[2] + ';',
                 '[keyword echo] ' + m1[3] + ';',
                 '[keyword echo] [string "end"];',
                 '[meta ?>]');
            
              var m2 = build_recursive_monsters(
                ['[string "a][variable-2 $]{[variable aaa] [operator +] ', ' [operator +] ', '}[string .a"]'],
                '[comment /* }?>{{ */] [string "a?>}{{aa][variable-2 $aaa][string .a}a?>a"]',
                5
              );
            
              MT('variable_interpolation_complex_syntax_3_2',
                 '[meta <?php] [comment /* Recursive monsters 2 */]',
                 '[keyword echo] ' + m2[0] + ';',
                 '[keyword echo] ' + m2[1] + ';',
                 '[keyword echo] ' + m2[5] + ';',
                 '[keyword echo] ' + m2[4] + ';',
                 '[keyword echo] ' + m2[2] + ';',
                 '[keyword echo] ' + m2[3] + ';',
                 '[keyword echo] [string "end"];',
                 '[meta ?>]');
            
              function build_recursive_monsters_2(mf1, mf2, nt, t, n){
                var monsters = [t];
                for (var i = 1; i <= n; ++i)
                  monsters[i] = nt[0] + mf1[i - 1] + nt[1] + mf2[i - 1] + nt[2] + monsters[i - 1] + nt[3];
                return monsters;
              }
            
              var m3 = build_recursive_monsters_2(
                m1,
                m2,
                ['[string "a][variable-2 $]{[variable aaa] [operator +] ', ' [operator +] ', ' [operator +] ', '}[string .a"]'],
                '[comment /* }?>{{ */] [string "a?>}{{aa][variable-2 $aaa][string .a}a?>a"]',
                4
              );
            
              MT('variable_interpolation_complex_syntax_3_3',
                 '[meta <?php] [comment /* Recursive monsters 2 */]',
                 '[keyword echo] ' + m3[4] + ';',
                 '[keyword echo] ' + m3[0] + ';',
                 '[keyword echo] ' + m3[3] + ';',
                 '[keyword echo] ' + m3[1] + ';',
                 '[keyword echo] ' + m3[2] + ';',
                 '[keyword echo] [string "end"];',
                 '[meta ?>]');
            
              MT("variable_interpolation_heredoc",
                 "[meta <?php]",
                 "[string <<<here]",
                 "[string doc ][variable-2 $]{[variable yay]}[string more]",
                 "[string here]; [comment // normal]");
            })();
            
        • pig
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Pig Latin mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="pig.js"></script>
            <style>.CodeMirror {border: 2px inset #dee;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Pig Latin</a>
              </ul>
            </div>
            
            <article>
            <h2>Pig Latin mode</h2>
            <form><textarea id="code" name="code">
            -- Apache Pig (Pig Latin Language) Demo
            /* 
            This is a multiline comment.
            */
            a = LOAD "\path\to\input" USING PigStorage('\t') AS (x:long, y:chararray, z:bytearray);
            b = GROUP a BY (x,y,3+4);
            c = FOREACH b GENERATE flatten(group) as (x,y), SUM(group.$2) as z;
            STORE c INTO "\path\to\output";
            
            --
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    indentUnit: 4,
                    mode: "text/x-pig"
                  });
                </script>
            
                <p>
                    Simple mode that handles Pig Latin language.
                </p>
            
                <p><strong>MIME type defined:</strong> <code>text/x-pig</code>
                (PIG code)
            </html>
            </article>
            
          • pig.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*
             *      Pig Latin Mode for CodeMirror 2
             *      @author Prasanth Jayachandran
             *      @link   https://github.com/prasanthj/pig-codemirror-2
             *  This implementation is adapted from PL/SQL mode in CodeMirror 2.
             */
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("pig", function(_config, parserConfig) {
              var keywords = parserConfig.keywords,
              builtins = parserConfig.builtins,
              types = parserConfig.types,
              multiLineStrings = parserConfig.multiLineStrings;
            
              var isOperatorChar = /[*+\-%<>=&?:\/!|]/;
            
              function chain(stream, state, f) {
                state.tokenize = f;
                return f(stream, state);
              }
            
              function tokenComment(stream, state) {
                var isEnd = false;
                var ch;
                while(ch = stream.next()) {
                  if(ch == "/" && isEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  isEnd = (ch == "*");
                }
                return "comment";
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while((next = stream.next()) != null) {
                    if (next == quote && !escaped) {
                      end = true; break;
                    }
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !(escaped || multiLineStrings))
                    state.tokenize = tokenBase;
                  return "error";
                };
              }
            
            
              function tokenBase(stream, state) {
                var ch = stream.next();
            
                // is a start of string?
                if (ch == '"' || ch == "'")
                  return chain(stream, state, tokenString(ch));
                // is it one of the special chars
                else if(/[\[\]{}\(\),;\.]/.test(ch))
                  return null;
                // is it a number?
                else if(/\d/.test(ch)) {
                  stream.eatWhile(/[\w\.]/);
                  return "number";
                }
                // multi line comment or operator
                else if (ch == "/") {
                  if (stream.eat("*")) {
                    return chain(stream, state, tokenComment);
                  }
                  else {
                    stream.eatWhile(isOperatorChar);
                    return "operator";
                  }
                }
                // single line comment or operator
                else if (ch=="-") {
                  if(stream.eat("-")){
                    stream.skipToEnd();
                    return "comment";
                  }
                  else {
                    stream.eatWhile(isOperatorChar);
                    return "operator";
                  }
                }
                // is it an operator
                else if (isOperatorChar.test(ch)) {
                  stream.eatWhile(isOperatorChar);
                  return "operator";
                }
                else {
                  // get the while word
                  stream.eatWhile(/[\w\$_]/);
                  // is it one of the listed keywords?
                  if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {
                    //keywords can be used as variables like flatten(group), group.$0 etc..
                    if (!stream.eat(")") && !stream.eat("."))
                      return "keyword";
                  }
                  // is it one of the builtin functions?
                  if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase()))
                    return "variable-2";
                  // is it one of the listed types?
                  if (types && types.propertyIsEnumerable(stream.current().toUpperCase()))
                    return "variable-3";
                  // default is a 'variable'
                  return "variable";
                }
              }
            
              // Interface
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase,
                    startOfLine: true
                  };
                },
            
                token: function(stream, state) {
                  if(stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
                  return style;
                }
              };
            });
            
            (function() {
              function keywords(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              // builtin funcs taken from trunk revision 1303237
              var pBuiltins = "ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL "
                + "CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS "
                + "DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG "
                + "FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN "
                + "INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER "
                + "ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS "
                + "LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA  "
                + "PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE "
                + "SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG "
                + "TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER ";
            
              // taken from QueryLexer.g
              var pKeywords = "VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP "
                + "JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL "
                + "PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE "
                + "SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE "
                + "NEQ MATCHES TRUE FALSE DUMP";
            
              // data types
              var pTypes = "BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP ";
            
              CodeMirror.defineMIME("text/x-pig", {
                name: "pig",
                builtins: keywords(pBuiltins),
                keywords: keywords(pKeywords),
                types: keywords(pTypes)
              });
            
              CodeMirror.registerHelper("hintWords", "pig", (pBuiltins + pTypes + pKeywords).split(" "));
            }());
            
            });
            
        • properties
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Properties files mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="properties.js"></script>
            <style>.CodeMirror {border-top: 1px solid #ddd; border-bottom: 1px solid #ddd;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Properties files</a>
              </ul>
            </div>
            
            <article>
            <h2>Properties files mode</h2>
            <form><textarea id="code" name="code">
            # This is a properties file
            a.key = A value
            another.key = http://example.com
            ! Exclamation mark as comment
            but.not=Within ! A value # indeed
               # Spaces at the beginning of a line
               spaces.before.key=value
            backslash=Used for multi\
                      line entries,\
                      that's convenient.
            # Unicode sequences
            unicode.key=This is \u0020 Unicode
            no.multiline=here
            # Colons
            colons : can be used too
            # Spaces
            spaces\ in\ keys=Not very common...
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-properties</code>,
                <code>text/x-ini</code>.</p>
            
              </article>
            
          • properties.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("properties", function() {
              return {
                token: function(stream, state) {
                  var sol = stream.sol() || state.afterSection;
                  var eol = stream.eol();
            
                  state.afterSection = false;
            
                  if (sol) {
                    if (state.nextMultiline) {
                      state.inMultiline = true;
                      state.nextMultiline = false;
                    } else {
                      state.position = "def";
                    }
                  }
            
                  if (eol && ! state.nextMultiline) {
                    state.inMultiline = false;
                    state.position = "def";
                  }
            
                  if (sol) {
                    while(stream.eatSpace());
                  }
            
                  var ch = stream.next();
            
                  if (sol && (ch === "#" || ch === "!" || ch === ";")) {
                    state.position = "comment";
                    stream.skipToEnd();
                    return "comment";
                  } else if (sol && ch === "[") {
                    state.afterSection = true;
                    stream.skipTo("]"); stream.eat("]");
                    return "header";
                  } else if (ch === "=" || ch === ":") {
                    state.position = "quote";
                    return null;
                  } else if (ch === "\\" && state.position === "quote") {
                    if (stream.eol()) {  // end of line?
                      // Multiline value
                      state.nextMultiline = true;
                    }
                  }
            
                  return state.position;
                },
            
                startState: function() {
                  return {
                    position : "def",       // Current position, "def", "quote" or "comment"
                    nextMultiline : false,  // Is the next line multiline value
                    inMultiline : false,    // Is the current line a multiline value
                    afterSection : false    // Did we just open a section
                  };
                }
            
              };
            });
            
            CodeMirror.defineMIME("text/x-properties", "properties");
            CodeMirror.defineMIME("text/x-ini", "properties");
            
            });
            
        • puppet
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Puppet mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="puppet.js"></script>
            <style>
                  .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                  .cm-s-default span.cm-arrow { color: red; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Puppet</a>
              </ul>
            </div>
            
            <article>
            <h2>Puppet mode</h2>
            <form><textarea id="code" name="code">
            # == Class: automysqlbackup
            #
            # Puppet module to install AutoMySQLBackup for periodic MySQL backups.
            #
            # class { 'automysqlbackup':
            #   backup_dir => '/mnt/backups',
            # }
            #
            
            class automysqlbackup (
              $bin_dir = $automysqlbackup::params::bin_dir,
              $etc_dir = $automysqlbackup::params::etc_dir,
              $backup_dir = $automysqlbackup::params::backup_dir,
              $install_multicore = undef,
              $config = {},
              $config_defaults = {},
            ) inherits automysqlbackup::params {
            
            # Ensure valid paths are assigned
              validate_absolute_path($bin_dir)
              validate_absolute_path($etc_dir)
              validate_absolute_path($backup_dir)
            
            # Create a subdirectory in /etc for config files
              file { $etc_dir:
                ensure => directory,
                owner => 'root',
                group => 'root',
                mode => '0750',
              }
            
            # Create an example backup file, useful for reference
              file { "${etc_dir}/automysqlbackup.conf.example":
                ensure => file,
                owner => 'root',
                group => 'root',
                mode => '0660',
                source => 'puppet:///modules/automysqlbackup/automysqlbackup.conf',
              }
            
            # Add files from the developer
              file { "${etc_dir}/AMB_README":
                ensure => file,
                source => 'puppet:///modules/automysqlbackup/AMB_README',
              }
              file { "${etc_dir}/AMB_LICENSE":
                ensure => file,
                source => 'puppet:///modules/automysqlbackup/AMB_LICENSE',
              }
            
            # Install the actual binary file
              file { "${bin_dir}/automysqlbackup":
                ensure => file,
                owner => 'root',
                group => 'root',
                mode => '0755',
                source => 'puppet:///modules/automysqlbackup/automysqlbackup',
              }
            
            # Create the base backup directory
              file { $backup_dir:
                ensure => directory,
                owner => 'root',
                group => 'root',
                mode => '0755',
              }
            
            # If you'd like to keep your config in hiera and pass it to this class
              if !empty($config) {
                create_resources('automysqlbackup::backup', $config, $config_defaults)
              }
            
            # If using RedHat family, must have the RPMforge repo's enabled
              if $install_multicore {
                package { ['pigz', 'pbzip2']: ensure => installed }
              }
            
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/x-puppet",
                    matchBrackets: true,
                    indentUnit: 4
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-puppet</code>.</p>
            
              </article>
            
          • puppet.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("puppet", function () {
              // Stores the words from the define method
              var words = {};
              // Taken, mostly, from the Puppet official variable standards regex
              var variable_regex = /({)?([a-z][a-z0-9_]*)?((::[a-z][a-z0-9_]*)*::)?[a-zA-Z0-9_]+(})?/;
            
              // Takes a string of words separated by spaces and adds them as
              // keys with the value of the first argument 'style'
              function define(style, string) {
                var split = string.split(' ');
                for (var i = 0; i < split.length; i++) {
                  words[split[i]] = style;
                }
              }
            
              // Takes commonly known puppet types/words and classifies them to a style
              define('keyword', 'class define site node include import inherits');
              define('keyword', 'case if else in and elsif default or');
              define('atom', 'false true running present absent file directory undef');
              define('builtin', 'action augeas burst chain computer cron destination dport exec ' +
                'file filebucket group host icmp iniface interface jump k5login limit log_level ' +
                'log_prefix macauthorization mailalias maillist mcx mount nagios_command ' +
                'nagios_contact nagios_contactgroup nagios_host nagios_hostdependency ' +
                'nagios_hostescalation nagios_hostextinfo nagios_hostgroup nagios_service ' +
                'nagios_servicedependency nagios_serviceescalation nagios_serviceextinfo ' +
                'nagios_servicegroup nagios_timeperiod name notify outiface package proto reject ' +
                'resources router schedule scheduled_task selboolean selmodule service source ' +
                'sport ssh_authorized_key sshkey stage state table tidy todest toports tosource ' +
                'user vlan yumrepo zfs zone zpool');
            
              // After finding a start of a string ('|") this function attempts to find the end;
              // If a variable is encountered along the way, we display it differently when it
              // is encapsulated in a double-quoted string.
              function tokenString(stream, state) {
                var current, prev, found_var = false;
                while (!stream.eol() && (current = stream.next()) != state.pending) {
                  if (current === '$' && prev != '\\' && state.pending == '"') {
                    found_var = true;
                    break;
                  }
                  prev = current;
                }
                if (found_var) {
                  stream.backUp(1);
                }
                if (current == state.pending) {
                  state.continueString = false;
                } else {
                  state.continueString = true;
                }
                return "string";
              }
            
              // Main function
              function tokenize(stream, state) {
                // Matches one whole word
                var word = stream.match(/[\w]+/, false);
                // Matches attributes (i.e. ensure => present ; 'ensure' would be matched)
                var attribute = stream.match(/(\s+)?\w+\s+=>.*/, false);
                // Matches non-builtin resource declarations
                // (i.e. "apache::vhost {" or "mycustomclasss {" would be matched)
                var resource = stream.match(/(\s+)?[\w:_]+(\s+)?{/, false);
                // Matches virtual and exported resources (i.e. @@user { ; and the like)
                var special_resource = stream.match(/(\s+)?[@]{1,2}[\w:_]+(\s+)?{/, false);
            
                // Finally advance the stream
                var ch = stream.next();
            
                // Have we found a variable?
                if (ch === '$') {
                  if (stream.match(variable_regex)) {
                    // If so, and its in a string, assign it a different color
                    return state.continueString ? 'variable-2' : 'variable';
                  }
                  // Otherwise return an invalid variable
                  return "error";
                }
                // Should we still be looking for the end of a string?
                if (state.continueString) {
                  // If so, go through the loop again
                  stream.backUp(1);
                  return tokenString(stream, state);
                }
                // Are we in a definition (class, node, define)?
                if (state.inDefinition) {
                  // If so, return def (i.e. for 'class myclass {' ; 'myclass' would be matched)
                  if (stream.match(/(\s+)?[\w:_]+(\s+)?/)) {
                    return 'def';
                  }
                  // Match the rest it the next time around
                  stream.match(/\s+{/);
                  state.inDefinition = false;
                }
                // Are we in an 'include' statement?
                if (state.inInclude) {
                  // Match and return the included class
                  stream.match(/(\s+)?\S+(\s+)?/);
                  state.inInclude = false;
                  return 'def';
                }
                // Do we just have a function on our hands?
                // In 'ensure_resource("myclass")', 'ensure_resource' is matched
                if (stream.match(/(\s+)?\w+\(/)) {
                  stream.backUp(1);
                  return 'def';
                }
                // Have we matched the prior attribute regex?
                if (attribute) {
                  stream.match(/(\s+)?\w+/);
                  return 'tag';
                }
                // Do we have Puppet specific words?
                if (word && words.hasOwnProperty(word)) {
                  // Negates the initial next()
                  stream.backUp(1);
                  // Acutally move the stream
                  stream.match(/[\w]+/);
                  // We want to process these words differently
                  // do to the importance they have in Puppet
                  if (stream.match(/\s+\S+\s+{/, false)) {
                    state.inDefinition = true;
                  }
                  if (word == 'include') {
                    state.inInclude = true;
                  }
                  // Returns their value as state in the prior define methods
                  return words[word];
                }
                // Is there a match on a reference?
                if (/(^|\s+)[A-Z][\w:_]+/.test(word)) {
                  // Negate the next()
                  stream.backUp(1);
                  // Match the full reference
                  stream.match(/(^|\s+)[A-Z][\w:_]+/);
                  return 'def';
                }
                // Have we matched the prior resource regex?
                if (resource) {
                  stream.match(/(\s+)?[\w:_]+/);
                  return 'def';
                }
                // Have we matched the prior special_resource regex?
                if (special_resource) {
                  stream.match(/(\s+)?[@]{1,2}/);
                  return 'special';
                }
                // Match all the comments. All of them.
                if (ch == "#") {
                  stream.skipToEnd();
                  return "comment";
                }
                // Have we found a string?
                if (ch == "'" || ch == '"') {
                  // Store the type (single or double)
                  state.pending = ch;
                  // Perform the looping function to find the end
                  return tokenString(stream, state);
                }
                // Match all the brackets
                if (ch == '{' || ch == '}') {
                  return 'bracket';
                }
                // Match characters that we are going to assume
                // are trying to be regex
                if (ch == '/') {
                  stream.match(/.*?\//);
                  return 'variable-3';
                }
                // Match all the numbers
                if (ch.match(/[0-9]/)) {
                  stream.eatWhile(/[0-9]+/);
                  return 'number';
                }
                // Match the '=' and '=>' operators
                if (ch == '=') {
                  if (stream.peek() == '>') {
                      stream.next();
                  }
                  return "operator";
                }
                // Keep advancing through all the rest
                stream.eatWhile(/[\w-]/);
                // Return a blank line for everything else
                return null;
              }
              // Start it all
              return {
                startState: function () {
                  var state = {};
                  state.inDefinition = false;
                  state.inInclude = false;
                  state.continueString = false;
                  state.pending = false;
                  return state;
                },
                token: function (stream, state) {
                  // Strip the spaces, but regex will account for them eitherway
                  if (stream.eatSpace()) return null;
                  // Go through the main process
                  return tokenize(stream, state);
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-puppet", "puppet");
            
            });
            
        • python
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Python mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="python.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Python</a>
              </ul>
            </div>
            
            <article>
            <h2>Python mode</h2>
            
                <div><textarea id="code" name="code">
            # Literals
            1234
            0.0e101
            .123
            0b01010011100
            0o01234567
            0x0987654321abcdef
            7
            2147483647
            3L
            79228162514264337593543950336L
            0x100000000L
            79228162514264337593543950336
            0xdeadbeef
            3.14j
            10.j
            10j
            .001j
            1e100j
            3.14e-10j
            
            
            # String Literals
            'For\''
            "God\""
            """so loved
            the world"""
            '''that he gave
            his only begotten\' '''
            'that whosoever believeth \
            in him'
            ''
            
            # Identifiers
            __a__
            a.b
            a.b.c
            
            #Unicode identifiers on Python3
            # a = x\ddot
            a⃗ = ẍ
            # a = v\dot
            a⃗ = v̇
            
            #F\vec = m \cdot a\vec
            F⃗ = m•a⃗ 
            
            # Operators
            + - * / % & | ^ ~ < >
            == != <= >= <> << >> // **
            and or not in is
            
            #infix matrix multiplication operator (PEP 465)
            A @ B
            
            # Delimiters
            () [] {} , : ` = ; @ .  # Note that @ and . require the proper context on Python 2.
            += -= *= /= %= &= |= ^=
            //= >>= <<= **=
            
            # Keywords
            as assert break class continue def del elif else except
            finally for from global if import lambda pass raise
            return try while with yield
            
            # Python 2 Keywords (otherwise Identifiers)
            exec print
            
            # Python 3 Keywords (otherwise Identifiers)
            nonlocal
            
            # Types
            bool classmethod complex dict enumerate float frozenset int list object
            property reversed set slice staticmethod str super tuple type
            
            # Python 2 Types (otherwise Identifiers)
            basestring buffer file long unicode xrange
            
            # Python 3 Types (otherwise Identifiers)
            bytearray bytes filter map memoryview open range zip
            
            # Some Example code
            import os
            from package import ParentClass
            
            @nonsenseDecorator
            def doesNothing():
                pass
            
            class ExampleClass(ParentClass):
                @staticmethod
                def example(inputStr):
                    a = list(inputStr)
                    a.reverse()
                    return ''.join(a)
            
                def __init__(self, mixin = 'Hello'):
                    self.mixin = mixin
            
            </textarea></div>
            
            
            <h2>Cython mode</h2>
            
            <div><textarea id="code-cython" name="code-cython">
            
            import numpy as np
            cimport cython
            from libc.math cimport sqrt
            
            @cython.boundscheck(False)
            @cython.wraparound(False)
            def pairwise_cython(double[:, ::1] X):
                cdef int M = X.shape[0]
                cdef int N = X.shape[1]
                cdef double tmp, d
                cdef double[:, ::1] D = np.empty((M, M), dtype=np.float64)
                for i in range(M):
                    for j in range(M):
                        d = 0.0
                        for k in range(N):
                            tmp = X[i, k] - X[j, k]
                            d += tmp * tmp
                        D[i, j] = sqrt(d)
                return np.asarray(D)
            
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "python",
                           version: 3,
                           singleLineStringErrors: false},
                    lineNumbers: true,
                    indentUnit: 4,
                    matchBrackets: true
                });
            
                CodeMirror.fromTextArea(document.getElementById("code-cython"), {
                    mode: {name: "text/x-cython",
                           version: 2,
                           singleLineStringErrors: false},
                    lineNumbers: true,
                    indentUnit: 4,
                    matchBrackets: true
                  });
                </script>
                <h2>Configuration Options for Python mode:</h2>
                <ul>
                  <li>version - 2/3 - The version of Python to recognize.  Default is 2.</li>
                  <li>singleLineStringErrors - true/false - If you have a single-line string that is not terminated at the end of the line, this will show subsequent lines as errors if true, otherwise it will consider the newline as the end of the string. Default is false.</li>
                  <li>hangingIndent - int - If you want to write long arguments to a function starting on a new line, how much that line should be indented. Defaults to one normal indentation unit.</li>
                </ul>
                <h2>Advanced Configuration Options:</h2>
                <p>Usefull for superset of python syntax like Enthought enaml, IPython magics and  questionmark help</p>
                <ul>
                  <li>singleOperators - RegEx - Regular Expression for single operator matching,  default : <pre>^[\\+\\-\\*/%&amp;|\\^~&lt;&gt;!]</pre> including <pre>@</pre> on Python 3</li>
                  <li>singleDelimiters - RegEx - Regular Expression for single delimiter matching, default :  <pre>^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]</pre></li>
                  <li>doubleOperators - RegEx - Regular Expression for double operators matching, default : <pre>^((==)|(!=)|(&lt;=)|(&gt;=)|(&lt;&gt;)|(&lt;&lt;)|(&gt;&gt;)|(//)|(\\*\\*))</pre></li>
                  <li>doubleDelimiters - RegEx - Regular Expressoin for double delimiters matching, default : <pre>^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&amp;=)|(\\|=)|(\\^=))</pre></li>
                  <li>tripleDelimiters - RegEx - Regular Expression for triple delimiters matching, default : <pre>^((//=)|(&gt;&gt;=)|(&lt;&lt;=)|(\\*\\*=))</pre></li>
                  <li>identifiers - RegEx - Regular Expression for identifier, default : <pre>^[_A-Za-z][_A-Za-z0-9]*</pre> on Python 2 and <pre>^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*</pre> on Python 3.</li>
                  <li>extra_keywords - list of string - List of extra words ton consider as keywords</li>
                  <li>extra_builtins - list of string - List of extra words ton consider as builtins</li>
                </ul>
            
            
                <p><strong>MIME types defined:</strong> <code>text/x-python</code> and <code>text/x-cython</code>.</p>
              </article>
            
          • python.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              function wordRegexp(words) {
                return new RegExp("^((" + words.join(")|(") + "))\\b");
              }
            
              var wordOperators = wordRegexp(["and", "or", "not", "is"]);
              var commonKeywords = ["as", "assert", "break", "class", "continue",
                                    "def", "del", "elif", "else", "except", "finally",
                                    "for", "from", "global", "if", "import",
                                    "lambda", "pass", "raise", "return",
                                    "try", "while", "with", "yield", "in"];
              var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr",
                                    "classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod",
                                    "enumerate", "eval", "filter", "float", "format", "frozenset",
                                    "getattr", "globals", "hasattr", "hash", "help", "hex", "id",
                                    "input", "int", "isinstance", "issubclass", "iter", "len",
                                    "list", "locals", "map", "max", "memoryview", "min", "next",
                                    "object", "oct", "open", "ord", "pow", "property", "range",
                                    "repr", "reversed", "round", "set", "setattr", "slice",
                                    "sorted", "staticmethod", "str", "sum", "super", "tuple",
                                    "type", "vars", "zip", "__import__", "NotImplemented",
                                    "Ellipsis", "__debug__"];
              var py2 = {builtins: ["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
                                    "file", "intern", "long", "raw_input", "reduce", "reload",
                                    "unichr", "unicode", "xrange", "False", "True", "None"],
                         keywords: ["exec", "print"]};
              var py3 = {builtins: ["ascii", "bytes", "exec", "print"],
                         keywords: ["nonlocal", "False", "True", "None"]};
            
              CodeMirror.registerHelper("hintWords", "python", commonKeywords.concat(commonBuiltins));
            
              function top(state) {
                return state.scopes[state.scopes.length - 1];
              }
            
              CodeMirror.defineMode("python", function(conf, parserConf) {
                var ERRORCLASS = "error";
            
                var singleDelimiters = parserConf.singleDelimiters || new RegExp("^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]");
                var doubleOperators = parserConf.doubleOperators || new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
                var doubleDelimiters = parserConf.doubleDelimiters || new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
                var tripleDelimiters = parserConf.tripleDelimiters || new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
            
                if (parserConf.version && parseInt(parserConf.version, 10) == 3){
                    // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator
                    var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!@]");
                    var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*");
                } else {
                    var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
                    var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
                }
            
                var hangingIndent = parserConf.hangingIndent || conf.indentUnit;
            
                var myKeywords = commonKeywords, myBuiltins = commonBuiltins;
                if(parserConf.extra_keywords != undefined){
                  myKeywords = myKeywords.concat(parserConf.extra_keywords);
                }
                if(parserConf.extra_builtins != undefined){
                  myBuiltins = myBuiltins.concat(parserConf.extra_builtins);
                }
                if (parserConf.version && parseInt(parserConf.version, 10) == 3) {
                  myKeywords = myKeywords.concat(py3.keywords);
                  myBuiltins = myBuiltins.concat(py3.builtins);
                  var stringPrefixes = new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))", "i");
                } else {
                  myKeywords = myKeywords.concat(py2.keywords);
                  myBuiltins = myBuiltins.concat(py2.builtins);
                  var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
                }
                var keywords = wordRegexp(myKeywords);
                var builtins = wordRegexp(myBuiltins);
            
                // tokenizers
                function tokenBase(stream, state) {
                  // Handle scope changes
                  if (stream.sol() && top(state).type == "py") {
                    var scopeOffset = top(state).offset;
                    if (stream.eatSpace()) {
                      var lineOffset = stream.indentation();
                      if (lineOffset > scopeOffset)
                        pushScope(stream, state, "py");
                      else if (lineOffset < scopeOffset && dedent(stream, state))
                        state.errorToken = true;
                      return null;
                    } else {
                      var style = tokenBaseInner(stream, state);
                      if (scopeOffset > 0 && dedent(stream, state))
                        style += " " + ERRORCLASS;
                      return style;
                    }
                  }
                  return tokenBaseInner(stream, state);
                }
            
                function tokenBaseInner(stream, state) {
                  if (stream.eatSpace()) return null;
            
                  var ch = stream.peek();
            
                  // Handle Comments
                  if (ch == "#") {
                    stream.skipToEnd();
                    return "comment";
                  }
            
                  // Handle Number Literals
                  if (stream.match(/^[0-9\.]/, false)) {
                    var floatLiteral = false;
                    // Floats
                    if (stream.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)) { floatLiteral = true; }
                    if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; }
                    if (stream.match(/^\.\d+/)) { floatLiteral = true; }
                    if (floatLiteral) {
                      // Float literals may be "imaginary"
                      stream.eat(/J/i);
                      return "number";
                    }
                    // Integers
                    var intLiteral = false;
                    // Hex
                    if (stream.match(/^0x[0-9a-f]+/i)) intLiteral = true;
                    // Binary
                    if (stream.match(/^0b[01]+/i)) intLiteral = true;
                    // Octal
                    if (stream.match(/^0o[0-7]+/i)) intLiteral = true;
                    // Decimal
                    if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) {
                      // Decimal literals may be "imaginary"
                      stream.eat(/J/i);
                      // TODO - Can you have imaginary longs?
                      intLiteral = true;
                    }
                    // Zero by itself with no other piece of number.
                    if (stream.match(/^0(?![\dx])/i)) intLiteral = true;
                    if (intLiteral) {
                      // Integer literals may be "long"
                      stream.eat(/L/i);
                      return "number";
                    }
                  }
            
                  // Handle Strings
                  if (stream.match(stringPrefixes)) {
                    state.tokenize = tokenStringFactory(stream.current());
                    return state.tokenize(stream, state);
                  }
            
                  // Handle operators and Delimiters
                  if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters))
                    return null;
            
                  if (stream.match(doubleOperators) || stream.match(singleOperators))
                    return "operator";
            
                  if (stream.match(singleDelimiters))
                    return null;
            
                  if (stream.match(keywords) || stream.match(wordOperators))
                    return "keyword";
            
                  if (stream.match(builtins))
                    return "builtin";
            
                  if (stream.match(/^(self|cls)\b/))
                    return "variable-2";
            
                  if (stream.match(identifiers)) {
                    if (state.lastToken == "def" || state.lastToken == "class")
                      return "def";
                    return "variable";
                  }
            
                  // Handle non-detected items
                  stream.next();
                  return ERRORCLASS;
                }
            
                function tokenStringFactory(delimiter) {
                  while ("rub".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)
                    delimiter = delimiter.substr(1);
            
                  var singleline = delimiter.length == 1;
                  var OUTCLASS = "string";
            
                  function tokenString(stream, state) {
                    while (!stream.eol()) {
                      stream.eatWhile(/[^'"\\]/);
                      if (stream.eat("\\")) {
                        stream.next();
                        if (singleline && stream.eol())
                          return OUTCLASS;
                      } else if (stream.match(delimiter)) {
                        state.tokenize = tokenBase;
                        return OUTCLASS;
                      } else {
                        stream.eat(/['"]/);
                      }
                    }
                    if (singleline) {
                      if (parserConf.singleLineStringErrors)
                        return ERRORCLASS;
                      else
                        state.tokenize = tokenBase;
                    }
                    return OUTCLASS;
                  }
                  tokenString.isString = true;
                  return tokenString;
                }
            
                function pushScope(stream, state, type) {
                  var offset = 0, align = null;
                  if (type == "py") {
                    while (top(state).type != "py")
                      state.scopes.pop();
                  }
                  offset = top(state).offset + (type == "py" ? conf.indentUnit : hangingIndent);
                  if (type != "py" && !stream.match(/^(\s|#.*)*$/, false))
                    align = stream.column() + 1;
                  state.scopes.push({offset: offset, type: type, align: align});
                }
            
                function dedent(stream, state) {
                  var indented = stream.indentation();
                  while (top(state).offset > indented) {
                    if (top(state).type != "py") return true;
                    state.scopes.pop();
                  }
                  return top(state).offset != indented;
                }
            
                function tokenLexer(stream, state) {
                  var style = state.tokenize(stream, state);
                  var current = stream.current();
            
                  // Handle '.' connected identifiers
                  if (current == ".") {
                    style = stream.match(identifiers, false) ? null : ERRORCLASS;
                    if (style == null && state.lastStyle == "meta") {
                      // Apply 'meta' style to '.' connected identifiers when
                      // appropriate.
                      style = "meta";
                    }
                    return style;
                  }
            
                  // Handle decorators
                  if (current == "@"){
                    if(parserConf.version && parseInt(parserConf.version, 10) == 3){
                        return stream.match(identifiers, false) ? "meta" : "operator";
                    } else {
                        return stream.match(identifiers, false) ? "meta" : ERRORCLASS;
                    }
                  }
            
                  if ((style == "variable" || style == "builtin")
                      && state.lastStyle == "meta")
                    style = "meta";
            
                  // Handle scope changes.
                  if (current == "pass" || current == "return")
                    state.dedent += 1;
            
                  if (current == "lambda") state.lambda = true;
                  if (current == ":" && !state.lambda && top(state).type == "py")
                    pushScope(stream, state, "py");
            
                  var delimiter_index = current.length == 1 ? "[({".indexOf(current) : -1;
                  if (delimiter_index != -1)
                    pushScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
            
                  delimiter_index = "])}".indexOf(current);
                  if (delimiter_index != -1) {
                    if (top(state).type == current) state.scopes.pop();
                    else return ERRORCLASS;
                  }
                  if (state.dedent > 0 && stream.eol() && top(state).type == "py") {
                    if (state.scopes.length > 1) state.scopes.pop();
                    state.dedent -= 1;
                  }
            
                  return style;
                }
            
                var external = {
                  startState: function(basecolumn) {
                    return {
                      tokenize: tokenBase,
                      scopes: [{offset: basecolumn || 0, type: "py", align: null}],
                      lastStyle: null,
                      lastToken: null,
                      lambda: false,
                      dedent: 0
                    };
                  },
            
                  token: function(stream, state) {
                    var addErr = state.errorToken;
                    if (addErr) state.errorToken = false;
                    var style = tokenLexer(stream, state);
            
                    state.lastStyle = style;
            
                    var current = stream.current();
                    if (current && style)
                      state.lastToken = current;
            
                    if (stream.eol() && state.lambda)
                      state.lambda = false;
                    return addErr ? style + " " + ERRORCLASS : style;
                  },
            
                  indent: function(state, textAfter) {
                    if (state.tokenize != tokenBase)
                      return state.tokenize.isString ? CodeMirror.Pass : 0;
            
                    var scope = top(state);
                    var closing = textAfter && textAfter.charAt(0) == scope.type;
                    if (scope.align != null)
                      return scope.align - (closing ? 1 : 0);
                    else if (closing && state.scopes.length > 1)
                      return state.scopes[state.scopes.length - 2].offset;
                    else
                      return scope.offset;
                  },
            
                  closeBrackets: {triples: "'\""},
                  lineComment: "#",
                  fold: "indent"
                };
                return external;
              });
            
              CodeMirror.defineMIME("text/x-python", "python");
            
              var words = function(str) { return str.split(" "); };
            
              CodeMirror.defineMIME("text/x-cython", {
                name: "python",
                extra_keywords: words("by cdef cimport cpdef ctypedef enum except"+
                                      "extern gil include nogil property public"+
                                      "readonly struct union DEF IF ELIF ELSE")
              });
            
            });
            
        • q
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Q mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="q.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Q</a>
              </ul>
            </div>
            
            <article>
            <h2>Q mode</h2>
            
            
            <div><textarea id="code" name="code">
            / utilities to quickly load a csv file - for more exhaustive analysis of the csv contents see csvguess.q
            / 2009.09.20 - updated to match latest csvguess.q 
            
            / .csv.colhdrs[file] - return a list of colhdrs from file
            / info:.csv.info[file] - return a table of information about the file
            / columns are: 
            /	c - column name; ci - column index; t - load type; mw - max width; 
            /	dchar - distinct characters in values; rule - rule that caught the type
            /	maybe - needs checking, _could_ be say a date, but perhaps just a float?
            / .csv.info0[file;onlycols] - like .csv.info except that it only analyses <onlycols>
            / example:
            /	info:.csv.info0[file;(.csv.colhdrs file)like"*price"]
            /	info:.csv.infolike[file;"*price"]
            /	show delete from info where t=" "
            / .csv.data[file;info] - use the info from .csv.info to read the data
            / .csv.data10[file;info] - like .csv.data but only returns the first 10 rows
            / bulkload[file;info] - bulk loads file into table DATA (which must be already defined :: DATA:() )
            / .csv.read[file]/read10[file] - for when you don't care about checking/tweaking the <info> before reading 
            
            \d .csv
            DELIM:","
            ZAPHDRS:0b / lowercase and remove _ from colhdrs (junk characters are always removed)
            WIDTHHDR:25000 / number of characters read to get the header
            READLINES:222 / number of lines read and used to guess the types
            SYMMAXWIDTH:11 / character columns narrower than this are stored as symbols
            SYMMAXGR:10 / max symbol granularity% before we give up and keep as a * string
            FORCECHARWIDTH:30 / every field (of any type) with values this wide or more is forced to character "*"
            DISCARDEMPTY:0b / completely ignore empty columns if true else set them to "C"
            CHUNKSIZE:50000000 / used in fs2 (modified .Q.fs)
            
            k)nameltrim:{$[~@x;.z.s'x;~(*x)in aA:.Q.a,.Q.A;(+/&\~x in aA)_x;x]}
            k)fs2:{[f;s]((-7!s)>){[f;s;x]i:1+last@&0xa=r:1:(s;x;CHUNKSIZE);f@`\:i#r;x+i}[f;s]/0j}
            cleanhdrs:{{$[ZAPHDRS;lower x except"_";x]}x where x in DELIM,.Q.an}
            cancast:{nw:x$"";if[not x in"BXCS";nw:(min 0#;max 0#;::)@\:nw];$[not any nw in x$(11&count y)#y;$[11<count y;not any nw in x$y;1b];0b]}
            
            read:{[file]data[file;info[file]]}  
            read10:{[file]data10[file;info[file]]}  
            
            colhdrs:{[file]
            	`$nameltrim DELIM vs cleanhdrs first read0(file;0;1+first where 0xa=read1(file;0;WIDTHHDR))}
            data:{[file;info]
            	(exec c from info where not t=" ")xcol(exec t from info;enlist DELIM)0:file}
            data10:{[file;info]
            	data[;info](file;0;1+last 11#where 0xa=read1(file;0;15*WIDTHHDR))}
            info0:{[file;onlycols]
            	colhdrs:`$nameltrim DELIM vs cleanhdrs first head:read0(file;0;1+last where 0xa=read1(file;0;WIDTHHDR));
            	loadfmts:(count colhdrs)#"S";if[count onlycols;loadfmts[where not colhdrs in onlycols]:"C"];
            	breaks:where 0xa=read1(file;0;floor(10+READLINES)*WIDTHHDR%count head);
            	nas:count as:colhdrs xcol(loadfmts;enlist DELIM)0:(file;0;1+last((1+READLINES)&count breaks)#breaks);
            	info:([]c:key flip as;v:value flip as);as:();
            	reserved:key`.q;reserved,:.Q.res;reserved,:`i;
            	info:update res:c in reserved from info;
            	info:update ci:i,t:"?",ipa:0b,mdot:0,mw:0,rule:0,gr:0,ndv:0,maybe:0b,empty:0b,j10:0b,j12:0b from info;
            	info:update ci:`s#ci from info;
            	if[count onlycols;info:update t:" ",rule:10 from info where not c in onlycols];
            	info:update sdv:{string(distinct x)except`}peach v from info; 
            	info:update ndv:count each sdv from info;
            	info:update gr:floor 0.5+100*ndv%nas,mw:{max count each x}peach sdv from info where 0<ndv;
            	info:update t:"*",rule:20 from info where mw>.csv.FORCECHARWIDTH; / long values
            	info:update t:"C "[.csv.DISCARDEMPTY],rule:30,empty:1b from info where t="?",mw=0; / empty columns
            	info:update dchar:{asc distinct raze x}peach sdv from info where t="?";
            	info:update mdot:{max sum each"."=x}peach sdv from info where t="?",{"."in x}each dchar;
            	info:update t:"n",rule:40 from info where t="?",{any x in"0123456789"}each dchar; / vaguely numeric..
            	info:update t:"I",rule:50,ipa:1b from info where t="n",mw within 7 15,mdot=3,{all x in".0123456789"}each dchar,.csv.cancast["I"]peach sdv; / ip-address
            	info:update t:"J",rule:60 from info where t="n",mdot=0,{all x in"+-0123456789"}each dchar,.csv.cancast["J"]peach sdv;
            	info:update t:"I",rule:70 from info where t="J",mw<12,.csv.cancast["I"]peach sdv;
            	info:update t:"H",rule:80 from info where t="I",mw<7,.csv.cancast["H"]peach sdv;
            	info:update t:"F",rule:90 from info where t="n",mdot<2,mw>1,.csv.cancast["F"]peach sdv;
            	info:update t:"E",rule:100,maybe:1b from info where t="F",mw<9;
            	info:update t:"M",rule:110,maybe:1b from info where t in"nIHEF",mdot<2,mw within 4 7,.csv.cancast["M"]peach sdv; 
            	info:update t:"D",rule:120,maybe:1b from info where t in"nI",mdot in 0 2,mw within 6 11,.csv.cancast["D"]peach sdv; 
            	info:update t:"V",rule:130,maybe:1b from info where t="I",mw in 5 6,7<count each dchar,{all x like"*[0-9][0-5][0-9][0-5][0-9]"}peach sdv,.csv.cancast["V"]peach sdv; / 235959 12345        
            	info:update t:"U",rule:140,maybe:1b from info where t="H",mw in 3 4,7<count each dchar,{all x like"*[0-9][0-5][0-9]"}peach sdv,.csv.cancast["U"]peach sdv; /2359
            	info:update t:"U",rule:150,maybe:0b from info where t="n",mw in 4 5,mdot=0,{all x like"*[0-9]:[0-5][0-9]"}peach sdv,.csv.cancast["U"]peach sdv;
            	info:update t:"T",rule:160,maybe:0b from info where t="n",mw within 7 12,mdot<2,{all x like"*[0-9]:[0-5][0-9]:[0-5][0-9]*"}peach sdv,.csv.cancast["T"]peach sdv;
            	info:update t:"V",rule:170,maybe:0b from info where t="T",mw in 7 8,mdot=0,.csv.cancast["V"]peach sdv;
            	info:update t:"T",rule:180,maybe:1b from info where t in"EF",mw within 7 10,mdot=1,{all x like"*[0-9][0-5][0-9][0-5][0-9].*"}peach sdv,.csv.cancast["T"]peach sdv;
            	info:update t:"Z",rule:190,maybe:0b from info where t="n",mw within 11 24,mdot<4,.csv.cancast["Z"]peach sdv;
            	info:update t:"P",rule:200,maybe:1b from info where t="n",mw within 12 29,mdot<4,{all x like"[12]*"}peach sdv,.csv.cancast["P"]peach sdv;
            	info:update t:"N",rule:210,maybe:1b from info where t="n",mw within 3 28,mdot=1,.csv.cancast["N"]peach sdv;
            	info:update t:"?",rule:220,maybe:0b from info where t="n"; / reset remaining maybe numeric
            	info:update t:"C",rule:230,maybe:0b from info where t="?",mw=1; / char
            	info:update t:"B",rule:240,maybe:0b from info where t in"HC",mw=1,mdot=0,{$[all x in"01tTfFyYnN";(any"0fFnN"in x)and any"1tTyY"in x;0b]}each dchar; / boolean
            	info:update t:"B",rule:250,maybe:1b from info where t in"HC",mw=1,mdot=0,{all x in"01tTfFyYnN"}each dchar; / boolean
            	info:update t:"X",rule:260,maybe:0b from info where t="?",mw=2,{$[all x in"0123456789abcdefABCDEF";(any .Q.n in x)and any"abcdefABCDEF"in x;0b]}each dchar; /hex
            	info:update t:"S",rule:270,maybe:1b from info where t="?",mw<.csv.SYMMAXWIDTH,mw>1,gr<.csv.SYMMAXGR; / symbols (max width permitting)
            	info:update t:"*",rule:280,maybe:0b from info where t="?"; / the rest as strings
            	/ flag those S/* columns which could be encoded to integers (.Q.j10/x10/j12/x12) to avoid symbols
            	info:update j12:1b from info where t in"S*",mw<13,{all x in .Q.nA}each dchar;
            	info:update j10:1b from info where t in"S*",mw<11,{all x in .Q.b6}each dchar; 
            	select c,ci,t,maybe,empty,res,j10,j12,ipa,mw,mdot,rule,gr,ndv,dchar from info}
            info:info0[;()] / by default don't restrict columns
            infolike:{[file;pattern] info0[file;{x where x like y}[lower colhdrs[file];pattern]]} / .csv.infolike[file;"*time"]
            
            \d .
            / DATA:()
            bulkload:{[file;info]
            	if[not`DATA in system"v";'`DATA.not.defined];
            	if[count DATA;'`DATA.not.empty];
            	loadhdrs:exec c from info where not t=" ";loadfmts:exec t from info;
            	.csv.fs2[{[file;loadhdrs;loadfmts] `DATA insert $[count DATA;flip loadhdrs!(loadfmts;.csv.DELIM)0:file;loadhdrs xcol(loadfmts;enlist .csv.DELIM)0:file]}[file;loadhdrs;loadfmts]];
            	count DATA}
            @[.:;"\\l csvutil.custom.q";::]; / save your custom settings in csvutil.custom.q to override those set at the beginning of the file 
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true
                  });
                </script>
            
                <p><strong>MIME type defined:</strong> <code>text/x-q</code>.</p>
              </article>
            
          • q.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("q",function(config){
              var indentUnit=config.indentUnit,
                  curPunc,
                  keywords=buildRE(["abs","acos","aj","aj0","all","and","any","asc","asin","asof","atan","attr","avg","avgs","bin","by","ceiling","cols","cor","cos","count","cov","cross","csv","cut","delete","deltas","desc","dev","differ","distinct","div","do","each","ej","enlist","eval","except","exec","exit","exp","fby","fills","first","fkeys","flip","floor","from","get","getenv","group","gtime","hclose","hcount","hdel","hopen","hsym","iasc","idesc","if","ij","in","insert","inter","inv","key","keys","last","like","list","lj","load","log","lower","lsq","ltime","ltrim","mavg","max","maxs","mcount","md5","mdev","med","meta","min","mins","mmax","mmin","mmu","mod","msum","neg","next","not","null","or","over","parse","peach","pj","plist","prd","prds","prev","prior","rand","rank","ratios","raze","read0","read1","reciprocal","reverse","rload","rotate","rsave","rtrim","save","scan","select","set","setenv","show","signum","sin","sqrt","ss","ssr","string","sublist","sum","sums","sv","system","tables","tan","til","trim","txf","type","uj","ungroup","union","update","upper","upsert","value","var","view","views","vs","wavg","where","where","while","within","wj","wj1","wsum","xasc","xbar","xcol","xcols","xdesc","xexp","xgroup","xkey","xlog","xprev","xrank"]),
                  E=/[|/&^!+:\\\-*%$=~#;@><,?_\'\"\[\(\]\)\s{}]/;
              function buildRE(w){return new RegExp("^("+w.join("|")+")$");}
              function tokenBase(stream,state){
                var sol=stream.sol(),c=stream.next();
                curPunc=null;
                if(sol)
                  if(c=="/")
                    return(state.tokenize=tokenLineComment)(stream,state);
                  else if(c=="\\"){
                    if(stream.eol()||/\s/.test(stream.peek()))
                      return stream.skipToEnd(),/^\\\s*$/.test(stream.current())?(state.tokenize=tokenCommentToEOF)(stream, state):state.tokenize=tokenBase,"comment";
                    else
                      return state.tokenize=tokenBase,"builtin";
                  }
                if(/\s/.test(c))
                  return stream.peek()=="/"?(stream.skipToEnd(),"comment"):"whitespace";
                if(c=='"')
                  return(state.tokenize=tokenString)(stream,state);
                if(c=='`')
                  return stream.eatWhile(/[A-Z|a-z|\d|_|:|\/|\.]/),"symbol";
                if(("."==c&&/\d/.test(stream.peek()))||/\d/.test(c)){
                  var t=null;
                  stream.backUp(1);
                  if(stream.match(/^\d{4}\.\d{2}(m|\.\d{2}([D|T](\d{2}(:\d{2}(:\d{2}(\.\d{1,9})?)?)?)?)?)/)
                  || stream.match(/^\d+D(\d{2}(:\d{2}(:\d{2}(\.\d{1,9})?)?)?)/)
                  || stream.match(/^\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?/)
                  || stream.match(/^\d+[ptuv]{1}/))
                    t="temporal";
                  else if(stream.match(/^0[NwW]{1}/)
                  || stream.match(/^0x[\d|a-f|A-F]*/)
                  || stream.match(/^[0|1]+[b]{1}/)
                  || stream.match(/^\d+[chijn]{1}/)
                  || stream.match(/-?\d*(\.\d*)?(e[+\-]?\d+)?(e|f)?/))
                    t="number";
                  return(t&&(!(c=stream.peek())||E.test(c)))?t:(stream.next(),"error");
                }
                if(/[A-Z|a-z]|\./.test(c))
                  return stream.eatWhile(/[A-Z|a-z|\.|_|\d]/),keywords.test(stream.current())?"keyword":"variable";
                if(/[|/&^!+:\\\-*%$=~#;@><\.,?_\']/.test(c))
                  return null;
                if(/[{}\(\[\]\)]/.test(c))
                  return null;
                return"error";
              }
              function tokenLineComment(stream,state){
                return stream.skipToEnd(),/\/\s*$/.test(stream.current())?(state.tokenize=tokenBlockComment)(stream,state):(state.tokenize=tokenBase),"comment";
              }
              function tokenBlockComment(stream,state){
                var f=stream.sol()&&stream.peek()=="\\";
                stream.skipToEnd();
                if(f&&/^\\\s*$/.test(stream.current()))
                  state.tokenize=tokenBase;
                return"comment";
              }
              function tokenCommentToEOF(stream){return stream.skipToEnd(),"comment";}
              function tokenString(stream,state){
                var escaped=false,next,end=false;
                while((next=stream.next())){
                  if(next=="\""&&!escaped){end=true;break;}
                  escaped=!escaped&&next=="\\";
                }
                if(end)state.tokenize=tokenBase;
                return"string";
              }
              function pushContext(state,type,col){state.context={prev:state.context,indent:state.indent,col:col,type:type};}
              function popContext(state){state.indent=state.context.indent;state.context=state.context.prev;}
              return{
                startState:function(){
                  return{tokenize:tokenBase,
                         context:null,
                         indent:0,
                         col:0};
                },
                token:function(stream,state){
                  if(stream.sol()){
                    if(state.context&&state.context.align==null)
                      state.context.align=false;
                    state.indent=stream.indentation();
                  }
                  //if (stream.eatSpace()) return null;
                  var style=state.tokenize(stream,state);
                  if(style!="comment"&&state.context&&state.context.align==null&&state.context.type!="pattern"){
                    state.context.align=true;
                  }
                  if(curPunc=="(")pushContext(state,")",stream.column());
                  else if(curPunc=="[")pushContext(state,"]",stream.column());
                  else if(curPunc=="{")pushContext(state,"}",stream.column());
                  else if(/[\]\}\)]/.test(curPunc)){
                    while(state.context&&state.context.type=="pattern")popContext(state);
                    if(state.context&&curPunc==state.context.type)popContext(state);
                  }
                  else if(curPunc=="."&&state.context&&state.context.type=="pattern")popContext(state);
                  else if(/atom|string|variable/.test(style)&&state.context){
                    if(/[\}\]]/.test(state.context.type))
                      pushContext(state,"pattern",stream.column());
                    else if(state.context.type=="pattern"&&!state.context.align){
                      state.context.align=true;
                      state.context.col=stream.column();
                    }
                  }
                  return style;
                },
                indent:function(state,textAfter){
                  var firstChar=textAfter&&textAfter.charAt(0);
                  var context=state.context;
                  if(/[\]\}]/.test(firstChar))
                    while (context&&context.type=="pattern")context=context.prev;
                  var closing=context&&firstChar==context.type;
                  if(!context)
                    return 0;
                  else if(context.type=="pattern")
                    return context.col;
                  else if(context.align)
                    return context.col+(closing?0:1);
                  else
                    return context.indent+(closing?0:indentUnit);
                }
              };
            });
            CodeMirror.defineMIME("text/x-q","q");
            
            });
            
        • r
          • index.html
            <!doctype html>
            
            <title>CodeMirror: R mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="r.js"></script>
            <style>
                  .CodeMirror { border-top: 1px solid silver; border-bottom: 1px solid silver; }
                  .cm-s-default span.cm-semi { color: blue; font-weight: bold; }
                  .cm-s-default span.cm-dollar { color: orange; font-weight: bold; }
                  .cm-s-default span.cm-arrow { color: brown; }
                  .cm-s-default span.cm-arg-is { color: brown; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">R</a>
              </ul>
            </div>
            
            <article>
            <h2>R mode</h2>
            <form><textarea id="code" name="code">
            # Code from http://www.mayin.org/ajayshah/KB/R/
            
            # FIRST LEARN ABOUT LISTS --
            X = list(height=5.4, weight=54)
            print("Use default printing --")
            print(X)
            print("Accessing individual elements --")
            cat("Your height is ", X$height, " and your weight is ", X$weight, "\n")
            
            # FUNCTIONS --
            square <- function(x) {
              return(x*x)
            }
            cat("The square of 3 is ", square(3), "\n")
            
                             # default value of the arg is set to 5.
            cube <- function(x=5) {
              return(x*x*x);
            }
            cat("Calling cube with 2 : ", cube(2), "\n")    # will give 2^3
            cat("Calling cube        : ", cube(), "\n")     # will default to 5^3.
            
            # LEARN ABOUT FUNCTIONS THAT RETURN MULTIPLE OBJECTS --
            powers <- function(x) {
              parcel = list(x2=x*x, x3=x*x*x, x4=x*x*x*x);
              return(parcel);
            }
            
            X = powers(3);
            print("Showing powers of 3 --"); print(X);
            
            # WRITING THIS COMPACTLY (4 lines instead of 7)
            
            powerful <- function(x) {
              return(list(x2=x*x, x3=x*x*x, x4=x*x*x*x));
            }
            print("Showing powers of 3 --"); print(powerful(3));
            
            # In R, the last expression in a function is, by default, what is
            # returned. So you could equally just say:
            powerful <- function(x) {list(x2=x*x, x3=x*x*x, x4=x*x*x*x)}
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-rsrc</code>.</p>
            
                <p>Development of the CodeMirror R mode was kindly sponsored
                by <a href="https://twitter.com/ubalo">Ubalo</a>.</p>
            
              </article>
            
          • r.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("r", function(config) {
              function wordObj(str) {
                var words = str.split(" "), res = {};
                for (var i = 0; i < words.length; ++i) res[words[i]] = true;
                return res;
              }
              var atoms = wordObj("NULL NA Inf NaN NA_integer_ NA_real_ NA_complex_ NA_character_");
              var builtins = wordObj("list quote bquote eval return call parse deparse");
              var keywords = wordObj("if else repeat while function for in next break");
              var blockkeywords = wordObj("if else repeat while function for");
              var opChars = /[+\-*\/^<>=!&|~$:]/;
              var curPunc;
            
              function tokenBase(stream, state) {
                curPunc = null;
                var ch = stream.next();
                if (ch == "#") {
                  stream.skipToEnd();
                  return "comment";
                } else if (ch == "0" && stream.eat("x")) {
                  stream.eatWhile(/[\da-f]/i);
                  return "number";
                } else if (ch == "." && stream.eat(/\d/)) {
                  stream.match(/\d*(?:e[+\-]?\d+)?/);
                  return "number";
                } else if (/\d/.test(ch)) {
                  stream.match(/\d*(?:\.\d+)?(?:e[+\-]\d+)?L?/);
                  return "number";
                } else if (ch == "'" || ch == '"') {
                  state.tokenize = tokenString(ch);
                  return "string";
                } else if (ch == "." && stream.match(/.[.\d]+/)) {
                  return "keyword";
                } else if (/[\w\.]/.test(ch) && ch != "_") {
                  stream.eatWhile(/[\w\.]/);
                  var word = stream.current();
                  if (atoms.propertyIsEnumerable(word)) return "atom";
                  if (keywords.propertyIsEnumerable(word)) {
                    // Block keywords start new blocks, except 'else if', which only starts
                    // one new block for the 'if', no block for the 'else'.
                    if (blockkeywords.propertyIsEnumerable(word) &&
                        !stream.match(/\s*if(\s+|$)/, false))
                      curPunc = "block";
                    return "keyword";
                  }
                  if (builtins.propertyIsEnumerable(word)) return "builtin";
                  return "variable";
                } else if (ch == "%") {
                  if (stream.skipTo("%")) stream.next();
                  return "variable-2";
                } else if (ch == "<" && stream.eat("-")) {
                  return "arrow";
                } else if (ch == "=" && state.ctx.argList) {
                  return "arg-is";
                } else if (opChars.test(ch)) {
                  if (ch == "$") return "dollar";
                  stream.eatWhile(opChars);
                  return "operator";
                } else if (/[\(\){}\[\];]/.test(ch)) {
                  curPunc = ch;
                  if (ch == ";") return "semi";
                  return null;
                } else {
                  return null;
                }
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  if (stream.eat("\\")) {
                    var ch = stream.next();
                    if (ch == "x") stream.match(/^[a-f0-9]{2}/i);
                    else if ((ch == "u" || ch == "U") && stream.eat("{") && stream.skipTo("}")) stream.next();
                    else if (ch == "u") stream.match(/^[a-f0-9]{4}/i);
                    else if (ch == "U") stream.match(/^[a-f0-9]{8}/i);
                    else if (/[0-7]/.test(ch)) stream.match(/^[0-7]{1,2}/);
                    return "string-2";
                  } else {
                    var next;
                    while ((next = stream.next()) != null) {
                      if (next == quote) { state.tokenize = tokenBase; break; }
                      if (next == "\\") { stream.backUp(1); break; }
                    }
                    return "string";
                  }
                };
              }
            
              function push(state, type, stream) {
                state.ctx = {type: type,
                             indent: state.indent,
                             align: null,
                             column: stream.column(),
                             prev: state.ctx};
              }
              function pop(state) {
                state.indent = state.ctx.indent;
                state.ctx = state.ctx.prev;
              }
            
              return {
                startState: function() {
                  return {tokenize: tokenBase,
                          ctx: {type: "top",
                                indent: -config.indentUnit,
                                align: false},
                          indent: 0,
                          afterIdent: false};
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (state.ctx.align == null) state.ctx.align = false;
                    state.indent = stream.indentation();
                  }
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
                  if (style != "comment" && state.ctx.align == null) state.ctx.align = true;
            
                  var ctype = state.ctx.type;
                  if ((curPunc == ";" || curPunc == "{" || curPunc == "}") && ctype == "block") pop(state);
                  if (curPunc == "{") push(state, "}", stream);
                  else if (curPunc == "(") {
                    push(state, ")", stream);
                    if (state.afterIdent) state.ctx.argList = true;
                  }
                  else if (curPunc == "[") push(state, "]", stream);
                  else if (curPunc == "block") push(state, "block", stream);
                  else if (curPunc == ctype) pop(state);
                  state.afterIdent = style == "variable" || style == "keyword";
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0), ctx = state.ctx,
                      closing = firstChar == ctx.type;
                  if (ctx.type == "block") return ctx.indent + (firstChar == "{" ? 0 : config.indentUnit);
                  else if (ctx.align) return ctx.column + (closing ? 0 : 1);
                  else return ctx.indent + (closing ? 0 : config.indentUnit);
                },
            
                lineComment: "#"
              };
            });
            
            CodeMirror.defineMIME("text/x-rsrc", "r");
            
            });
            
        • rpm
          • changes
            • index.html
              <!doctype html>
              
              <title>CodeMirror: RPM changes mode</title>
              <meta charset="utf-8"/>
              <link rel=stylesheet href="../../doc/docs.css">
              
                  <link rel="stylesheet" href="../../../lib/codemirror.css">
                  <script src="../../../lib/codemirror.js"></script>
                  <script src="changes.js"></script>
                  <link rel="stylesheet" href="../../../doc/docs.css">
                  <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
              
              <div id=nav>
                <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../../doc/logo.png"></a>
              
                <ul>
                  <li><a href="../../../index.html">Home</a>
                  <li><a href="../../../doc/manual.html">Manual</a>
                  <li><a href="https://github.com/codemirror/codemirror">Code</a>
                </ul>
                <ul>
                  <li><a href="../../index.html">Language modes</a>
                  <li><a class=active href="#">RPM changes</a>
                </ul>
              </div>
              
              <article>
              <h2>RPM changes mode</h2>
              
                  <div><textarea id="code" name="code">
              -------------------------------------------------------------------
              Tue Oct 18 13:58:40 UTC 2011 - misterx@example.com
              
              - Update to r60.3
              - Fixes bug in the reflect package
                * disallow Interface method on Value obtained via unexported name
              
              -------------------------------------------------------------------
              Thu Oct  6 08:14:24 UTC 2011 - misterx@example.com
              
              - Update to r60.2
              - Fixes memory leak in certain map types
              
              -------------------------------------------------------------------
              Wed Oct  5 14:34:10 UTC 2011 - misterx@example.com
              
              - Tweaks for gdb debugging
              - go.spec changes:
                - move %go_arch definition to %prep section
                - pass correct location of go specific gdb pretty printer and
                  functions to cpp as HOST_EXTRA_CFLAGS macro
                - install go gdb functions & printer
              - gdb-printer.patch
                - patch linker (src/cmd/ld/dwarf.c) to emit correct location of go
                  gdb functions and pretty printer
              </textarea></div>
                  <script>
                    var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                      mode: {name: "changes"},
                      lineNumbers: true,
                      indentUnit: 4
                    });
                  </script>
              
                  <p><strong>MIME types defined:</strong> <code>text/x-rpm-changes</code>.</p>
              </article>
              
          • index.html
            <!doctype html>
            
            <title>CodeMirror: RPM changes mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
                <link rel="stylesheet" href="../../lib/codemirror.css">
                <script src="../../lib/codemirror.js"></script>
                <script src="rpm.js"></script>
                <link rel="stylesheet" href="../../doc/docs.css">
                <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">RPM</a>
              </ul>
            </div>
            
            <article>
            <h2>RPM changes mode</h2>
            
                <div><textarea id="code" name="code">
            -------------------------------------------------------------------
            Tue Oct 18 13:58:40 UTC 2011 - misterx@example.com
            
            - Update to r60.3
            - Fixes bug in the reflect package
              * disallow Interface method on Value obtained via unexported name
            
            -------------------------------------------------------------------
            Thu Oct  6 08:14:24 UTC 2011 - misterx@example.com
            
            - Update to r60.2
            - Fixes memory leak in certain map types
            
            -------------------------------------------------------------------
            Wed Oct  5 14:34:10 UTC 2011 - misterx@example.com
            
            - Tweaks for gdb debugging
            - go.spec changes:
              - move %go_arch definition to %prep section
              - pass correct location of go specific gdb pretty printer and
                functions to cpp as HOST_EXTRA_CFLAGS macro
              - install go gdb functions & printer
            - gdb-printer.patch
              - patch linker (src/cmd/ld/dwarf.c) to emit correct location of go
                gdb functions and pretty printer
            </textarea></div>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "rpm-changes"},
                    lineNumbers: true,
                    indentUnit: 4
                  });
                </script>
            
            <h2>RPM spec mode</h2>
                
                <div><textarea id="code2" name="code2">
            #
            # spec file for package minidlna
            #
            # Copyright (c) 2011, Sascha Peilicke <saschpe@gmx.de>
            #
            # All modifications and additions to the file contributed by third parties
            # remain the property of their copyright owners, unless otherwise agreed
            # upon. The license for this file, and modifications and additions to the
            # file, is the same license as for the pristine package itself (unless the
            # license for the pristine package is not an Open Source License, in which
            # case the license is the MIT License). An "Open Source License" is a
            # license that conforms to the Open Source Definition (Version 1.9)
            # published by the Open Source Initiative.
            
            
            Name:           libupnp6
            Version:        1.6.13
            Release:        0
            Summary:        Portable Universal Plug and Play (UPnP) SDK
            Group:          System/Libraries
            License:        BSD-3-Clause
            Url:            http://sourceforge.net/projects/pupnp/
            Source0:        http://downloads.sourceforge.net/pupnp/libupnp-%{version}.tar.bz2
            BuildRoot:      %{_tmppath}/%{name}-%{version}-build
            
            %description
            The portable Universal Plug and Play (UPnP) SDK provides support for building
            UPnP-compliant control points, devices, and bridges on several operating
            systems.
            
            %package -n libupnp-devel
            Summary:        Portable Universal Plug and Play (UPnP) SDK
            Group:          Development/Libraries/C and C++
            Provides:       pkgconfig(libupnp)
            Requires:       %{name} = %{version}
            
            %description -n libupnp-devel
            The portable Universal Plug and Play (UPnP) SDK provides support for building
            UPnP-compliant control points, devices, and bridges on several operating
            systems.
            
            %prep
            %setup -n libupnp-%{version}
            
            %build
            %configure --disable-static
            make %{?_smp_mflags}
            
            %install
            %makeinstall
            find %{buildroot} -type f -name '*.la' -exec rm -f {} ';'
            
            %post -p /sbin/ldconfig
            
            %postun -p /sbin/ldconfig
            
            %files
            %defattr(-,root,root,-)
            %doc ChangeLog NEWS README TODO
            %{_libdir}/libixml.so.*
            %{_libdir}/libthreadutil.so.*
            %{_libdir}/libupnp.so.*
            
            %files -n libupnp-devel
            %defattr(-,root,root,-)
            %{_libdir}/pkgconfig/libupnp.pc
            %{_libdir}/libixml.so
            %{_libdir}/libthreadutil.so
            %{_libdir}/libupnp.so
            %{_includedir}/upnp/
            
            %changelog</textarea></div>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code2"), {
                    mode: {name: "rpm-spec"},
                    lineNumbers: true,
                    indentUnit: 4
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-rpm-spec</code>, <code>text/x-rpm-changes</code>.</p>
            </article>
            
          • rpm.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("rpm-changes", function() {
              var headerSeperator = /^-+$/;
              var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)  ?\d{1,2} \d{2}:\d{2}(:\d{2})? [A-Z]{3,4} \d{4} - /;
              var simpleEmail = /^[\w+.-]+@[\w.-]+/;
            
              return {
                token: function(stream) {
                  if (stream.sol()) {
                    if (stream.match(headerSeperator)) { return 'tag'; }
                    if (stream.match(headerLine)) { return 'tag'; }
                  }
                  if (stream.match(simpleEmail)) { return 'string'; }
                  stream.next();
                  return null;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-rpm-changes", "rpm-changes");
            
            // Quick and dirty spec file highlighting
            
            CodeMirror.defineMode("rpm-spec", function() {
              var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;
            
              var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\(\w+\))?|Obsoletes|Conflicts|Recommends|Source\d*|Patch\d*|ExclusiveArch|NoSource|Supplements):/;
              var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preinstall|preun|postinstall|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/;
              var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros
              var control_flow_simple = /^%(else|endif)/; // rpm control flow macros
              var operators = /^(\!|\?|\<\=|\<|\>\=|\>|\=\=|\&\&|\|\|)/; // operators in control flow macros
            
              return {
                startState: function () {
                    return {
                      controlFlow: false,
                      macroParameters: false,
                      section: false
                    };
                },
                token: function (stream, state) {
                  var ch = stream.peek();
                  if (ch == "#") { stream.skipToEnd(); return "comment"; }
            
                  if (stream.sol()) {
                    if (stream.match(preamble)) { return "preamble"; }
                    if (stream.match(section)) { return "section"; }
                  }
            
                  if (stream.match(/^\$\w+/)) { return "def"; } // Variables like '$RPM_BUILD_ROOT'
                  if (stream.match(/^\$\{\w+\}/)) { return "def"; } // Variables like '${RPM_BUILD_ROOT}'
            
                  if (stream.match(control_flow_simple)) { return "keyword"; }
                  if (stream.match(control_flow_complex)) {
                    state.controlFlow = true;
                    return "keyword";
                  }
                  if (state.controlFlow) {
                    if (stream.match(operators)) { return "operator"; }
                    if (stream.match(/^(\d+)/)) { return "number"; }
                    if (stream.eol()) { state.controlFlow = false; }
                  }
            
                  if (stream.match(arch)) { return "number"; }
            
                  // Macros like '%make_install' or '%attr(0775,root,root)'
                  if (stream.match(/^%[\w]+/)) {
                    if (stream.match(/^\(/)) { state.macroParameters = true; }
                    return "macro";
                  }
                  if (state.macroParameters) {
                    if (stream.match(/^\d+/)) { return "number";}
                    if (stream.match(/^\)/)) {
                      state.macroParameters = false;
                      return "macro";
                    }
                  }
                  if (stream.match(/^%\{\??[\w \-]+\}/)) { return "macro"; } // Macros like '%{defined fedora}'
            
                  //TODO: Include bash script sub-parser (CodeMirror supports that)
                  stream.next();
                  return null;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-rpm-spec", "rpm-spec");
            
            });
            
        • rst
          • index.html
            <!doctype html>
            
            <title>CodeMirror: reStructuredText mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/mode/overlay.js"></script>
            <script src="rst.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">reStructuredText</a>
              </ul>
            </div>
            
            <article>
            <h2>reStructuredText mode</h2>
            <form><textarea id="code" name="code">
            .. This is an excerpt from Sphinx documentation: http://sphinx.pocoo.org/_sources/rest.txt
            
            .. highlightlang:: rest
            
            .. _rst-primer:
            
            reStructuredText Primer
            =======================
            
            This section is a brief introduction to reStructuredText (reST) concepts and
            syntax, intended to provide authors with enough information to author documents
            productively.  Since reST was designed to be a simple, unobtrusive markup
            language, this will not take too long.
            
            .. seealso::
            
               The authoritative `reStructuredText User Documentation
               &lt;http://docutils.sourceforge.net/rst.html&gt;`_.  The "ref" links in this
               document link to the description of the individual constructs in the reST
               reference.
            
            
            Paragraphs
            ----------
            
            The paragraph (:duref:`ref &lt;paragraphs&gt;`) is the most basic block in a reST
            document.  Paragraphs are simply chunks of text separated by one or more blank
            lines.  As in Python, indentation is significant in reST, so all lines of the
            same paragraph must be left-aligned to the same level of indentation.
            
            
            .. _inlinemarkup:
            
            Inline markup
            -------------
            
            The standard reST inline markup is quite simple: use
            
            * one asterisk: ``*text*`` for emphasis (italics),
            * two asterisks: ``**text**`` for strong emphasis (boldface), and
            * backquotes: ````text```` for code samples.
            
            If asterisks or backquotes appear in running text and could be confused with
            inline markup delimiters, they have to be escaped with a backslash.
            
            Be aware of some restrictions of this markup:
            
            * it may not be nested,
            * content may not start or end with whitespace: ``* text*`` is wrong,
            * it must be separated from surrounding text by non-word characters.  Use a
              backslash escaped space to work around that: ``thisis\ *one*\ word``.
            
            These restrictions may be lifted in future versions of the docutils.
            
            reST also allows for custom "interpreted text roles"', which signify that the
            enclosed text should be interpreted in a specific way.  Sphinx uses this to
            provide semantic markup and cross-referencing of identifiers, as described in
            the appropriate section.  The general syntax is ``:rolename:`content```.
            
            Standard reST provides the following roles:
            
            * :durole:`emphasis` -- alternate spelling for ``*emphasis*``
            * :durole:`strong` -- alternate spelling for ``**strong**``
            * :durole:`literal` -- alternate spelling for ````literal````
            * :durole:`subscript` -- subscript text
            * :durole:`superscript` -- superscript text
            * :durole:`title-reference` -- for titles of books, periodicals, and other
              materials
            
            See :ref:`inline-markup` for roles added by Sphinx.
            
            
            Lists and Quote-like blocks
            ---------------------------
            
            List markup (:duref:`ref &lt;bullet-lists&gt;`) is natural: just place an asterisk at
            the start of a paragraph and indent properly.  The same goes for numbered lists;
            they can also be autonumbered using a ``#`` sign::
            
               * This is a bulleted list.
               * It has two items, the second
                 item uses two lines.
            
               1. This is a numbered list.
               2. It has two items too.
            
               #. This is a numbered list.
               #. It has two items too.
            
            
            Nested lists are possible, but be aware that they must be separated from the
            parent list items by blank lines::
            
               * this is
               * a list
            
                 * with a nested list
                 * and some subitems
            
               * and here the parent list continues
            
            Definition lists (:duref:`ref &lt;definition-lists&gt;`) are created as follows::
            
               term (up to a line of text)
                  Definition of the term, which must be indented
            
                  and can even consist of multiple paragraphs
            
               next term
                  Description.
            
            Note that the term cannot have more than one line of text.
            
            Quoted paragraphs (:duref:`ref &lt;block-quotes&gt;`) are created by just indenting
            them more than the surrounding paragraphs.
            
            Line blocks (:duref:`ref &lt;line-blocks&gt;`) are a way of preserving line breaks::
            
               | These lines are
               | broken exactly like in
               | the source file.
            
            There are also several more special blocks available:
            
            * field lists (:duref:`ref &lt;field-lists&gt;`)
            * option lists (:duref:`ref &lt;option-lists&gt;`)
            * quoted literal blocks (:duref:`ref &lt;quoted-literal-blocks&gt;`)
            * doctest blocks (:duref:`ref &lt;doctest-blocks&gt;`)
            
            
            Source Code
            -----------
            
            Literal code blocks (:duref:`ref &lt;literal-blocks&gt;`) are introduced by ending a
            paragraph with the special marker ``::``.  The literal block must be indented
            (and, like all paragraphs, separated from the surrounding ones by blank lines)::
            
               This is a normal text paragraph. The next paragraph is a code sample::
            
                  It is not processed in any way, except
                  that the indentation is removed.
            
                  It can span multiple lines.
            
               This is a normal text paragraph again.
            
            The handling of the ``::`` marker is smart:
            
            * If it occurs as a paragraph of its own, that paragraph is completely left
              out of the document.
            * If it is preceded by whitespace, the marker is removed.
            * If it is preceded by non-whitespace, the marker is replaced by a single
              colon.
            
            That way, the second sentence in the above example's first paragraph would be
            rendered as "The next paragraph is a code sample:".
            
            
            .. _rst-tables:
            
            Tables
            ------
            
            Two forms of tables are supported.  For *grid tables* (:duref:`ref
            &lt;grid-tables&gt;`), you have to "paint" the cell grid yourself.  They look like
            this::
            
               +------------------------+------------+----------+----------+
               | Header row, column 1   | Header 2   | Header 3 | Header 4 |
               | (header rows optional) |            |          |          |
               +========================+============+==========+==========+
               | body row 1, column 1   | column 2   | column 3 | column 4 |
               +------------------------+------------+----------+----------+
               | body row 2             | ...        | ...      |          |
               +------------------------+------------+----------+----------+
            
            *Simple tables* (:duref:`ref &lt;simple-tables&gt;`) are easier to write, but
            limited: they must contain more than one row, and the first column cannot
            contain multiple lines.  They look like this::
            
               =====  =====  =======
               A      B      A and B
               =====  =====  =======
               False  False  False
               True   False  False
               False  True   False
               True   True   True
               =====  =====  =======
            
            
            Hyperlinks
            ----------
            
            External links
            ^^^^^^^^^^^^^^
            
            Use ```Link text &lt;http://example.com/&gt;`_`` for inline web links.  If the link
            text should be the web address, you don't need special markup at all, the parser
            finds links and mail addresses in ordinary text.
            
            You can also separate the link and the target definition (:duref:`ref
            &lt;hyperlink-targets&gt;`), like this::
            
               This is a paragraph that contains `a link`_.
            
               .. _a link: http://example.com/
            
            
            Internal links
            ^^^^^^^^^^^^^^
            
            Internal linking is done via a special reST role provided by Sphinx, see the
            section on specific markup, :ref:`ref-role`.
            
            
            Sections
            --------
            
            Section headers (:duref:`ref &lt;sections&gt;`) are created by underlining (and
            optionally overlining) the section title with a punctuation character, at least
            as long as the text::
            
               =================
               This is a heading
               =================
            
            Normally, there are no heading levels assigned to certain characters as the
            structure is determined from the succession of headings.  However, for the
            Python documentation, this convention is used which you may follow:
            
            * ``#`` with overline, for parts
            * ``*`` with overline, for chapters
            * ``=``, for sections
            * ``-``, for subsections
            * ``^``, for subsubsections
            * ``"``, for paragraphs
            
            Of course, you are free to use your own marker characters (see the reST
            documentation), and use a deeper nesting level, but keep in mind that most
            target formats (HTML, LaTeX) have a limited supported nesting depth.
            
            
            Explicit Markup
            ---------------
            
            "Explicit markup" (:duref:`ref &lt;explicit-markup-blocks&gt;`) is used in reST for
            most constructs that need special handling, such as footnotes,
            specially-highlighted paragraphs, comments, and generic directives.
            
            An explicit markup block begins with a line starting with ``..`` followed by
            whitespace and is terminated by the next paragraph at the same level of
            indentation.  (There needs to be a blank line between explicit markup and normal
            paragraphs.  This may all sound a bit complicated, but it is intuitive enough
            when you write it.)
            
            
            .. _directives:
            
            Directives
            ----------
            
            A directive (:duref:`ref &lt;directives&gt;`) is a generic block of explicit markup.
            Besides roles, it is one of the extension mechanisms of reST, and Sphinx makes
            heavy use of it.
            
            Docutils supports the following directives:
            
            * Admonitions: :dudir:`attention`, :dudir:`caution`, :dudir:`danger`,
              :dudir:`error`, :dudir:`hint`, :dudir:`important`, :dudir:`note`,
              :dudir:`tip`, :dudir:`warning` and the generic :dudir:`admonition`.
              (Most themes style only "note" and "warning" specially.)
            
            * Images:
            
              - :dudir:`image` (see also Images_ below)
              - :dudir:`figure` (an image with caption and optional legend)
            
            * Additional body elements:
            
              - :dudir:`contents` (a local, i.e. for the current file only, table of
                contents)
              - :dudir:`container` (a container with a custom class, useful to generate an
                outer ``&lt;div&gt;`` in HTML)
              - :dudir:`rubric` (a heading without relation to the document sectioning)
              - :dudir:`topic`, :dudir:`sidebar` (special highlighted body elements)
              - :dudir:`parsed-literal` (literal block that supports inline markup)
              - :dudir:`epigraph` (a block quote with optional attribution line)
              - :dudir:`highlights`, :dudir:`pull-quote` (block quotes with their own
                class attribute)
              - :dudir:`compound` (a compound paragraph)
            
            * Special tables:
            
              - :dudir:`table` (a table with title)
              - :dudir:`csv-table` (a table generated from comma-separated values)
              - :dudir:`list-table` (a table generated from a list of lists)
            
            * Special directives:
            
              - :dudir:`raw` (include raw target-format markup)
              - :dudir:`include` (include reStructuredText from another file)
                -- in Sphinx, when given an absolute include file path, this directive takes
                it as relative to the source directory
              - :dudir:`class` (assign a class attribute to the next element) [1]_
            
            * HTML specifics:
            
              - :dudir:`meta` (generation of HTML ``&lt;meta&gt;`` tags)
              - :dudir:`title` (override document title)
            
            * Influencing markup:
            
              - :dudir:`default-role` (set a new default role)
              - :dudir:`role` (create a new role)
            
              Since these are only per-file, better use Sphinx' facilities for setting the
              :confval:`default_role`.
            
            Do *not* use the directives :dudir:`sectnum`, :dudir:`header` and
            :dudir:`footer`.
            
            Directives added by Sphinx are described in :ref:`sphinxmarkup`.
            
            Basically, a directive consists of a name, arguments, options and content. (Keep
            this terminology in mind, it is used in the next chapter describing custom
            directives.)  Looking at this example, ::
            
               .. function:: foo(x)
                             foo(y, z)
                  :module: some.module.name
            
                  Return a line of text input from the user.
            
            ``function`` is the directive name.  It is given two arguments here, the
            remainder of the first line and the second line, as well as one option
            ``module`` (as you can see, options are given in the lines immediately following
            the arguments and indicated by the colons).  Options must be indented to the
            same level as the directive content.
            
            The directive content follows after a blank line and is indented relative to the
            directive start.
            
            
            Images
            ------
            
            reST supports an image directive (:dudir:`ref &lt;image&gt;`), used like so::
            
               .. image:: gnu.png
                  (options)
            
            When used within Sphinx, the file name given (here ``gnu.png``) must either be
            relative to the source file, or absolute which means that they are relative to
            the top source directory.  For example, the file ``sketch/spam.rst`` could refer
            to the image ``images/spam.png`` as ``../images/spam.png`` or
            ``/images/spam.png``.
            
            Sphinx will automatically copy image files over to a subdirectory of the output
            directory on building (e.g. the ``_static`` directory for HTML output.)
            
            Interpretation of image size options (``width`` and ``height``) is as follows:
            if the size has no unit or the unit is pixels, the given size will only be
            respected for output channels that support pixels (i.e. not in LaTeX output).
            Other units (like ``pt`` for points) will be used for HTML and LaTeX output.
            
            Sphinx extends the standard docutils behavior by allowing an asterisk for the
            extension::
            
               .. image:: gnu.*
            
            Sphinx then searches for all images matching the provided pattern and determines
            their type.  Each builder then chooses the best image out of these candidates.
            For instance, if the file name ``gnu.*`` was given and two files :file:`gnu.pdf`
            and :file:`gnu.png` existed in the source tree, the LaTeX builder would choose
            the former, while the HTML builder would prefer the latter.
            
            .. versionchanged:: 0.4
               Added the support for file names ending in an asterisk.
            
            .. versionchanged:: 0.6
               Image paths can now be absolute.
            
            
            Footnotes
            ---------
            
            For footnotes (:duref:`ref &lt;footnotes&gt;`), use ``[#name]_`` to mark the footnote
            location, and add the footnote body at the bottom of the document after a
            "Footnotes" rubric heading, like so::
            
               Lorem ipsum [#f1]_ dolor sit amet ... [#f2]_
            
               .. rubric:: Footnotes
            
               .. [#f1] Text of the first footnote.
               .. [#f2] Text of the second footnote.
            
            You can also explicitly number the footnotes (``[1]_``) or use auto-numbered
            footnotes without names (``[#]_``).
            
            
            Citations
            ---------
            
            Standard reST citations (:duref:`ref &lt;citations&gt;`) are supported, with the
            additional feature that they are "global", i.e. all citations can be referenced
            from all files.  Use them like so::
            
               Lorem ipsum [Ref]_ dolor sit amet.
            
               .. [Ref] Book or article reference, URL or whatever.
            
            Citation usage is similar to footnote usage, but with a label that is not
            numeric or begins with ``#``.
            
            
            Substitutions
            -------------
            
            reST supports "substitutions" (:duref:`ref &lt;substitution-definitions&gt;`), which
            are pieces of text and/or markup referred to in the text by ``|name|``.  They
            are defined like footnotes with explicit markup blocks, like this::
            
               .. |name| replace:: replacement *text*
            
            or this::
            
               .. |caution| image:: warning.png
                            :alt: Warning!
            
            See the :duref:`reST reference for substitutions &lt;substitution-definitions&gt;`
            for details.
            
            If you want to use some substitutions for all documents, put them into
            :confval:`rst_prolog` or put them into a separate file and include it into all
            documents you want to use them in, using the :rst:dir:`include` directive.  (Be
            sure to give the include file a file name extension differing from that of other
            source files, to avoid Sphinx finding it as a standalone document.)
            
            Sphinx defines some default substitutions, see :ref:`default-substitutions`.
            
            
            Comments
            --------
            
            Every explicit markup block which isn't a valid markup construct (like the
            footnotes above) is regarded as a comment (:duref:`ref &lt;comments&gt;`).  For
            example::
            
               .. This is a comment.
            
            You can indent text after a comment start to form multiline comments::
            
               ..
                  This whole indented block
                  is a comment.
            
                  Still in the comment.
            
            
            Source encoding
            ---------------
            
            Since the easiest way to include special characters like em dashes or copyright
            signs in reST is to directly write them as Unicode characters, one has to
            specify an encoding.  Sphinx assumes source files to be encoded in UTF-8 by
            default; you can change this with the :confval:`source_encoding` config value.
            
            
            Gotchas
            -------
            
            There are some problems one commonly runs into while authoring reST documents:
            
            * **Separation of inline markup:** As said above, inline markup spans must be
              separated from the surrounding text by non-word characters, you have to use a
              backslash-escaped space to get around that.  See `the reference
              &lt;http://docutils.sf.net/docs/ref/rst/restructuredtext.html#inline-markup&gt;`_
              for the details.
            
            * **No nested inline markup:** Something like ``*see :func:`foo`*`` is not
              possible.
            
            
            .. rubric:: Footnotes
            
            .. [1] When the default domain contains a :rst:dir:`class` directive, this directive
                   will be shadowed.  Therefore, Sphinx re-exports it as :rst:dir:`rst-class`.
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                  });
                </script>
                <p>
                    The <code>python</code> mode will be used for highlighting blocks
                    containing Python/IPython terminal sessions: blocks starting with
                    <code>&gt;&gt;&gt;</code> (for Python) or <code>In [num]:</code> (for
                    IPython).
            
                    Further, the <code>stex</code> mode will be used for highlighting
                    blocks containing LaTex code.
                </p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-rst</code>.</p>
              </article>
            
          • rst.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../python/python"), require("../stex/stex"), require("../../addon/mode/overlay"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../python/python", "../stex/stex", "../../addon/mode/overlay"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('rst', function (config, options) {
            
              var rx_strong = /^\*\*[^\*\s](?:[^\*]*[^\*\s])?\*\*/;
              var rx_emphasis = /^\*[^\*\s](?:[^\*]*[^\*\s])?\*/;
              var rx_literal = /^``[^`\s](?:[^`]*[^`\s])``/;
            
              var rx_number = /^(?:[\d]+(?:[\.,]\d+)*)/;
              var rx_positive = /^(?:\s\+[\d]+(?:[\.,]\d+)*)/;
              var rx_negative = /^(?:\s\-[\d]+(?:[\.,]\d+)*)/;
            
              var rx_uri_protocol = "[Hh][Tt][Tt][Pp][Ss]?://";
              var rx_uri_domain = "(?:[\\d\\w.-]+)\\.(?:\\w{2,6})";
              var rx_uri_path = "(?:/[\\d\\w\\#\\%\\&\\-\\.\\,\\/\\:\\=\\?\\~]+)*";
              var rx_uri = new RegExp("^" + rx_uri_protocol + rx_uri_domain + rx_uri_path);
            
              var overlay = {
                token: function (stream) {
            
                  if (stream.match(rx_strong) && stream.match (/\W+|$/, false))
                    return 'strong';
                  if (stream.match(rx_emphasis) && stream.match (/\W+|$/, false))
                    return 'em';
                  if (stream.match(rx_literal) && stream.match (/\W+|$/, false))
                    return 'string-2';
                  if (stream.match(rx_number))
                    return 'number';
                  if (stream.match(rx_positive))
                    return 'positive';
                  if (stream.match(rx_negative))
                    return 'negative';
                  if (stream.match(rx_uri))
                    return 'link';
            
                  while (stream.next() != null) {
                    if (stream.match(rx_strong, false)) break;
                    if (stream.match(rx_emphasis, false)) break;
                    if (stream.match(rx_literal, false)) break;
                    if (stream.match(rx_number, false)) break;
                    if (stream.match(rx_positive, false)) break;
                    if (stream.match(rx_negative, false)) break;
                    if (stream.match(rx_uri, false)) break;
                  }
            
                  return null;
                }
              };
            
              var mode = CodeMirror.getMode(
                config, options.backdrop || 'rst-base'
              );
            
              return CodeMirror.overlayMode(mode, overlay, true); // combine
            }, 'python', 'stex');
            
            ///////////////////////////////////////////////////////////////////////////////
            ///////////////////////////////////////////////////////////////////////////////
            
            CodeMirror.defineMode('rst-base', function (config) {
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              function format(string) {
                var args = Array.prototype.slice.call(arguments, 1);
                return string.replace(/{(\d+)}/g, function (match, n) {
                  return typeof args[n] != 'undefined' ? args[n] : match;
                });
              }
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              var mode_python = CodeMirror.getMode(config, 'python');
              var mode_stex = CodeMirror.getMode(config, 'stex');
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              var SEPA = "\\s+";
              var TAIL = "(?:\\s*|\\W|$)",
              rx_TAIL = new RegExp(format('^{0}', TAIL));
            
              var NAME =
                "(?:[^\\W\\d_](?:[\\w!\"#$%&'()\\*\\+,\\-\\.\/:;<=>\\?]*[^\\W_])?)",
              rx_NAME = new RegExp(format('^{0}', NAME));
              var NAME_WWS =
                "(?:[^\\W\\d_](?:[\\w\\s!\"#$%&'()\\*\\+,\\-\\.\/:;<=>\\?]*[^\\W_])?)";
              var REF_NAME = format('(?:{0}|`{1}`)', NAME, NAME_WWS);
            
              var TEXT1 = "(?:[^\\s\\|](?:[^\\|]*[^\\s\\|])?)";
              var TEXT2 = "(?:[^\\`]+)",
              rx_TEXT2 = new RegExp(format('^{0}', TEXT2));
            
              var rx_section = new RegExp(
                "^([!'#$%&\"()*+,-./:;<=>?@\\[\\\\\\]^_`{|}~])\\1{3,}\\s*$");
              var rx_explicit = new RegExp(
                format('^\\.\\.{0}', SEPA));
              var rx_link = new RegExp(
                format('^_{0}:{1}|^__:{1}', REF_NAME, TAIL));
              var rx_directive = new RegExp(
                format('^{0}::{1}', REF_NAME, TAIL));
              var rx_substitution = new RegExp(
                format('^\\|{0}\\|{1}{2}::{3}', TEXT1, SEPA, REF_NAME, TAIL));
              var rx_footnote = new RegExp(
                format('^\\[(?:\\d+|#{0}?|\\*)]{1}', REF_NAME, TAIL));
              var rx_citation = new RegExp(
                format('^\\[{0}\\]{1}', REF_NAME, TAIL));
            
              var rx_substitution_ref = new RegExp(
                format('^\\|{0}\\|', TEXT1));
              var rx_footnote_ref = new RegExp(
                format('^\\[(?:\\d+|#{0}?|\\*)]_', REF_NAME));
              var rx_citation_ref = new RegExp(
                format('^\\[{0}\\]_', REF_NAME));
              var rx_link_ref1 = new RegExp(
                format('^{0}__?', REF_NAME));
              var rx_link_ref2 = new RegExp(
                format('^`{0}`_', TEXT2));
            
              var rx_role_pre = new RegExp(
                format('^:{0}:`{1}`{2}', NAME, TEXT2, TAIL));
              var rx_role_suf = new RegExp(
                format('^`{1}`:{0}:{2}', NAME, TEXT2, TAIL));
              var rx_role = new RegExp(
                format('^:{0}:{1}', NAME, TAIL));
            
              var rx_directive_name = new RegExp(format('^{0}', REF_NAME));
              var rx_directive_tail = new RegExp(format('^::{0}', TAIL));
              var rx_substitution_text = new RegExp(format('^\\|{0}\\|', TEXT1));
              var rx_substitution_sepa = new RegExp(format('^{0}', SEPA));
              var rx_substitution_name = new RegExp(format('^{0}', REF_NAME));
              var rx_substitution_tail = new RegExp(format('^::{0}', TAIL));
              var rx_link_head = new RegExp("^_");
              var rx_link_name = new RegExp(format('^{0}|_', REF_NAME));
              var rx_link_tail = new RegExp(format('^:{0}', TAIL));
            
              var rx_verbatim = new RegExp('^::\\s*$');
              var rx_examples = new RegExp('^\\s+(?:>>>|In \\[\\d+\\]:)\\s');
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              function to_normal(stream, state) {
                var token = null;
            
                if (stream.sol() && stream.match(rx_examples, false)) {
                  change(state, to_mode, {
                    mode: mode_python, local: CodeMirror.startState(mode_python)
                  });
                } else if (stream.sol() && stream.match(rx_explicit)) {
                  change(state, to_explicit);
                  token = 'meta';
                } else if (stream.sol() && stream.match(rx_section)) {
                  change(state, to_normal);
                  token = 'header';
                } else if (phase(state) == rx_role_pre ||
                           stream.match(rx_role_pre, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_normal, context(rx_role_pre, 1));
                    stream.match(/^:/);
                    token = 'meta';
                    break;
                  case 1:
                    change(state, to_normal, context(rx_role_pre, 2));
                    stream.match(rx_NAME);
                    token = 'keyword';
            
                    if (stream.current().match(/^(?:math|latex)/)) {
                      state.tmp_stex = true;
                    }
                    break;
                  case 2:
                    change(state, to_normal, context(rx_role_pre, 3));
                    stream.match(/^:`/);
                    token = 'meta';
                    break;
                  case 3:
                    if (state.tmp_stex) {
                      state.tmp_stex = undefined; state.tmp = {
                        mode: mode_stex, local: CodeMirror.startState(mode_stex)
                      };
                    }
            
                    if (state.tmp) {
                      if (stream.peek() == '`') {
                        change(state, to_normal, context(rx_role_pre, 4));
                        state.tmp = undefined;
                        break;
                      }
            
                      token = state.tmp.mode.token(stream, state.tmp.local);
                      break;
                    }
            
                    change(state, to_normal, context(rx_role_pre, 4));
                    stream.match(rx_TEXT2);
                    token = 'string';
                    break;
                  case 4:
                    change(state, to_normal, context(rx_role_pre, 5));
                    stream.match(/^`/);
                    token = 'meta';
                    break;
                  case 5:
                    change(state, to_normal, context(rx_role_pre, 6));
                    stream.match(rx_TAIL);
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (phase(state) == rx_role_suf ||
                           stream.match(rx_role_suf, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_normal, context(rx_role_suf, 1));
                    stream.match(/^`/);
                    token = 'meta';
                    break;
                  case 1:
                    change(state, to_normal, context(rx_role_suf, 2));
                    stream.match(rx_TEXT2);
                    token = 'string';
                    break;
                  case 2:
                    change(state, to_normal, context(rx_role_suf, 3));
                    stream.match(/^`:/);
                    token = 'meta';
                    break;
                  case 3:
                    change(state, to_normal, context(rx_role_suf, 4));
                    stream.match(rx_NAME);
                    token = 'keyword';
                    break;
                  case 4:
                    change(state, to_normal, context(rx_role_suf, 5));
                    stream.match(/^:/);
                    token = 'meta';
                    break;
                  case 5:
                    change(state, to_normal, context(rx_role_suf, 6));
                    stream.match(rx_TAIL);
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (phase(state) == rx_role || stream.match(rx_role, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_normal, context(rx_role, 1));
                    stream.match(/^:/);
                    token = 'meta';
                    break;
                  case 1:
                    change(state, to_normal, context(rx_role, 2));
                    stream.match(rx_NAME);
                    token = 'keyword';
                    break;
                  case 2:
                    change(state, to_normal, context(rx_role, 3));
                    stream.match(/^:/);
                    token = 'meta';
                    break;
                  case 3:
                    change(state, to_normal, context(rx_role, 4));
                    stream.match(rx_TAIL);
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (phase(state) == rx_substitution_ref ||
                           stream.match(rx_substitution_ref, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_normal, context(rx_substitution_ref, 1));
                    stream.match(rx_substitution_text);
                    token = 'variable-2';
                    break;
                  case 1:
                    change(state, to_normal, context(rx_substitution_ref, 2));
                    if (stream.match(/^_?_?/)) token = 'link';
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (stream.match(rx_footnote_ref)) {
                  change(state, to_normal);
                  token = 'quote';
                } else if (stream.match(rx_citation_ref)) {
                  change(state, to_normal);
                  token = 'quote';
                } else if (stream.match(rx_link_ref1)) {
                  change(state, to_normal);
                  if (!stream.peek() || stream.peek().match(/^\W$/)) {
                    token = 'link';
                  }
                } else if (phase(state) == rx_link_ref2 ||
                           stream.match(rx_link_ref2, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    if (!stream.peek() || stream.peek().match(/^\W$/)) {
                      change(state, to_normal, context(rx_link_ref2, 1));
                    } else {
                      stream.match(rx_link_ref2);
                    }
                    break;
                  case 1:
                    change(state, to_normal, context(rx_link_ref2, 2));
                    stream.match(/^`/);
                    token = 'link';
                    break;
                  case 2:
                    change(state, to_normal, context(rx_link_ref2, 3));
                    stream.match(rx_TEXT2);
                    break;
                  case 3:
                    change(state, to_normal, context(rx_link_ref2, 4));
                    stream.match(/^`_/);
                    token = 'link';
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (stream.match(rx_verbatim)) {
                  change(state, to_verbatim);
                }
            
                else {
                  if (stream.next()) change(state, to_normal);
                }
            
                return token;
              }
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              function to_explicit(stream, state) {
                var token = null;
            
                if (phase(state) == rx_substitution ||
                    stream.match(rx_substitution, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_explicit, context(rx_substitution, 1));
                    stream.match(rx_substitution_text);
                    token = 'variable-2';
                    break;
                  case 1:
                    change(state, to_explicit, context(rx_substitution, 2));
                    stream.match(rx_substitution_sepa);
                    break;
                  case 2:
                    change(state, to_explicit, context(rx_substitution, 3));
                    stream.match(rx_substitution_name);
                    token = 'keyword';
                    break;
                  case 3:
                    change(state, to_explicit, context(rx_substitution, 4));
                    stream.match(rx_substitution_tail);
                    token = 'meta';
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (phase(state) == rx_directive ||
                           stream.match(rx_directive, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_explicit, context(rx_directive, 1));
                    stream.match(rx_directive_name);
                    token = 'keyword';
            
                    if (stream.current().match(/^(?:math|latex)/))
                      state.tmp_stex = true;
                    else if (stream.current().match(/^python/))
                      state.tmp_py = true;
                    break;
                  case 1:
                    change(state, to_explicit, context(rx_directive, 2));
                    stream.match(rx_directive_tail);
                    token = 'meta';
            
                    if (stream.match(/^latex\s*$/) || state.tmp_stex) {
                      state.tmp_stex = undefined; change(state, to_mode, {
                        mode: mode_stex, local: CodeMirror.startState(mode_stex)
                      });
                    }
                    break;
                  case 2:
                    change(state, to_explicit, context(rx_directive, 3));
                    if (stream.match(/^python\s*$/) || state.tmp_py) {
                      state.tmp_py = undefined; change(state, to_mode, {
                        mode: mode_python, local: CodeMirror.startState(mode_python)
                      });
                    }
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (phase(state) == rx_link || stream.match(rx_link, false)) {
            
                  switch (stage(state)) {
                  case 0:
                    change(state, to_explicit, context(rx_link, 1));
                    stream.match(rx_link_head);
                    stream.match(rx_link_name);
                    token = 'link';
                    break;
                  case 1:
                    change(state, to_explicit, context(rx_link, 2));
                    stream.match(rx_link_tail);
                    token = 'meta';
                    break;
                  default:
                    change(state, to_normal);
                  }
                } else if (stream.match(rx_footnote)) {
                  change(state, to_normal);
                  token = 'quote';
                } else if (stream.match(rx_citation)) {
                  change(state, to_normal);
                  token = 'quote';
                }
            
                else {
                  stream.eatSpace();
                  if (stream.eol()) {
                    change(state, to_normal);
                  } else {
                    stream.skipToEnd();
                    change(state, to_comment);
                    token = 'comment';
                  }
                }
            
                return token;
              }
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              function to_comment(stream, state) {
                return as_block(stream, state, 'comment');
              }
            
              function to_verbatim(stream, state) {
                return as_block(stream, state, 'meta');
              }
            
              function as_block(stream, state, token) {
                if (stream.eol() || stream.eatSpace()) {
                  stream.skipToEnd();
                  return token;
                } else {
                  change(state, to_normal);
                  return null;
                }
              }
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              function to_mode(stream, state) {
            
                if (state.ctx.mode && state.ctx.local) {
            
                  if (stream.sol()) {
                    if (!stream.eatSpace()) change(state, to_normal);
                    return null;
                  }
            
                  return state.ctx.mode.token(stream, state.ctx.local);
                }
            
                change(state, to_normal);
                return null;
              }
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              function context(phase, stage, mode, local) {
                return {phase: phase, stage: stage, mode: mode, local: local};
              }
            
              function change(state, tok, ctx) {
                state.tok = tok;
                state.ctx = ctx || {};
              }
            
              function stage(state) {
                return state.ctx.stage || 0;
              }
            
              function phase(state) {
                return state.ctx.phase;
              }
            
              ///////////////////////////////////////////////////////////////////////////
              ///////////////////////////////////////////////////////////////////////////
            
              return {
                startState: function () {
                  return {tok: to_normal, ctx: context(undefined, 0)};
                },
            
                copyState: function (state) {
                  var ctx = state.ctx, tmp = state.tmp;
                  if (ctx.local)
                    ctx = {mode: ctx.mode, local: CodeMirror.copyState(ctx.mode, ctx.local)};
                  if (tmp)
                    tmp = {mode: tmp.mode, local: CodeMirror.copyState(tmp.mode, tmp.local)};
                  return {tok: state.tok, ctx: ctx, tmp: tmp};
                },
            
                innerMode: function (state) {
                  return state.tmp      ? {state: state.tmp.local, mode: state.tmp.mode}
                  : state.ctx.mode ? {state: state.ctx.local, mode: state.ctx.mode}
                  : null;
                },
            
                token: function (stream, state) {
                  return state.tok(stream, state);
                }
              };
            }, 'python', 'stex');
            
            ///////////////////////////////////////////////////////////////////////////////
            ///////////////////////////////////////////////////////////////////////////////
            
            CodeMirror.defineMIME('text/x-rst', 'rst');
            
            ///////////////////////////////////////////////////////////////////////////////
            ///////////////////////////////////////////////////////////////////////////////
            
            });
            
        • ruby
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Ruby mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="ruby.js"></script>
            <style>
                  .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
                  .cm-s-default span.cm-arrow { color: red; }
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Ruby</a>
              </ul>
            </div>
            
            <article>
            <h2>Ruby mode</h2>
            <form><textarea id="code" name="code">
            # Code from http://sandbox.mc.edu/~bennet/ruby/code/poly_rb.html
            #
            # This program evaluates polynomials.  It first asks for the coefficients
            # of a polynomial, which must be entered on one line, highest-order first.
            # It then requests values of x and will compute the value of the poly for
            # each x.  It will repeatly ask for x values, unless you the user enters
            # a blank line.  It that case, it will ask for another polynomial.  If the
            # user types quit for either input, the program immediately exits.
            #
            
            #
            # Function to evaluate a polynomial at x.  The polynomial is given
            # as a list of coefficients, from the greatest to the least.
            def polyval(x, coef)
                sum = 0
                coef = coef.clone           # Don't want to destroy the original
                while true
                    sum += coef.shift       # Add and remove the next coef
                    break if coef.empty?    # If no more, done entirely.
                    sum *= x                # This happens the right number of times.
                end
                return sum
            end
            
            #
            # Function to read a line containing a list of integers and return
            # them as an array of integers.  If the string conversion fails, it
            # throws TypeError.  If the input line is the word 'quit', then it
            # converts it to an end-of-file exception
            def readints(prompt)
                # Read a line
                print prompt
                line = readline.chomp
                raise EOFError.new if line == 'quit' # You can also use a real EOF.
                        
                # Go through each item on the line, converting each one and adding it
                # to retval.
                retval = [ ]
                for str in line.split(/\s+/)
                    if str =~ /^\-?\d+$/
                        retval.push(str.to_i)
                    else
                        raise TypeError.new
                    end
                end
            
                return retval
            end
            
            #
            # Take a coeff and an exponent and return the string representation, ignoring
            # the sign of the coefficient.
            def term_to_str(coef, exp)
                ret = ""
            
                # Show coeff, unless it's 1 or at the right
                coef = coef.abs
                ret = coef.to_s     unless coef == 1 && exp > 0
                ret += "x" if exp > 0                               # x if exponent not 0
                ret += "^" + exp.to_s if exp > 1                    # ^exponent, if > 1.
            
                return ret
            end
            
            #
            # Create a string of the polynomial in sort-of-readable form.
            def polystr(p)
                # Get the exponent of first coefficient, plus 1.
                exp = p.length
            
                # Assign exponents to each term, making pairs of coeff and exponent,
                # Then get rid of the zero terms.
                p = (p.map { |c| exp -= 1; [ c, exp ] }).select { |p| p[0] != 0 }
            
                # If there's nothing left, it's a zero
                return "0" if p.empty?
            
                # *** Now p is a non-empty list of [ coef, exponent ] pairs. ***
            
                # Convert the first term, preceded by a "-" if it's negative.
                result = (if p[0][0] < 0 then "-" else "" end) + term_to_str(*p[0])
            
                # Convert the rest of the terms, in each case adding the appropriate
                # + or - separating them.  
                for term in p[1...p.length]
                    # Add the separator then the rep. of the term.
                    result += (if term[0] < 0 then " - " else " + " end) + 
                            term_to_str(*term)
                end
            
                return result
            end
                    
            #
            # Run until some kind of endfile.
            begin
                # Repeat until an exception or quit gets us out.
                while true
                    # Read a poly until it works.  An EOF will except out of the
                    # program.
                    print "\n"
                    begin
                        poly = readints("Enter a polynomial coefficients: ")
                    rescue TypeError
                        print "Try again.\n"
                        retry
                    end
                    break if poly.empty?
            
                    # Read and evaluate x values until the user types a blank line.
                    # Again, an EOF will except out of the pgm.
                    while true
                        # Request an integer.
                        print "Enter x value or blank line: "
                        x = readline.chomp
                        break if x == ''
                        raise EOFError.new if x == 'quit'
            
                        # If it looks bad, let's try again.
                        if x !~ /^\-?\d+$/
                            print "That doesn't look like an integer.  Please try again.\n"
                            next
                        end
            
                        # Convert to an integer and print the result.
                        x = x.to_i
                        print "p(x) = ", polystr(poly), "\n"
                        print "p(", x, ") = ", polyval(x, poly), "\n"
                    end
                end
            rescue EOFError
                print "\n=== EOF ===\n"
            rescue Interrupt, SignalException
                print "\n=== Interrupted ===\n"
            else
                print "--- Bye ---\n"
            end
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/x-ruby",
                    matchBrackets: true,
                    indentUnit: 4
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-ruby</code>.</p>
            
                <p>Development of the CodeMirror Ruby mode was kindly sponsored
                by <a href="http://ubalo.com/">Ubalo</a>.</p>
            
              </article>
            
          • ruby.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("ruby", function(config) {
              function wordObj(words) {
                var o = {};
                for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;
                return o;
              }
              var keywords = wordObj([
                "alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined?", "do", "else",
                "elsif", "END", "end", "ensure", "false", "for", "if", "in", "module", "next", "not", "or",
                "redo", "rescue", "retry", "return", "self", "super", "then", "true", "undef", "unless",
                "until", "when", "while", "yield", "nil", "raise", "throw", "catch", "fail", "loop", "callcc",
                "caller", "lambda", "proc", "public", "protected", "private", "require", "load",
                "require_relative", "extend", "autoload", "__END__", "__FILE__", "__LINE__", "__dir__"
              ]);
              var indentWords = wordObj(["def", "class", "case", "for", "while", "module", "then",
                                         "catch", "loop", "proc", "begin"]);
              var dedentWords = wordObj(["end", "until"]);
              var matching = {"[": "]", "{": "}", "(": ")"};
              var curPunc;
            
              function chain(newtok, stream, state) {
                state.tokenize.push(newtok);
                return newtok(stream, state);
              }
            
              function tokenBase(stream, state) {
                curPunc = null;
                if (stream.sol() && stream.match("=begin") && stream.eol()) {
                  state.tokenize.push(readBlockComment);
                  return "comment";
                }
                if (stream.eatSpace()) return null;
                var ch = stream.next(), m;
                if (ch == "`" || ch == "'" || ch == '"') {
                  return chain(readQuoted(ch, "string", ch == '"' || ch == "`"), stream, state);
                } else if (ch == "/") {
                  var currentIndex = stream.current().length;
                  if (stream.skipTo("/")) {
                    var search_till = stream.current().length;
                    stream.backUp(stream.current().length - currentIndex);
                    var balance = 0;  // balance brackets
                    while (stream.current().length < search_till) {
                      var chchr = stream.next();
                      if (chchr == "(") balance += 1;
                      else if (chchr == ")") balance -= 1;
                      if (balance < 0) break;
                    }
                    stream.backUp(stream.current().length - currentIndex);
                    if (balance == 0)
                      return chain(readQuoted(ch, "string-2", true), stream, state);
                  }
                  return "operator";
                } else if (ch == "%") {
                  var style = "string", embed = true;
                  if (stream.eat("s")) style = "atom";
                  else if (stream.eat(/[WQ]/)) style = "string";
                  else if (stream.eat(/[r]/)) style = "string-2";
                  else if (stream.eat(/[wxq]/)) { style = "string"; embed = false; }
                  var delim = stream.eat(/[^\w\s=]/);
                  if (!delim) return "operator";
                  if (matching.propertyIsEnumerable(delim)) delim = matching[delim];
                  return chain(readQuoted(delim, style, embed, true), stream, state);
                } else if (ch == "#") {
                  stream.skipToEnd();
                  return "comment";
                } else if (ch == "<" && (m = stream.match(/^<-?[\`\"\']?([a-zA-Z_?]\w*)[\`\"\']?(?:;|$)/))) {
                  return chain(readHereDoc(m[1]), stream, state);
                } else if (ch == "0") {
                  if (stream.eat("x")) stream.eatWhile(/[\da-fA-F]/);
                  else if (stream.eat("b")) stream.eatWhile(/[01]/);
                  else stream.eatWhile(/[0-7]/);
                  return "number";
                } else if (/\d/.test(ch)) {
                  stream.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+\-]?[\d_]+)?/);
                  return "number";
                } else if (ch == "?") {
                  while (stream.match(/^\\[CM]-/)) {}
                  if (stream.eat("\\")) stream.eatWhile(/\w/);
                  else stream.next();
                  return "string";
                } else if (ch == ":") {
                  if (stream.eat("'")) return chain(readQuoted("'", "atom", false), stream, state);
                  if (stream.eat('"')) return chain(readQuoted('"', "atom", true), stream, state);
            
                  // :> :>> :< :<< are valid symbols
                  if (stream.eat(/[\<\>]/)) {
                    stream.eat(/[\<\>]/);
                    return "atom";
                  }
            
                  // :+ :- :/ :* :| :& :! are valid symbols
                  if (stream.eat(/[\+\-\*\/\&\|\:\!]/)) {
                    return "atom";
                  }
            
                  // Symbols can't start by a digit
                  if (stream.eat(/[a-zA-Z$@_\xa1-\uffff]/)) {
                    stream.eatWhile(/[\w$\xa1-\uffff]/);
                    // Only one ? ! = is allowed and only as the last character
                    stream.eat(/[\?\!\=]/);
                    return "atom";
                  }
                  return "operator";
                } else if (ch == "@" && stream.match(/^@?[a-zA-Z_\xa1-\uffff]/)) {
                  stream.eat("@");
                  stream.eatWhile(/[\w\xa1-\uffff]/);
                  return "variable-2";
                } else if (ch == "$") {
                  if (stream.eat(/[a-zA-Z_]/)) {
                    stream.eatWhile(/[\w]/);
                  } else if (stream.eat(/\d/)) {
                    stream.eat(/\d/);
                  } else {
                    stream.next(); // Must be a special global like $: or $!
                  }
                  return "variable-3";
                } else if (/[a-zA-Z_\xa1-\uffff]/.test(ch)) {
                  stream.eatWhile(/[\w\xa1-\uffff]/);
                  stream.eat(/[\?\!]/);
                  if (stream.eat(":")) return "atom";
                  return "ident";
                } else if (ch == "|" && (state.varList || state.lastTok == "{" || state.lastTok == "do")) {
                  curPunc = "|";
                  return null;
                } else if (/[\(\)\[\]{}\\;]/.test(ch)) {
                  curPunc = ch;
                  return null;
                } else if (ch == "-" && stream.eat(">")) {
                  return "arrow";
                } else if (/[=+\-\/*:\.^%<>~|]/.test(ch)) {
                  var more = stream.eatWhile(/[=+\-\/*:\.^%<>~|]/);
                  if (ch == "." && !more) curPunc = ".";
                  return "operator";
                } else {
                  return null;
                }
              }
            
              function tokenBaseUntilBrace(depth) {
                if (!depth) depth = 1;
                return function(stream, state) {
                  if (stream.peek() == "}") {
                    if (depth == 1) {
                      state.tokenize.pop();
                      return state.tokenize[state.tokenize.length-1](stream, state);
                    } else {
                      state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth - 1);
                    }
                  } else if (stream.peek() == "{") {
                    state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth + 1);
                  }
                  return tokenBase(stream, state);
                };
              }
              function tokenBaseOnce() {
                var alreadyCalled = false;
                return function(stream, state) {
                  if (alreadyCalled) {
                    state.tokenize.pop();
                    return state.tokenize[state.tokenize.length-1](stream, state);
                  }
                  alreadyCalled = true;
                  return tokenBase(stream, state);
                };
              }
              function readQuoted(quote, style, embed, unescaped) {
                return function(stream, state) {
                  var escaped = false, ch;
            
                  if (state.context.type === 'read-quoted-paused') {
                    state.context = state.context.prev;
                    stream.eat("}");
                  }
            
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && (unescaped || !escaped)) {
                      state.tokenize.pop();
                      break;
                    }
                    if (embed && ch == "#" && !escaped) {
                      if (stream.eat("{")) {
                        if (quote == "}") {
                          state.context = {prev: state.context, type: 'read-quoted-paused'};
                        }
                        state.tokenize.push(tokenBaseUntilBrace());
                        break;
                      } else if (/[@\$]/.test(stream.peek())) {
                        state.tokenize.push(tokenBaseOnce());
                        break;
                      }
                    }
                    escaped = !escaped && ch == "\\";
                  }
                  return style;
                };
              }
              function readHereDoc(phrase) {
                return function(stream, state) {
                  if (stream.match(phrase)) state.tokenize.pop();
                  else stream.skipToEnd();
                  return "string";
                };
              }
              function readBlockComment(stream, state) {
                if (stream.sol() && stream.match("=end") && stream.eol())
                  state.tokenize.pop();
                stream.skipToEnd();
                return "comment";
              }
            
              return {
                startState: function() {
                  return {tokenize: [tokenBase],
                          indented: 0,
                          context: {type: "top", indented: -config.indentUnit},
                          continuedLine: false,
                          lastTok: null,
                          varList: false};
                },
            
                token: function(stream, state) {
                  if (stream.sol()) state.indented = stream.indentation();
                  var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype;
                  var thisTok = curPunc;
                  if (style == "ident") {
                    var word = stream.current();
                    style = state.lastTok == "." ? "property"
                      : keywords.propertyIsEnumerable(stream.current()) ? "keyword"
                      : /^[A-Z]/.test(word) ? "tag"
                      : (state.lastTok == "def" || state.lastTok == "class" || state.varList) ? "def"
                      : "variable";
                    if (style == "keyword") {
                      thisTok = word;
                      if (indentWords.propertyIsEnumerable(word)) kwtype = "indent";
                      else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent";
                      else if ((word == "if" || word == "unless") && stream.column() == stream.indentation())
                        kwtype = "indent";
                      else if (word == "do" && state.context.indented < state.indented)
                        kwtype = "indent";
                    }
                  }
                  if (curPunc || (style && style != "comment")) state.lastTok = thisTok;
                  if (curPunc == "|") state.varList = !state.varList;
            
                  if (kwtype == "indent" || /[\(\[\{]/.test(curPunc))
                    state.context = {prev: state.context, type: curPunc || style, indented: state.indented};
                  else if ((kwtype == "dedent" || /[\)\]\}]/.test(curPunc)) && state.context.prev)
                    state.context = state.context.prev;
            
                  if (stream.eol())
                    state.continuedLine = (curPunc == "\\" || style == "operator");
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0);
                  var ct = state.context;
                  var closing = ct.type == matching[firstChar] ||
                    ct.type == "keyword" && /^(?:end|until|else|elsif|when|rescue)\b/.test(textAfter);
                  return ct.indented + (closing ? 0 : config.indentUnit) +
                    (state.continuedLine ? config.indentUnit : 0);
                },
            
                electricChars: "}de", // enD and rescuE
                lineComment: "#"
              };
            });
            
            CodeMirror.defineMIME("text/x-ruby", "ruby");
            
            });
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 2}, "ruby");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT("divide_equal_operator",
                 "[variable bar] [operator /=] [variable foo]");
            
              MT("divide_equal_operator_no_spacing",
                 "[variable foo][operator /=][number 42]");
            
            })();
            
        • rust
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Rust mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="rust.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Rust</a>
              </ul>
            </div>
            
            <article>
            <h2>Rust mode</h2>
            
            
            <div><textarea id="code" name="code">
            // Demo code.
            
            type foo<T> = int;
            enum bar {
                some(int, foo<float>),
                none
            }
            
            fn check_crate(x: int) {
                let v = 10;
                alt foo {
                  1 to 3 {
                    print_foo();
                    if x {
                        blah() + 10;
                    }
                  }
                  (x, y) { "bye" }
                  _ { "hi" }
                }
            }
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-rustsrc</code>.</p>
              </article>
            
          • rust.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("rust", function() {
              var indentUnit = 4, altIndentUnit = 2;
              var valKeywords = {
                "if": "if-style", "while": "if-style", "loop": "else-style", "else": "else-style",
                "do": "else-style", "ret": "else-style", "fail": "else-style",
                "break": "atom", "cont": "atom", "const": "let", "resource": "fn",
                "let": "let", "fn": "fn", "for": "for", "alt": "alt", "iface": "iface",
                "impl": "impl", "type": "type", "enum": "enum", "mod": "mod",
                "as": "op", "true": "atom", "false": "atom", "assert": "op", "check": "op",
                "claim": "op", "native": "ignore", "unsafe": "ignore", "import": "else-style",
                "export": "else-style", "copy": "op", "log": "op", "log_err": "op",
                "use": "op", "bind": "op", "self": "atom", "struct": "enum"
              };
              var typeKeywords = function() {
                var keywords = {"fn": "fn", "block": "fn", "obj": "obj"};
                var atoms = "bool uint int i8 i16 i32 i64 u8 u16 u32 u64 float f32 f64 str char".split(" ");
                for (var i = 0, e = atoms.length; i < e; ++i) keywords[atoms[i]] = "atom";
                return keywords;
              }();
              var operatorChar = /[+\-*&%=<>!?|\.@]/;
            
              // Tokenizer
            
              // Used as scratch variable to communicate multiple values without
              // consing up tons of objects.
              var tcat, content;
              function r(tc, style) {
                tcat = tc;
                return style;
              }
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"') {
                  state.tokenize = tokenString;
                  return state.tokenize(stream, state);
                }
                if (ch == "'") {
                  tcat = "atom";
                  if (stream.eat("\\")) {
                    if (stream.skipTo("'")) { stream.next(); return "string"; }
                    else { return "error"; }
                  } else {
                    stream.next();
                    return stream.eat("'") ? "string" : "error";
                  }
                }
                if (ch == "/") {
                  if (stream.eat("/")) { stream.skipToEnd(); return "comment"; }
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment(1);
                    return state.tokenize(stream, state);
                  }
                }
                if (ch == "#") {
                  if (stream.eat("[")) { tcat = "open-attr"; return null; }
                  stream.eatWhile(/\w/);
                  return r("macro", "meta");
                }
                if (ch == ":" && stream.match(":<")) {
                  return r("op", null);
                }
                if (ch.match(/\d/) || (ch == "." && stream.eat(/\d/))) {
                  var flp = false;
                  if (!stream.match(/^x[\da-f]+/i) && !stream.match(/^b[01]+/)) {
                    stream.eatWhile(/\d/);
                    if (stream.eat(".")) { flp = true; stream.eatWhile(/\d/); }
                    if (stream.match(/^e[+\-]?\d+/i)) { flp = true; }
                  }
                  if (flp) stream.match(/^f(?:32|64)/);
                  else stream.match(/^[ui](?:8|16|32|64)/);
                  return r("atom", "number");
                }
                if (ch.match(/[()\[\]{}:;,]/)) return r(ch, null);
                if (ch == "-" && stream.eat(">")) return r("->", null);
                if (ch.match(operatorChar)) {
                  stream.eatWhile(operatorChar);
                  return r("op", null);
                }
                stream.eatWhile(/\w/);
                content = stream.current();
                if (stream.match(/^::\w/)) {
                  stream.backUp(1);
                  return r("prefix", "variable-2");
                }
                if (state.keywords.propertyIsEnumerable(content))
                  return r(state.keywords[content], content.match(/true|false/) ? "atom" : "keyword");
                return r("name", "variable");
              }
            
              function tokenString(stream, state) {
                var ch, escaped = false;
                while (ch = stream.next()) {
                  if (ch == '"' && !escaped) {
                    state.tokenize = tokenBase;
                    return r("atom", "string");
                  }
                  escaped = !escaped && ch == "\\";
                }
                // Hack to not confuse the parser when a string is split in
                // pieces.
                return r("op", "string");
              }
            
              function tokenComment(depth) {
                return function(stream, state) {
                  var lastCh = null, ch;
                  while (ch = stream.next()) {
                    if (ch == "/" && lastCh == "*") {
                      if (depth == 1) {
                        state.tokenize = tokenBase;
                        break;
                      } else {
                        state.tokenize = tokenComment(depth - 1);
                        return state.tokenize(stream, state);
                      }
                    }
                    if (ch == "*" && lastCh == "/") {
                      state.tokenize = tokenComment(depth + 1);
                      return state.tokenize(stream, state);
                    }
                    lastCh = ch;
                  }
                  return "comment";
                };
              }
            
              // Parser
            
              var cx = {state: null, stream: null, marked: null, cc: null};
              function pass() {
                for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
              }
              function cont() {
                pass.apply(null, arguments);
                return true;
              }
            
              function pushlex(type, info) {
                var result = function() {
                  var state = cx.state;
                  state.lexical = {indented: state.indented, column: cx.stream.column(),
                                   type: type, prev: state.lexical, info: info};
                };
                result.lex = true;
                return result;
              }
              function poplex() {
                var state = cx.state;
                if (state.lexical.prev) {
                  if (state.lexical.type == ")")
                    state.indented = state.lexical.indented;
                  state.lexical = state.lexical.prev;
                }
              }
              function typecx() { cx.state.keywords = typeKeywords; }
              function valcx() { cx.state.keywords = valKeywords; }
              poplex.lex = typecx.lex = valcx.lex = true;
            
              function commasep(comb, end) {
                function more(type) {
                  if (type == ",") return cont(comb, more);
                  if (type == end) return cont();
                  return cont(more);
                }
                return function(type) {
                  if (type == end) return cont();
                  return pass(comb, more);
                };
              }
            
              function stat_of(comb, tag) {
                return cont(pushlex("stat", tag), comb, poplex, block);
              }
              function block(type) {
                if (type == "}") return cont();
                if (type == "let") return stat_of(letdef1, "let");
                if (type == "fn") return stat_of(fndef);
                if (type == "type") return cont(pushlex("stat"), tydef, endstatement, poplex, block);
                if (type == "enum") return stat_of(enumdef);
                if (type == "mod") return stat_of(mod);
                if (type == "iface") return stat_of(iface);
                if (type == "impl") return stat_of(impl);
                if (type == "open-attr") return cont(pushlex("]"), commasep(expression, "]"), poplex);
                if (type == "ignore" || type.match(/[\]\);,]/)) return cont(block);
                return pass(pushlex("stat"), expression, poplex, endstatement, block);
              }
              function endstatement(type) {
                if (type == ";") return cont();
                return pass();
              }
              function expression(type) {
                if (type == "atom" || type == "name") return cont(maybeop);
                if (type == "{") return cont(pushlex("}"), exprbrace, poplex);
                if (type.match(/[\[\(]/)) return matchBrackets(type, expression);
                if (type.match(/[\]\)\};,]/)) return pass();
                if (type == "if-style") return cont(expression, expression);
                if (type == "else-style" || type == "op") return cont(expression);
                if (type == "for") return cont(pattern, maybetype, inop, expression, expression);
                if (type == "alt") return cont(expression, altbody);
                if (type == "fn") return cont(fndef);
                if (type == "macro") return cont(macro);
                return cont();
              }
              function maybeop(type) {
                if (content == ".") return cont(maybeprop);
                if (content == "::<"){return cont(typarams, maybeop);}
                if (type == "op" || content == ":") return cont(expression);
                if (type == "(" || type == "[") return matchBrackets(type, expression);
                return pass();
              }
              function maybeprop() {
                if (content.match(/^\w+$/)) {cx.marked = "variable"; return cont(maybeop);}
                return pass(expression);
              }
              function exprbrace(type) {
                if (type == "op") {
                  if (content == "|") return cont(blockvars, poplex, pushlex("}", "block"), block);
                  if (content == "||") return cont(poplex, pushlex("}", "block"), block);
                }
                if (content == "mutable" || (content.match(/^\w+$/) && cx.stream.peek() == ":"
                                             && !cx.stream.match("::", false)))
                  return pass(record_of(expression));
                return pass(block);
              }
              function record_of(comb) {
                function ro(type) {
                  if (content == "mutable" || content == "with") {cx.marked = "keyword"; return cont(ro);}
                  if (content.match(/^\w*$/)) {cx.marked = "variable"; return cont(ro);}
                  if (type == ":") return cont(comb, ro);
                  if (type == "}") return cont();
                  return cont(ro);
                }
                return ro;
              }
              function blockvars(type) {
                if (type == "name") {cx.marked = "def"; return cont(blockvars);}
                if (type == "op" && content == "|") return cont();
                return cont(blockvars);
              }
            
              function letdef1(type) {
                if (type.match(/[\]\)\};]/)) return cont();
                if (content == "=") return cont(expression, letdef2);
                if (type == ",") return cont(letdef1);
                return pass(pattern, maybetype, letdef1);
              }
              function letdef2(type) {
                if (type.match(/[\]\)\};,]/)) return pass(letdef1);
                else return pass(expression, letdef2);
              }
              function maybetype(type) {
                if (type == ":") return cont(typecx, rtype, valcx);
                return pass();
              }
              function inop(type) {
                if (type == "name" && content == "in") {cx.marked = "keyword"; return cont();}
                return pass();
              }
              function fndef(type) {
                if (content == "@" || content == "~") {cx.marked = "keyword"; return cont(fndef);}
                if (type == "name") {cx.marked = "def"; return cont(fndef);}
                if (content == "<") return cont(typarams, fndef);
                if (type == "{") return pass(expression);
                if (type == "(") return cont(pushlex(")"), commasep(argdef, ")"), poplex, fndef);
                if (type == "->") return cont(typecx, rtype, valcx, fndef);
                if (type == ";") return cont();
                return cont(fndef);
              }
              function tydef(type) {
                if (type == "name") {cx.marked = "def"; return cont(tydef);}
                if (content == "<") return cont(typarams, tydef);
                if (content == "=") return cont(typecx, rtype, valcx);
                return cont(tydef);
              }
              function enumdef(type) {
                if (type == "name") {cx.marked = "def"; return cont(enumdef);}
                if (content == "<") return cont(typarams, enumdef);
                if (content == "=") return cont(typecx, rtype, valcx, endstatement);
                if (type == "{") return cont(pushlex("}"), typecx, enumblock, valcx, poplex);
                return cont(enumdef);
              }
              function enumblock(type) {
                if (type == "}") return cont();
                if (type == "(") return cont(pushlex(")"), commasep(rtype, ")"), poplex, enumblock);
                if (content.match(/^\w+$/)) cx.marked = "def";
                return cont(enumblock);
              }
              function mod(type) {
                if (type == "name") {cx.marked = "def"; return cont(mod);}
                if (type == "{") return cont(pushlex("}"), block, poplex);
                return pass();
              }
              function iface(type) {
                if (type == "name") {cx.marked = "def"; return cont(iface);}
                if (content == "<") return cont(typarams, iface);
                if (type == "{") return cont(pushlex("}"), block, poplex);
                return pass();
              }
              function impl(type) {
                if (content == "<") return cont(typarams, impl);
                if (content == "of" || content == "for") {cx.marked = "keyword"; return cont(rtype, impl);}
                if (type == "name") {cx.marked = "def"; return cont(impl);}
                if (type == "{") return cont(pushlex("}"), block, poplex);
                return pass();
              }
              function typarams() {
                if (content == ">") return cont();
                if (content == ",") return cont(typarams);
                if (content == ":") return cont(rtype, typarams);
                return pass(rtype, typarams);
              }
              function argdef(type) {
                if (type == "name") {cx.marked = "def"; return cont(argdef);}
                if (type == ":") return cont(typecx, rtype, valcx);
                return pass();
              }
              function rtype(type) {
                if (type == "name") {cx.marked = "variable-3"; return cont(rtypemaybeparam); }
                if (content == "mutable") {cx.marked = "keyword"; return cont(rtype);}
                if (type == "atom") return cont(rtypemaybeparam);
                if (type == "op" || type == "obj") return cont(rtype);
                if (type == "fn") return cont(fntype);
                if (type == "{") return cont(pushlex("{"), record_of(rtype), poplex);
                return matchBrackets(type, rtype);
              }
              function rtypemaybeparam() {
                if (content == "<") return cont(typarams);
                return pass();
              }
              function fntype(type) {
                if (type == "(") return cont(pushlex("("), commasep(rtype, ")"), poplex, fntype);
                if (type == "->") return cont(rtype);
                return pass();
              }
              function pattern(type) {
                if (type == "name") {cx.marked = "def"; return cont(patternmaybeop);}
                if (type == "atom") return cont(patternmaybeop);
                if (type == "op") return cont(pattern);
                if (type.match(/[\]\)\};,]/)) return pass();
                return matchBrackets(type, pattern);
              }
              function patternmaybeop(type) {
                if (type == "op" && content == ".") return cont();
                if (content == "to") {cx.marked = "keyword"; return cont(pattern);}
                else return pass();
              }
              function altbody(type) {
                if (type == "{") return cont(pushlex("}", "alt"), altblock1, poplex);
                return pass();
              }
              function altblock1(type) {
                if (type == "}") return cont();
                if (type == "|") return cont(altblock1);
                if (content == "when") {cx.marked = "keyword"; return cont(expression, altblock2);}
                if (type.match(/[\]\);,]/)) return cont(altblock1);
                return pass(pattern, altblock2);
              }
              function altblock2(type) {
                if (type == "{") return cont(pushlex("}", "alt"), block, poplex, altblock1);
                else return pass(altblock1);
              }
            
              function macro(type) {
                if (type.match(/[\[\(\{]/)) return matchBrackets(type, expression);
                return pass();
              }
              function matchBrackets(type, comb) {
                if (type == "[") return cont(pushlex("]"), commasep(comb, "]"), poplex);
                if (type == "(") return cont(pushlex(")"), commasep(comb, ")"), poplex);
                if (type == "{") return cont(pushlex("}"), commasep(comb, "}"), poplex);
                return cont();
              }
            
              function parse(state, stream, style) {
                var cc = state.cc;
                // Communicate our context to the combinators.
                // (Less wasteful than consing up a hundred closures on every call.)
                cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
            
                while (true) {
                  var combinator = cc.length ? cc.pop() : block;
                  if (combinator(tcat)) {
                    while(cc.length && cc[cc.length - 1].lex)
                      cc.pop()();
                    return cx.marked || style;
                  }
                }
              }
            
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase,
                    cc: [],
                    lexical: {indented: -indentUnit, column: 0, type: "top", align: false},
                    keywords: valKeywords,
                    indented: 0
                  };
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (!state.lexical.hasOwnProperty("align"))
                      state.lexical.align = false;
                    state.indented = stream.indentation();
                  }
                  if (stream.eatSpace()) return null;
                  tcat = content = null;
                  var style = state.tokenize(stream, state);
                  if (style == "comment") return style;
                  if (!state.lexical.hasOwnProperty("align"))
                    state.lexical.align = true;
                  if (tcat == "prefix") return style;
                  if (!content) content = stream.current();
                  return parse(state, stream, style);
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase) return 0;
                  var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,
                      type = lexical.type, closing = firstChar == type;
                  if (type == "stat") return lexical.indented + indentUnit;
                  if (lexical.align) return lexical.column + (closing ? 0 : 1);
                  return lexical.indented + (closing ? 0 : (lexical.info == "alt" ? altIndentUnit : indentUnit));
                },
            
                electricChars: "{}",
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                lineComment: "//",
                fold: "brace"
              };
            });
            
            CodeMirror.defineMIME("text/x-rustsrc", "rust");
            
            });
            
        • sass
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Sass mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="sass.js"></script>
            <style>.CodeMirror {border: 1px solid #ddd; font-size:12px; height: 400px}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Sass</a>
              </ul>
            </div>
            
            <article>
            <h2>Sass mode</h2>
            <form><textarea id="code" name="code">// Variable Definitions
            
            $page-width:    800px
            $sidebar-width: 200px
            $primary-color: #eeeeee
            
            // Global Attributes
            
            body
              font:
                family: sans-serif
                size: 30em
                weight: bold
            
            // Scoped Styles
            
            #contents
              width: $page-width
              #sidebar
                float: right
                width: $sidebar-width
              #main
                width: $page-width - $sidebar-width
                background: $primary-color
                h2
                  color: blue
            
            #footer
              height: 200px
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers : true,
                    matchBrackets : true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-sass</code>.</p>
              </article>
            
          • sass.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("sass", function(config) {
              function tokenRegexp(words) {
                return new RegExp("^" + words.join("|"));
              }
            
              var keywords = ["true", "false", "null", "auto"];
              var keywordsRegexp = new RegExp("^" + keywords.join("|"));
            
              var operators = ["\\(", "\\)", "=", ">", "<", "==", ">=", "<=", "\\+", "-",
                               "\\!=", "/", "\\*", "%", "and", "or", "not", ";","\\{","\\}",":"];
              var opRegexp = tokenRegexp(operators);
            
              var pseudoElementsRegexp = /^::?[a-zA-Z_][\w\-]*/;
            
              function urlTokens(stream, state) {
                var ch = stream.peek();
            
                if (ch === ")") {
                  stream.next();
                  state.tokenizer = tokenBase;
                  return "operator";
                } else if (ch === "(") {
                  stream.next();
                  stream.eatSpace();
            
                  return "operator";
                } else if (ch === "'" || ch === '"') {
                  state.tokenizer = buildStringTokenizer(stream.next());
                  return "string";
                } else {
                  state.tokenizer = buildStringTokenizer(")", false);
                  return "string";
                }
              }
              function comment(indentation, multiLine) {
                return function(stream, state) {
                  if (stream.sol() && stream.indentation() <= indentation) {
                    state.tokenizer = tokenBase;
                    return tokenBase(stream, state);
                  }
            
                  if (multiLine && stream.skipTo("*/")) {
                    stream.next();
                    stream.next();
                    state.tokenizer = tokenBase;
                  } else {
                    stream.skipToEnd();
                  }
            
                  return "comment";
                };
              }
            
              function buildStringTokenizer(quote, greedy) {
                if (greedy == null) { greedy = true; }
            
                function stringTokenizer(stream, state) {
                  var nextChar = stream.next();
                  var peekChar = stream.peek();
                  var previousChar = stream.string.charAt(stream.pos-2);
            
                  var endingString = ((nextChar !== "\\" && peekChar === quote) || (nextChar === quote && previousChar !== "\\"));
            
                  if (endingString) {
                    if (nextChar !== quote && greedy) { stream.next(); }
                    state.tokenizer = tokenBase;
                    return "string";
                  } else if (nextChar === "#" && peekChar === "{") {
                    state.tokenizer = buildInterpolationTokenizer(stringTokenizer);
                    stream.next();
                    return "operator";
                  } else {
                    return "string";
                  }
                }
            
                return stringTokenizer;
              }
            
              function buildInterpolationTokenizer(currentTokenizer) {
                return function(stream, state) {
                  if (stream.peek() === "}") {
                    stream.next();
                    state.tokenizer = currentTokenizer;
                    return "operator";
                  } else {
                    return tokenBase(stream, state);
                  }
                };
              }
            
              function indent(state) {
                if (state.indentCount == 0) {
                  state.indentCount++;
                  var lastScopeOffset = state.scopes[0].offset;
                  var currentOffset = lastScopeOffset + config.indentUnit;
                  state.scopes.unshift({ offset:currentOffset });
                }
              }
            
              function dedent(state) {
                if (state.scopes.length == 1) return;
            
                state.scopes.shift();
              }
            
              function tokenBase(stream, state) {
                var ch = stream.peek();
            
                // Comment
                if (stream.match("/*")) {
                  state.tokenizer = comment(stream.indentation(), true);
                  return state.tokenizer(stream, state);
                }
                if (stream.match("//")) {
                  state.tokenizer = comment(stream.indentation(), false);
                  return state.tokenizer(stream, state);
                }
            
                // Interpolation
                if (stream.match("#{")) {
                  state.tokenizer = buildInterpolationTokenizer(tokenBase);
                  return "operator";
                }
            
                // Strings
                if (ch === '"' || ch === "'") {
                  stream.next();
                  state.tokenizer = buildStringTokenizer(ch);
                  return "string";
                }
            
                if(!state.cursorHalf){// state.cursorHalf === 0
                // first half i.e. before : for key-value pairs
                // including selectors
            
                  if (ch === ".") {
                    stream.next();
                    if (stream.match(/^[\w-]+/)) {
                      indent(state);
                      return "atom";
                    } else if (stream.peek() === "#") {
                      indent(state);
                      return "atom";
                    }
                  }
            
                  if (ch === "#") {
                    stream.next();
                    // ID selectors
                    if (stream.match(/^[\w-]+/)) {
                      indent(state);
                      return "atom";
                    }
                    if (stream.peek() === "#") {
                      indent(state);
                      return "atom";
                    }
                  }
            
                  // Variables
                  if (ch === "$") {
                    stream.next();
                    stream.eatWhile(/[\w-]/);
                    return "variable-2";
                  }
            
                  // Numbers
                  if (stream.match(/^-?[0-9\.]+/))
                    return "number";
            
                  // Units
                  if (stream.match(/^(px|em|in)\b/))
                    return "unit";
            
                  if (stream.match(keywordsRegexp))
                    return "keyword";
            
                  if (stream.match(/^url/) && stream.peek() === "(") {
                    state.tokenizer = urlTokens;
                    return "atom";
                  }
            
                  if (ch === "=") {
                    // Match shortcut mixin definition
                    if (stream.match(/^=[\w-]+/)) {
                      indent(state);
                      return "meta";
                    }
                  }
            
                  if (ch === "+") {
                    // Match shortcut mixin definition
                    if (stream.match(/^\+[\w-]+/)){
                      return "variable-3";
                    }
                  }
            
                  if(ch === "@"){
                    if(stream.match(/@extend/)){
                      if(!stream.match(/\s*[\w]/))
                        dedent(state);
                    }
                  }
            
            
                  // Indent Directives
                  if (stream.match(/^@(else if|if|media|else|for|each|while|mixin|function)/)) {
                    indent(state);
                    return "meta";
                  }
            
                  // Other Directives
                  if (ch === "@") {
                    stream.next();
                    stream.eatWhile(/[\w-]/);
                    return "meta";
                  }
            
                  if (stream.eatWhile(/[\w-]/)){
                    if(stream.match(/ *: *[\w-\+\$#!\("']/,false)){
                      return "property";
                    }
                    else if(stream.match(/ *:/,false)){
                      indent(state);
                      state.cursorHalf = 1;
                      return "atom";
                    }
                    else if(stream.match(/ *,/,false)){
                      return "atom";
                    }
                    else{
                      indent(state);
                      return "atom";
                    }
                  }
            
                  if(ch === ":"){
                    if (stream.match(pseudoElementsRegexp)){ // could be a pseudo-element
                      return "keyword";
                    }
                    stream.next();
                    state.cursorHalf=1;
                    return "operator";
                  }
            
                } // cursorHalf===0 ends here
                else{
            
                  if (ch === "#") {
                    stream.next();
                    // Hex numbers
                    if (stream.match(/[0-9a-fA-F]{6}|[0-9a-fA-F]{3}/)){
                      if(!stream.peek()){
                        state.cursorHalf = 0;
                      }
                      return "number";
                    }
                  }
            
                  // Numbers
                  if (stream.match(/^-?[0-9\.]+/)){
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "number";
                  }
            
                  // Units
                  if (stream.match(/^(px|em|in)\b/)){
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "unit";
                  }
            
                  if (stream.match(keywordsRegexp)){
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "keyword";
                  }
            
                  if (stream.match(/^url/) && stream.peek() === "(") {
                    state.tokenizer = urlTokens;
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "atom";
                  }
            
                  // Variables
                  if (ch === "$") {
                    stream.next();
                    stream.eatWhile(/[\w-]/);
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "variable-3";
                  }
            
                  // bang character for !important, !default, etc.
                  if (ch === "!") {
                    stream.next();
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return stream.match(/^[\w]+/) ? "keyword": "operator";
                  }
            
                  if (stream.match(opRegexp)){
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "operator";
                  }
            
                  // attributes
                  if (stream.eatWhile(/[\w-]/)) {
                    if(!stream.peek()){
                      state.cursorHalf = 0;
                    }
                    return "attribute";
                  }
            
                  //stream.eatSpace();
                  if(!stream.peek()){
                    state.cursorHalf = 0;
                    return null;
                  }
            
                } // else ends here
            
                if (stream.match(opRegexp))
                  return "operator";
            
                // If we haven't returned by now, we move 1 character
                // and return an error
                stream.next();
                return null;
              }
            
              function tokenLexer(stream, state) {
                if (stream.sol()) state.indentCount = 0;
                var style = state.tokenizer(stream, state);
                var current = stream.current();
            
                if (current === "@return" || current === "}"){
                  dedent(state);
                }
            
                if (style !== null) {
                  var startOfToken = stream.pos - current.length;
            
                  var withCurrentIndent = startOfToken + (config.indentUnit * state.indentCount);
            
                  var newScopes = [];
            
                  for (var i = 0; i < state.scopes.length; i++) {
                    var scope = state.scopes[i];
            
                    if (scope.offset <= withCurrentIndent)
                      newScopes.push(scope);
                  }
            
                  state.scopes = newScopes;
                }
            
            
                return style;
              }
            
              return {
                startState: function() {
                  return {
                    tokenizer: tokenBase,
                    scopes: [{offset: 0, type: "sass"}],
                    indentCount: 0,
                    cursorHalf: 0,  // cursor half tells us if cursor lies after (1)
                                    // or before (0) colon (well... more or less)
                    definedVars: [],
                    definedMixins: []
                  };
                },
                token: function(stream, state) {
                  var style = tokenLexer(stream, state);
            
                  state.lastToken = { style: style, content: stream.current() };
            
                  return style;
                },
            
                indent: function(state) {
                  return state.scopes[0].offset;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-sass", "sass");
            
            });
            
        • scheme
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Scheme mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="scheme.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Scheme</a>
              </ul>
            </div>
            
            <article>
            <h2>Scheme mode</h2>
            <form><textarea id="code" name="code">
            ; See if the input starts with a given symbol.
            (define (match-symbol input pattern)
              (cond ((null? (remain input)) #f)
            	((eqv? (car (remain input)) pattern) (r-cdr input))
            	(else #f)))
            
            ; Allow the input to start with one of a list of patterns.
            (define (match-or input pattern)
              (cond ((null? pattern) #f)
            	((match-pattern input (car pattern)))
            	(else (match-or input (cdr pattern)))))
            
            ; Allow a sequence of patterns.
            (define (match-seq input pattern)
              (if (null? pattern)
                  input
                  (let ((match (match-pattern input (car pattern))))
            	(if match (match-seq match (cdr pattern)) #f))))
            
            ; Match with the pattern but no problem if it does not match.
            (define (match-opt input pattern)
              (let ((match (match-pattern input (car pattern))))
                (if match match input)))
            
            ; Match anything (other than '()), until pattern is found. The rather
            ; clumsy form of requiring an ending pattern is needed to decide where
            ; the end of the match is. If none is given, this will match the rest
            ; of the sentence.
            (define (match-any input pattern)
              (cond ((null? (remain input)) #f)
            	((null? pattern) (f-cons (remain input) (clear-remain input)))
            	(else
            	 (let ((accum-any (collector)))
            	   (define (match-pattern-any input pattern)
            	     (cond ((null? (remain input)) #f)
            		   (else (accum-any (car (remain input)))
            			 (cond ((match-pattern (r-cdr input) pattern))
            			       (else (match-pattern-any (r-cdr input) pattern))))))
            	   (let ((retval (match-pattern-any input (car pattern))))
            	     (if retval
            		 (f-cons (accum-any) retval)
            		 #f))))))
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-scheme</code>.</p>
            
              </article>
            
          • scheme.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Author: Koh Zi Han, based on implementation by Koh Zi Chun
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("scheme", function () {
                var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
                    ATOM = "atom", NUMBER = "number", BRACKET = "bracket";
                var INDENT_WORD_SKIP = 2;
            
                function makeKeywords(str) {
                    var obj = {}, words = str.split(" ");
                    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                    return obj;
                }
            
                var keywords = makeKeywords("λ case-lambda call/cc class define-class exit-handler field import inherit init-field interface let*-values let-values let/ec mixin opt-lambda override protect provide public rename require require-for-syntax syntax syntax-case syntax-error unit/sig unless when with-syntax and begin call-with-current-continuation call-with-input-file call-with-output-file case cond define define-syntax delay do dynamic-wind else for-each if lambda let let* let-syntax letrec letrec-syntax map or syntax-rules abs acos angle append apply asin assoc assq assv atan boolean? caar cadr call-with-input-file call-with-output-file call-with-values car cdddar cddddr cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char<? char=? char>=? char>? char? close-input-port close-output-port complex? cons cos current-input-port current-output-port denominator display eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt #f floor force gcd imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lcm length list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file output-port? pair? peek-char port? positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci<? string-ci=? string-ci>=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string<? string=? string>=? string>? string? substring symbol->string symbol? #t tan transcript-off transcript-on truncate values vector vector->list vector-fill! vector-length vector-ref vector-set! with-input-from-file with-output-to-file write write-char zero?");
                var indentKeys = makeKeywords("define let letrec let* lambda");
            
                function stateStack(indent, type, prev) { // represents a state stack object
                    this.indent = indent;
                    this.type = type;
                    this.prev = prev;
                }
            
                function pushStack(state, indent, type) {
                    state.indentStack = new stateStack(indent, type, state.indentStack);
                }
            
                function popStack(state) {
                    state.indentStack = state.indentStack.prev;
                }
            
                var binaryMatcher = new RegExp(/^(?:[-+]i|[-+][01]+#*(?:\/[01]+#*)?i|[-+]?[01]+#*(?:\/[01]+#*)?@[-+]?[01]+#*(?:\/[01]+#*)?|[-+]?[01]+#*(?:\/[01]+#*)?[-+](?:[01]+#*(?:\/[01]+#*)?)?i|[-+]?[01]+#*(?:\/[01]+#*)?)(?=[()\s;"]|$)/i);
                var octalMatcher = new RegExp(/^(?:[-+]i|[-+][0-7]+#*(?:\/[0-7]+#*)?i|[-+]?[0-7]+#*(?:\/[0-7]+#*)?@[-+]?[0-7]+#*(?:\/[0-7]+#*)?|[-+]?[0-7]+#*(?:\/[0-7]+#*)?[-+](?:[0-7]+#*(?:\/[0-7]+#*)?)?i|[-+]?[0-7]+#*(?:\/[0-7]+#*)?)(?=[()\s;"]|$)/i);
                var hexMatcher = new RegExp(/^(?:[-+]i|[-+][\da-f]+#*(?:\/[\da-f]+#*)?i|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?@[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?[-+](?:[\da-f]+#*(?:\/[\da-f]+#*)?)?i|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?)(?=[()\s;"]|$)/i);
                var decimalMatcher = new RegExp(/^(?:[-+]i|[-+](?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)i|[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)@[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)|[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)[-+](?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)?i|(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*))(?=[()\s;"]|$)/i);
            
                function isBinaryNumber (stream) {
                    return stream.match(binaryMatcher);
                }
            
                function isOctalNumber (stream) {
                    return stream.match(octalMatcher);
                }
            
                function isDecimalNumber (stream, backup) {
                    if (backup === true) {
                        stream.backUp(1);
                    }
                    return stream.match(decimalMatcher);
                }
            
                function isHexNumber (stream) {
                    return stream.match(hexMatcher);
                }
            
                return {
                    startState: function () {
                        return {
                            indentStack: null,
                            indentation: 0,
                            mode: false,
                            sExprComment: false
                        };
                    },
            
                    token: function (stream, state) {
                        if (state.indentStack == null && stream.sol()) {
                            // update indentation, but only if indentStack is empty
                            state.indentation = stream.indentation();
                        }
            
                        // skip spaces
                        if (stream.eatSpace()) {
                            return null;
                        }
                        var returnType = null;
            
                        switch(state.mode){
                            case "string": // multi-line string parsing mode
                                var next, escaped = false;
                                while ((next = stream.next()) != null) {
                                    if (next == "\"" && !escaped) {
            
                                        state.mode = false;
                                        break;
                                    }
                                    escaped = !escaped && next == "\\";
                                }
                                returnType = STRING; // continue on in scheme-string mode
                                break;
                            case "comment": // comment parsing mode
                                var next, maybeEnd = false;
                                while ((next = stream.next()) != null) {
                                    if (next == "#" && maybeEnd) {
            
                                        state.mode = false;
                                        break;
                                    }
                                    maybeEnd = (next == "|");
                                }
                                returnType = COMMENT;
                                break;
                            case "s-expr-comment": // s-expr commenting mode
                                state.mode = false;
                                if(stream.peek() == "(" || stream.peek() == "["){
                                    // actually start scheme s-expr commenting mode
                                    state.sExprComment = 0;
                                }else{
                                    // if not we just comment the entire of the next token
                                    stream.eatWhile(/[^/s]/); // eat non spaces
                                    returnType = COMMENT;
                                    break;
                                }
                            default: // default parsing mode
                                var ch = stream.next();
            
                                if (ch == "\"") {
                                    state.mode = "string";
                                    returnType = STRING;
            
                                } else if (ch == "'") {
                                    returnType = ATOM;
                                } else if (ch == '#') {
                                    if (stream.eat("|")) {                    // Multi-line comment
                                        state.mode = "comment"; // toggle to comment mode
                                        returnType = COMMENT;
                                    } else if (stream.eat(/[tf]/i)) {            // #t/#f (atom)
                                        returnType = ATOM;
                                    } else if (stream.eat(';')) {                // S-Expr comment
                                        state.mode = "s-expr-comment";
                                        returnType = COMMENT;
                                    } else {
                                        var numTest = null, hasExactness = false, hasRadix = true;
                                        if (stream.eat(/[ei]/i)) {
                                            hasExactness = true;
                                        } else {
                                            stream.backUp(1);       // must be radix specifier
                                        }
                                        if (stream.match(/^#b/i)) {
                                            numTest = isBinaryNumber;
                                        } else if (stream.match(/^#o/i)) {
                                            numTest = isOctalNumber;
                                        } else if (stream.match(/^#x/i)) {
                                            numTest = isHexNumber;
                                        } else if (stream.match(/^#d/i)) {
                                            numTest = isDecimalNumber;
                                        } else if (stream.match(/^[-+0-9.]/, false)) {
                                            hasRadix = false;
                                            numTest = isDecimalNumber;
                                        // re-consume the intial # if all matches failed
                                        } else if (!hasExactness) {
                                            stream.eat('#');
                                        }
                                        if (numTest != null) {
                                            if (hasRadix && !hasExactness) {
                                                // consume optional exactness after radix
                                                stream.match(/^#[ei]/i);
                                            }
                                            if (numTest(stream))
                                                returnType = NUMBER;
                                        }
                                    }
                                } else if (/^[-+0-9.]/.test(ch) && isDecimalNumber(stream, true)) { // match non-prefixed number, must be decimal
                                    returnType = NUMBER;
                                } else if (ch == ";") { // comment
                                    stream.skipToEnd(); // rest of the line is a comment
                                    returnType = COMMENT;
                                } else if (ch == "(" || ch == "[") {
                                  var keyWord = ''; var indentTemp = stream.column(), letter;
                                    /**
                                    Either
                                    (indent-word ..
                                    (non-indent-word ..
                                    (;something else, bracket, etc.
                                    */
            
                                    while ((letter = stream.eat(/[^\s\(\[\;\)\]]/)) != null) {
                                        keyWord += letter;
                                    }
            
                                    if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word
            
                                        pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
                                    } else { // non-indent word
                                        // we continue eating the spaces
                                        stream.eatSpace();
                                        if (stream.eol() || stream.peek() == ";") {
                                            // nothing significant after
                                            // we restart indentation 1 space after
                                            pushStack(state, indentTemp + 1, ch);
                                        } else {
                                            pushStack(state, indentTemp + stream.current().length, ch); // else we match
                                        }
                                    }
                                    stream.backUp(stream.current().length - 1); // undo all the eating
            
                                    if(typeof state.sExprComment == "number") state.sExprComment++;
            
                                    returnType = BRACKET;
                                } else if (ch == ")" || ch == "]") {
                                    returnType = BRACKET;
                                    if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : "[")) {
                                        popStack(state);
            
                                        if(typeof state.sExprComment == "number"){
                                            if(--state.sExprComment == 0){
                                                returnType = COMMENT; // final closing bracket
                                                state.sExprComment = false; // turn off s-expr commenting mode
                                            }
                                        }
                                    }
                                } else {
                                    stream.eatWhile(/[\w\$_\-!$%&*+\.\/:<=>?@\^~]/);
            
                                    if (keywords && keywords.propertyIsEnumerable(stream.current())) {
                                        returnType = BUILTIN;
                                    } else returnType = "variable";
                                }
                        }
                        return (typeof state.sExprComment == "number") ? COMMENT : returnType;
                    },
            
                    indent: function (state) {
                        if (state.indentStack == null) return state.indentation;
                        return state.indentStack.indent;
                    },
            
                    closeBrackets: {pairs: "()[]{}\"\""},
                    lineComment: ";;"
                };
            });
            
            CodeMirror.defineMIME("text/x-scheme", "scheme");
            
            });
            
        • shell
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Shell mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel=stylesheet href=../../lib/codemirror.css>
            <script src=../../lib/codemirror.js></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src=shell.js></script>
            <style type=text/css>
              .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
            </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Shell</a>
              </ul>
            </div>
            
            <article>
            <h2>Shell mode</h2>
            
            
            <textarea id=code>
            #!/bin/bash
            
            # clone the repository
            git clone http://github.com/garden/tree
            
            # generate HTTPS credentials
            cd tree
            openssl genrsa -aes256 -out https.key 1024
            openssl req -new -nodes -key https.key -out https.csr
            openssl x509 -req -days 365 -in https.csr -signkey https.key -out https.crt
            cp https.key{,.orig}
            openssl rsa -in https.key.orig -out https.key
            
            # start the server in HTTPS mode
            cd web
            sudo node ../server.js 443 'yes' &gt;&gt; ../node.log &amp;
            
            # here is how to stop the server
            for pid in `ps aux | grep 'node ../server.js' | awk '{print $2}'` ; do
              sudo kill -9 $pid 2&gt; /dev/null
            done
            
            exit 0</textarea>
            
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
                mode: 'shell',
                lineNumbers: true,
                matchBrackets: true
              });
            </script>
            
            <p><strong>MIME types defined:</strong> <code>text/x-sh</code>.</p>
            </article>
            
          • shell.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('shell', function() {
            
              var words = {};
              function define(style, string) {
                var split = string.split(' ');
                for(var i = 0; i < split.length; i++) {
                  words[split[i]] = style;
                }
              };
            
              // Atoms
              define('atom', 'true false');
            
              // Keywords
              define('keyword', 'if then do else elif while until for in esac fi fin ' +
                'fil done exit set unset export function');
            
              // Commands
              define('builtin', 'ab awk bash beep cat cc cd chown chmod chroot clear cp ' +
                'curl cut diff echo find gawk gcc get git grep kill killall ln ls make ' +
                'mkdir openssl mv nc node npm ping ps restart rm rmdir sed service sh ' +
                'shopt shred source sort sleep ssh start stop su sudo tee telnet top ' +
                'touch vi vim wall wc wget who write yes zsh');
            
              function tokenBase(stream, state) {
                if (stream.eatSpace()) return null;
            
                var sol = stream.sol();
                var ch = stream.next();
            
                if (ch === '\\') {
                  stream.next();
                  return null;
                }
                if (ch === '\'' || ch === '"' || ch === '`') {
                  state.tokens.unshift(tokenString(ch));
                  return tokenize(stream, state);
                }
                if (ch === '#') {
                  if (sol && stream.eat('!')) {
                    stream.skipToEnd();
                    return 'meta'; // 'comment'?
                  }
                  stream.skipToEnd();
                  return 'comment';
                }
                if (ch === '$') {
                  state.tokens.unshift(tokenDollar);
                  return tokenize(stream, state);
                }
                if (ch === '+' || ch === '=') {
                  return 'operator';
                }
                if (ch === '-') {
                  stream.eat('-');
                  stream.eatWhile(/\w/);
                  return 'attribute';
                }
                if (/\d/.test(ch)) {
                  stream.eatWhile(/\d/);
                  if(stream.eol() || !/\w/.test(stream.peek())) {
                    return 'number';
                  }
                }
                stream.eatWhile(/[\w-]/);
                var cur = stream.current();
                if (stream.peek() === '=' && /\w+/.test(cur)) return 'def';
                return words.hasOwnProperty(cur) ? words[cur] : null;
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var next, end = false, escaped = false;
                  while ((next = stream.next()) != null) {
                    if (next === quote && !escaped) {
                      end = true;
                      break;
                    }
                    if (next === '$' && !escaped && quote !== '\'') {
                      escaped = true;
                      stream.backUp(1);
                      state.tokens.unshift(tokenDollar);
                      break;
                    }
                    escaped = !escaped && next === '\\';
                  }
                  if (end || !escaped) {
                    state.tokens.shift();
                  }
                  return (quote === '`' || quote === ')' ? 'quote' : 'string');
                };
              };
            
              var tokenDollar = function(stream, state) {
                if (state.tokens.length > 1) stream.eat('$');
                var ch = stream.next(), hungry = /\w/;
                if (ch === '{') hungry = /[^}]/;
                if (ch === '(') {
                  state.tokens[0] = tokenString(')');
                  return tokenize(stream, state);
                }
                if (!/\d/.test(ch)) {
                  stream.eatWhile(hungry);
                  stream.eat('}');
                }
                state.tokens.shift();
                return 'def';
              };
            
              function tokenize(stream, state) {
                return (state.tokens[0] || tokenBase) (stream, state);
              };
            
              return {
                startState: function() {return {tokens:[]};},
                token: function(stream, state) {
                  return tokenize(stream, state);
                },
                lineComment: '#',
                fold: "brace"
              };
            });
            
            CodeMirror.defineMIME('text/x-sh', 'shell');
            
            });
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({}, "shell");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT("var",
                 "text [def $var] text");
              MT("varBraces",
                 "text[def ${var}]text");
              MT("varVar",
                 "text [def $a$b] text");
              MT("varBracesVarBraces",
                 "text[def ${a}${b}]text");
            
              MT("singleQuotedVar",
                 "[string 'text $var text']");
              MT("singleQuotedVarBraces",
                 "[string 'text ${var} text']");
            
              MT("doubleQuotedVar",
                 '[string "text ][def $var][string  text"]');
              MT("doubleQuotedVarBraces",
                 '[string "text][def ${var}][string text"]');
              MT("doubleQuotedVarPunct",
                 '[string "text ][def $@][string  text"]');
              MT("doubleQuotedVarVar",
                 '[string "][def $a$b][string "]');
              MT("doubleQuotedVarBracesVarBraces",
                 '[string "][def ${a}${b}][string "]');
            
              MT("notAString",
                 "text\\'text");
              MT("escapes",
                 "outside\\'\\\"\\`\\\\[string \"inside\\`\\'\\\"\\\\`\\$notAVar\"]outside\\$\\(notASubShell\\)");
            
              MT("subshell",
                 "[builtin echo] [quote $(whoami)] s log, stardate [quote `date`].");
              MT("doubleQuotedSubshell",
                 "[builtin echo] [string \"][quote $(whoami)][string 's log, stardate `date`.\"]");
            
              MT("hashbang",
                 "[meta #!/bin/bash]");
              MT("comment",
                 "text [comment # Blurb]");
            
              MT("numbers",
                 "[number 0] [number 1] [number 2]");
              MT("keywords",
                 "[keyword while] [atom true]; [keyword do]",
                 "  [builtin sleep] [number 3]",
                 "[keyword done]");
              MT("options",
                 "[builtin ls] [attribute -l] [attribute --human-readable]");
              MT("operator",
                 "[def var][operator =]value");
            })();
            
        • sieve
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Sieve (RFC5228) mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="sieve.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Sieve (RFC5228)</a>
              </ul>
            </div>
            
            <article>
            <h2>Sieve (RFC5228) mode</h2>
            <form><textarea id="code" name="code">
            #
            # Example Sieve Filter
            # Declare any optional features or extension used by the script
            #
            
            require ["fileinto", "reject"];
            
            #
            # Reject any large messages (note that the four leading dots get
            # "stuffed" to three)
            #
            if size :over 1M
            {
              reject text:
            Please do not send me large attachments.
            Put your file on a server and send me the URL.
            Thank you.
            .... Fred
            .
            ;
              stop;
            }
            
            #
            # Handle messages from known mailing lists
            # Move messages from IETF filter discussion list to filter folder
            #
            if header :is "Sender" "owner-ietf-mta-filters@imc.org"
            {
              fileinto "filter";  # move to "filter" folder
            }
            #
            # Keep all messages to or from people in my company
            #
            elsif address :domain :is ["From", "To"] "example.com"
            {
              keep;               # keep in "In" folder
            }
            
            #
            # Try and catch unsolicited email.  If a message is not to me,
            # or it contains a subject known to be spam, file it away.
            #
            elsif anyof (not address :all :contains
                           ["To", "Cc", "Bcc"] "me@example.com",
                         header :matches "subject"
                           ["*make*money*fast*", "*university*dipl*mas*"])
            {
              # If message header does not contain my address,
              # it's from a list.
              fileinto "spam";   # move to "spam" folder
            }
            else
            {
              # Move all other (non-company) mail to "personal"
              # folder.
              fileinto "personal";
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>application/sieve</code>.</p>
            
              </article>
            
          • sieve.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("sieve", function(config) {
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              var keywords = words("if elsif else stop require");
              var atoms = words("true false not");
              var indentUnit = config.indentUnit;
            
              function tokenBase(stream, state) {
            
                var ch = stream.next();
                if (ch == "/" && stream.eat("*")) {
                  state.tokenize = tokenCComment;
                  return tokenCComment(stream, state);
                }
            
                if (ch === '#') {
                  stream.skipToEnd();
                  return "comment";
                }
            
                if (ch == "\"") {
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
            
                if (ch == "(") {
                  state._indent.push("(");
                  // add virtual angel wings so that editor behaves...
                  // ...more sane incase of broken brackets
                  state._indent.push("{");
                  return null;
                }
            
                if (ch === "{") {
                  state._indent.push("{");
                  return null;
                }
            
                if (ch == ")")  {
                  state._indent.pop();
                  state._indent.pop();
                }
            
                if (ch === "}") {
                  state._indent.pop();
                  return null;
                }
            
                if (ch == ",")
                  return null;
            
                if (ch == ";")
                  return null;
            
            
                if (/[{}\(\),;]/.test(ch))
                  return null;
            
                // 1*DIGIT "K" / "M" / "G"
                if (/\d/.test(ch)) {
                  stream.eatWhile(/[\d]/);
                  stream.eat(/[KkMmGg]/);
                  return "number";
                }
            
                // ":" (ALPHA / "_") *(ALPHA / DIGIT / "_")
                if (ch == ":") {
                  stream.eatWhile(/[a-zA-Z_]/);
                  stream.eatWhile(/[a-zA-Z0-9_]/);
            
                  return "operator";
                }
            
                stream.eatWhile(/\w/);
                var cur = stream.current();
            
                // "text:" *(SP / HTAB) (hash-comment / CRLF)
                // *(multiline-literal / multiline-dotstart)
                // "." CRLF
                if ((cur == "text") && stream.eat(":"))
                {
                  state.tokenize = tokenMultiLineString;
                  return "string";
                }
            
                if (keywords.propertyIsEnumerable(cur))
                  return "keyword";
            
                if (atoms.propertyIsEnumerable(cur))
                  return "atom";
            
                return null;
              }
            
              function tokenMultiLineString(stream, state)
              {
                state._multiLineString = true;
                // the first line is special it may contain a comment
                if (!stream.sol()) {
                  stream.eatSpace();
            
                  if (stream.peek() == "#") {
                    stream.skipToEnd();
                    return "comment";
                  }
            
                  stream.skipToEnd();
                  return "string";
                }
            
                if ((stream.next() == ".")  && (stream.eol()))
                {
                  state._multiLineString = false;
                  state.tokenize = tokenBase;
                }
            
                return "string";
              }
            
              function tokenCComment(stream, state) {
                var maybeEnd = false, ch;
                while ((ch = stream.next()) != null) {
                  if (maybeEnd && ch == "/") {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped)
                      break;
                    escaped = !escaped && ch == "\\";
                  }
                  if (!escaped) state.tokenize = tokenBase;
                  return "string";
                };
              }
            
              return {
                startState: function(base) {
                  return {tokenize: tokenBase,
                          baseIndent: base || 0,
                          _indent: []};
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace())
                    return null;
            
                  return (state.tokenize || tokenBase)(stream, state);;
                },
            
                indent: function(state, _textAfter) {
                  var length = state._indent.length;
                  if (_textAfter && (_textAfter[0] == "}"))
                    length--;
            
                  if (length <0)
                    length = 0;
            
                  return length * indentUnit;
                },
            
                electricChars: "}"
              };
            });
            
            CodeMirror.defineMIME("application/sieve", "sieve");
            
            });
            
        • slim
          • index.html
            <!doctype html>
            
            <title>CodeMirror: SLIM mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/ambiance.css">
            <script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
            <script src="https://code.jquery.com/ui/1.11.0/jquery-ui.min.js"></script>
            <link rel="stylesheet" href="https://code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../htmlembedded/htmlembedded.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="../coffeescript/coffeescript.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../ruby/ruby.js"></script>
            <script src="../markdown/markdown.js"></script>
            <script src="slim.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">SLIM</a>
              </ul>
            </div>
            
            <article>
              <h2>SLIM mode</h2>
              <form><textarea id="code" name="code">
            body
              table
                - for user in users
                  td id="user_#{user.id}" class=user.role
                    a href=user_action(user, :edit) Edit #{user.name}
                    a href=(path_to_user user) = user.name
            body
              h1(id="logo") = page_logo
              h2[id="tagline" class="small tagline"] = page_tagline
            
            h2[id="tagline"
               class="small tagline"] = page_tagline
            
            h1 id = "logo" = page_logo
            h2 [ id = "tagline" ] = page_tagline
            
            / comment
              second line
            /! html comment
               second line
            <!-- html comment -->
            <a href="#{'hello' if set}">link</a>
            a.slim href="work" disabled=false running==:atom Text <b>bold</b>
            .clazz data-id="test" == 'hello' unless quark
             | Text mode #{12}
               Second line
            = x ||= :ruby_atom
            #menu.left
              - @env.each do |x|
                li: a = x
            *@dyntag attr="val"
            .first *{:class => [:second, :third]} Text
            .second class=["text","more"]
            .third class=:text,:symbol
            
              </textarea></form>
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  theme: "ambiance",
                  mode: "application/x-slim"
                });
                $('.CodeMirror').resizable({
                  resize: function() {
                    editor.setSize($(this).width(), $(this).height());
                    //editor.refresh();
                  }
                });
              </script>
            
              <p><strong>MIME types defined:</strong> <code>application/x-slim</code>.</p>
            
              <p>
                <strong>Parsing/Highlighting Tests:</strong>
                <a href="../../test/index.html#slim_*">normal</a>,
                <a href="../../test/index.html#verbose,slim_*">verbose</a>.
              </p>
            </article>
            
          • slim.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
              CodeMirror.defineMode("slim", function(config) {
                var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"});
                var rubyMode = CodeMirror.getMode(config, "ruby");
                var modes = { html: htmlMode, ruby: rubyMode };
                var embedded = {
                  ruby: "ruby",
                  javascript: "javascript",
                  css: "text/css",
                  sass: "text/x-sass",
                  scss: "text/x-scss",
                  less: "text/x-less",
                  styl: "text/x-styl", // no highlighting so far
                  coffee: "coffeescript",
                  asciidoc: "text/x-asciidoc",
                  markdown: "text/x-markdown",
                  textile: "text/x-textile", // no highlighting so far
                  creole: "text/x-creole", // no highlighting so far
                  wiki: "text/x-wiki", // no highlighting so far
                  mediawiki: "text/x-mediawiki", // no highlighting so far
                  rdoc: "text/x-rdoc", // no highlighting so far
                  builder: "text/x-builder", // no highlighting so far
                  nokogiri: "text/x-nokogiri", // no highlighting so far
                  erb: "application/x-erb"
                };
                var embeddedRegexp = function(map){
                  var arr = [];
                  for(var key in map) arr.push(key);
                  return new RegExp("^("+arr.join('|')+"):");
                }(embedded);
            
                var styleMap = {
                  "commentLine": "comment",
                  "slimSwitch": "operator special",
                  "slimTag": "tag",
                  "slimId": "attribute def",
                  "slimClass": "attribute qualifier",
                  "slimAttribute": "attribute",
                  "slimSubmode": "keyword special",
                  "closeAttributeTag": null,
                  "slimDoctype": null,
                  "lineContinuation": null
                };
                var closing = {
                  "{": "}",
                  "[": "]",
                  "(": ")"
                };
            
                var nameStartChar = "_a-zA-Z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD";
                var nameChar = nameStartChar + "\\-0-9\xB7\u0300-\u036F\u203F-\u2040";
                var nameRegexp = new RegExp("^[:"+nameStartChar+"](?::["+nameChar+"]|["+nameChar+"]*)");
                var attributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*(?=\\s*=)");
                var wrappedAttributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*");
                var classNameRegexp = /^\.-?[_a-zA-Z]+[\w\-]*/;
                var classIdRegexp = /^#[_a-zA-Z]+[\w\-]*/;
            
                function backup(pos, tokenize, style) {
                  var restore = function(stream, state) {
                    state.tokenize = tokenize;
                    if (stream.pos < pos) {
                      stream.pos = pos;
                      return style;
                    }
                    return state.tokenize(stream, state);
                  };
                  return function(stream, state) {
                    state.tokenize = restore;
                    return tokenize(stream, state);
                  };
                }
            
                function maybeBackup(stream, state, pat, offset, style) {
                  var cur = stream.current();
                  var idx = cur.search(pat);
                  if (idx > -1) {
                    state.tokenize = backup(stream.pos, state.tokenize, style);
                    stream.backUp(cur.length - idx - offset);
                  }
                  return style;
                }
            
                function continueLine(state, column) {
                  state.stack = {
                    parent: state.stack,
                    style: "continuation",
                    indented: column,
                    tokenize: state.line
                  };
                  state.line = state.tokenize;
                }
                function finishContinue(state) {
                  if (state.line == state.tokenize) {
                    state.line = state.stack.tokenize;
                    state.stack = state.stack.parent;
                  }
                }
            
                function lineContinuable(column, tokenize) {
                  return function(stream, state) {
                    finishContinue(state);
                    if (stream.match(/^\\$/)) {
                      continueLine(state, column);
                      return "lineContinuation";
                    }
                    var style = tokenize(stream, state);
                    if (stream.eol() && stream.current().match(/(?:^|[^\\])(?:\\\\)*\\$/)) {
                      stream.backUp(1);
                    }
                    return style;
                  };
                }
                function commaContinuable(column, tokenize) {
                  return function(stream, state) {
                    finishContinue(state);
                    var style = tokenize(stream, state);
                    if (stream.eol() && stream.current().match(/,$/)) {
                      continueLine(state, column);
                    }
                    return style;
                  };
                }
            
                function rubyInQuote(endQuote, tokenize) {
                  // TODO: add multi line support
                  return function(stream, state) {
                    var ch = stream.peek();
                    if (ch == endQuote && state.rubyState.tokenize.length == 1) {
                      // step out of ruby context as it seems to complete processing all the braces
                      stream.next();
                      state.tokenize = tokenize;
                      return "closeAttributeTag";
                    } else {
                      return ruby(stream, state);
                    }
                  };
                }
                function startRubySplat(tokenize) {
                  var rubyState;
                  var runSplat = function(stream, state) {
                    if (state.rubyState.tokenize.length == 1 && !state.rubyState.context.prev) {
                      stream.backUp(1);
                      if (stream.eatSpace()) {
                        state.rubyState = rubyState;
                        state.tokenize = tokenize;
                        return tokenize(stream, state);
                      }
                      stream.next();
                    }
                    return ruby(stream, state);
                  };
                  return function(stream, state) {
                    rubyState = state.rubyState;
                    state.rubyState = rubyMode.startState();
                    state.tokenize = runSplat;
                    return ruby(stream, state);
                  };
                }
            
                function ruby(stream, state) {
                  return rubyMode.token(stream, state.rubyState);
                }
            
                function htmlLine(stream, state) {
                  if (stream.match(/^\\$/)) {
                    return "lineContinuation";
                  }
                  return html(stream, state);
                }
                function html(stream, state) {
                  if (stream.match(/^#\{/)) {
                    state.tokenize = rubyInQuote("}", state.tokenize);
                    return null;
                  }
                  return maybeBackup(stream, state, /[^\\]#\{/, 1, htmlMode.token(stream, state.htmlState));
                }
            
                function startHtmlLine(lastTokenize) {
                  return function(stream, state) {
                    var style = htmlLine(stream, state);
                    if (stream.eol()) state.tokenize = lastTokenize;
                    return style;
                  };
                }
            
                function startHtmlMode(stream, state, offset) {
                  state.stack = {
                    parent: state.stack,
                    style: "html",
                    indented: stream.column() + offset, // pipe + space
                    tokenize: state.line
                  };
                  state.line = state.tokenize = html;
                  return null;
                }
            
                function comment(stream, state) {
                  stream.skipToEnd();
                  return state.stack.style;
                }
            
                function commentMode(stream, state) {
                  state.stack = {
                    parent: state.stack,
                    style: "comment",
                    indented: state.indented + 1,
                    tokenize: state.line
                  };
                  state.line = comment;
                  return comment(stream, state);
                }
            
                function attributeWrapper(stream, state) {
                  if (stream.eat(state.stack.endQuote)) {
                    state.line = state.stack.line;
                    state.tokenize = state.stack.tokenize;
                    state.stack = state.stack.parent;
                    return null;
                  }
                  if (stream.match(wrappedAttributeNameRegexp)) {
                    state.tokenize = attributeWrapperAssign;
                    return "slimAttribute";
                  }
                  stream.next();
                  return null;
                }
                function attributeWrapperAssign(stream, state) {
                  if (stream.match(/^==?/)) {
                    state.tokenize = attributeWrapperValue;
                    return null;
                  }
                  return attributeWrapper(stream, state);
                }
                function attributeWrapperValue(stream, state) {
                  var ch = stream.peek();
                  if (ch == '"' || ch == "\'") {
                    state.tokenize = readQuoted(ch, "string", true, false, attributeWrapper);
                    stream.next();
                    return state.tokenize(stream, state);
                  }
                  if (ch == '[') {
                    return startRubySplat(attributeWrapper)(stream, state);
                  }
                  if (stream.match(/^(true|false|nil)\b/)) {
                    state.tokenize = attributeWrapper;
                    return "keyword";
                  }
                  return startRubySplat(attributeWrapper)(stream, state);
                }
            
                function startAttributeWrapperMode(state, endQuote, tokenize) {
                  state.stack = {
                    parent: state.stack,
                    style: "wrapper",
                    indented: state.indented + 1,
                    tokenize: tokenize,
                    line: state.line,
                    endQuote: endQuote
                  };
                  state.line = state.tokenize = attributeWrapper;
                  return null;
                }
            
                function sub(stream, state) {
                  if (stream.match(/^#\{/)) {
                    state.tokenize = rubyInQuote("}", state.tokenize);
                    return null;
                  }
                  var subStream = new CodeMirror.StringStream(stream.string.slice(state.stack.indented), stream.tabSize);
                  subStream.pos = stream.pos - state.stack.indented;
                  subStream.start = stream.start - state.stack.indented;
                  subStream.lastColumnPos = stream.lastColumnPos - state.stack.indented;
                  subStream.lastColumnValue = stream.lastColumnValue - state.stack.indented;
                  var style = state.subMode.token(subStream, state.subState);
                  stream.pos = subStream.pos + state.stack.indented;
                  return style;
                }
                function firstSub(stream, state) {
                  state.stack.indented = stream.column();
                  state.line = state.tokenize = sub;
                  return state.tokenize(stream, state);
                }
            
                function createMode(mode) {
                  var query = embedded[mode];
                  var spec = CodeMirror.mimeModes[query];
                  if (spec) {
                    return CodeMirror.getMode(config, spec);
                  }
                  var factory = CodeMirror.modes[query];
                  if (factory) {
                    return factory(config, {name: query});
                  }
                  return CodeMirror.getMode(config, "null");
                }
            
                function getMode(mode) {
                  if (!modes.hasOwnProperty(mode)) {
                    return modes[mode] = createMode(mode);
                  }
                  return modes[mode];
                }
            
                function startSubMode(mode, state) {
                  var subMode = getMode(mode);
                  var subState = subMode.startState && subMode.startState();
            
                  state.subMode = subMode;
                  state.subState = subState;
            
                  state.stack = {
                    parent: state.stack,
                    style: "sub",
                    indented: state.indented + 1,
                    tokenize: state.line
                  };
                  state.line = state.tokenize = firstSub;
                  return "slimSubmode";
                }
            
                function doctypeLine(stream, _state) {
                  stream.skipToEnd();
                  return "slimDoctype";
                }
            
                function startLine(stream, state) {
                  var ch = stream.peek();
                  if (ch == '<') {
                    return (state.tokenize = startHtmlLine(state.tokenize))(stream, state);
                  }
                  if (stream.match(/^[|']/)) {
                    return startHtmlMode(stream, state, 1);
                  }
                  if (stream.match(/^\/(!|\[\w+])?/)) {
                    return commentMode(stream, state);
                  }
                  if (stream.match(/^(-|==?[<>]?)/)) {
                    state.tokenize = lineContinuable(stream.column(), commaContinuable(stream.column(), ruby));
                    return "slimSwitch";
                  }
                  if (stream.match(/^doctype\b/)) {
                    state.tokenize = doctypeLine;
                    return "keyword";
                  }
            
                  var m = stream.match(embeddedRegexp);
                  if (m) {
                    return startSubMode(m[1], state);
                  }
            
                  return slimTag(stream, state);
                }
            
                function slim(stream, state) {
                  if (state.startOfLine) {
                    return startLine(stream, state);
                  }
                  return slimTag(stream, state);
                }
            
                function slimTag(stream, state) {
                  if (stream.eat('*')) {
                    state.tokenize = startRubySplat(slimTagExtras);
                    return null;
                  }
                  if (stream.match(nameRegexp)) {
                    state.tokenize = slimTagExtras;
                    return "slimTag";
                  }
                  return slimClass(stream, state);
                }
                function slimTagExtras(stream, state) {
                  if (stream.match(/^(<>?|><?)/)) {
                    state.tokenize = slimClass;
                    return null;
                  }
                  return slimClass(stream, state);
                }
                function slimClass(stream, state) {
                  if (stream.match(classIdRegexp)) {
                    state.tokenize = slimClass;
                    return "slimId";
                  }
                  if (stream.match(classNameRegexp)) {
                    state.tokenize = slimClass;
                    return "slimClass";
                  }
                  return slimAttribute(stream, state);
                }
                function slimAttribute(stream, state) {
                  if (stream.match(/^([\[\{\(])/)) {
                    return startAttributeWrapperMode(state, closing[RegExp.$1], slimAttribute);
                  }
                  if (stream.match(attributeNameRegexp)) {
                    state.tokenize = slimAttributeAssign;
                    return "slimAttribute";
                  }
                  if (stream.peek() == '*') {
                    stream.next();
                    state.tokenize = startRubySplat(slimContent);
                    return null;
                  }
                  return slimContent(stream, state);
                }
                function slimAttributeAssign(stream, state) {
                  if (stream.match(/^==?/)) {
                    state.tokenize = slimAttributeValue;
                    return null;
                  }
                  // should never happen, because of forward lookup
                  return slimAttribute(stream, state);
                }
            
                function slimAttributeValue(stream, state) {
                  var ch = stream.peek();
                  if (ch == '"' || ch == "\'") {
                    state.tokenize = readQuoted(ch, "string", true, false, slimAttribute);
                    stream.next();
                    return state.tokenize(stream, state);
                  }
                  if (ch == '[') {
                    return startRubySplat(slimAttribute)(stream, state);
                  }
                  if (ch == ':') {
                    return startRubySplat(slimAttributeSymbols)(stream, state);
                  }
                  if (stream.match(/^(true|false|nil)\b/)) {
                    state.tokenize = slimAttribute;
                    return "keyword";
                  }
                  return startRubySplat(slimAttribute)(stream, state);
                }
                function slimAttributeSymbols(stream, state) {
                  stream.backUp(1);
                  if (stream.match(/^[^\s],(?=:)/)) {
                    state.tokenize = startRubySplat(slimAttributeSymbols);
                    return null;
                  }
                  stream.next();
                  return slimAttribute(stream, state);
                }
                function readQuoted(quote, style, embed, unescaped, nextTokenize) {
                  return function(stream, state) {
                    finishContinue(state);
                    var fresh = stream.current().length == 0;
                    if (stream.match(/^\\$/, fresh)) {
                      if (!fresh) return style;
                      continueLine(state, state.indented);
                      return "lineContinuation";
                    }
                    if (stream.match(/^#\{/, fresh)) {
                      if (!fresh) return style;
                      state.tokenize = rubyInQuote("}", state.tokenize);
                      return null;
                    }
                    var escaped = false, ch;
                    while ((ch = stream.next()) != null) {
                      if (ch == quote && (unescaped || !escaped)) {
                        state.tokenize = nextTokenize;
                        break;
                      }
                      if (embed && ch == "#" && !escaped) {
                        if (stream.eat("{")) {
                          stream.backUp(2);
                          break;
                        }
                      }
                      escaped = !escaped && ch == "\\";
                    }
                    if (stream.eol() && escaped) {
                      stream.backUp(1);
                    }
                    return style;
                  };
                }
                function slimContent(stream, state) {
                  if (stream.match(/^==?/)) {
                    state.tokenize = ruby;
                    return "slimSwitch";
                  }
                  if (stream.match(/^\/$/)) { // tag close hint
                    state.tokenize = slim;
                    return null;
                  }
                  if (stream.match(/^:/)) { // inline tag
                    state.tokenize = slimTag;
                    return "slimSwitch";
                  }
                  startHtmlMode(stream, state, 0);
                  return state.tokenize(stream, state);
                }
            
                var mode = {
                  // default to html mode
                  startState: function() {
                    var htmlState = htmlMode.startState();
                    var rubyState = rubyMode.startState();
                    return {
                      htmlState: htmlState,
                      rubyState: rubyState,
                      stack: null,
                      last: null,
                      tokenize: slim,
                      line: slim,
                      indented: 0
                    };
                  },
            
                  copyState: function(state) {
                    return {
                      htmlState : CodeMirror.copyState(htmlMode, state.htmlState),
                      rubyState: CodeMirror.copyState(rubyMode, state.rubyState),
                      subMode: state.subMode,
                      subState: state.subMode && CodeMirror.copyState(state.subMode, state.subState),
                      stack: state.stack,
                      last: state.last,
                      tokenize: state.tokenize,
                      line: state.line
                    };
                  },
            
                  token: function(stream, state) {
                    if (stream.sol()) {
                      state.indented = stream.indentation();
                      state.startOfLine = true;
                      state.tokenize = state.line;
                      while (state.stack && state.stack.indented > state.indented && state.last != "slimSubmode") {
                        state.line = state.tokenize = state.stack.tokenize;
                        state.stack = state.stack.parent;
                        state.subMode = null;
                        state.subState = null;
                      }
                    }
                    if (stream.eatSpace()) return null;
                    var style = state.tokenize(stream, state);
                    state.startOfLine = false;
                    if (style) state.last = style;
                    return styleMap.hasOwnProperty(style) ? styleMap[style] : style;
                  },
            
                  blankLine: function(state) {
                    if (state.subMode && state.subMode.blankLine) {
                      return state.subMode.blankLine(state.subState);
                    }
                  },
            
                  innerMode: function(state) {
                    if (state.subMode) return {state: state.subState, mode: state.subMode};
                    return {state: state, mode: mode};
                  }
            
                  //indent: function(state) {
                  //  return state.indented;
                  //}
                };
                return mode;
              }, "htmlmixed", "ruby");
            
              CodeMirror.defineMIME("text/x-slim", "slim");
              CodeMirror.defineMIME("application/x-slim", "slim");
            });
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "slim");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              // Requires at least one media query
              MT("elementName",
                 "[tag h1] Hey There");
            
              MT("oneElementPerLine",
                 "[tag h1] Hey There .h2");
            
              MT("idShortcut",
                 "[attribute&def #test] Hey There");
            
              MT("tagWithIdShortcuts",
                 "[tag h1][attribute&def #test] Hey There");
            
              MT("classShortcut",
                 "[attribute&qualifier .hello] Hey There");
            
              MT("tagWithIdAndClassShortcuts",
                 "[tag h1][attribute&def #test][attribute&qualifier .hello] Hey There");
            
              MT("docType",
                 "[keyword doctype] xml");
            
              MT("comment",
                 "[comment / Hello WORLD]");
            
              MT("notComment",
                 "[tag h1] This is not a / comment ");
            
              MT("attributes",
                 "[tag a]([attribute title]=[string \"test\"]) [attribute href]=[string \"link\"]}");
            
              MT("multiLineAttributes",
                 "[tag a]([attribute title]=[string \"test\"]",
                 "  ) [attribute href]=[string \"link\"]}");
            
              MT("htmlCode",
                 "[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket </][tag h1][tag&bracket >]");
            
              MT("rubyBlock",
                 "[operator&special =][variable-2 @item]");
            
              MT("selectorRubyBlock",
                 "[tag a][attribute&qualifier .test][operator&special =] [variable-2 @item]");
            
              MT("nestedRubyBlock",
                  "[tag a]",
                  "  [operator&special =][variable puts] [string \"test\"]");
            
              MT("multilinePlaintext",
                  "[tag p]",
                  "  | Hello,",
                  "    World");
            
              MT("multilineRuby",
                  "[tag p]",
                  "  [comment /# this is a comment]",
                  "     [comment and this is a comment too]",
                  "  | Date/Time",
                  "  [operator&special -] [variable now] [operator =] [tag DateTime][operator .][property now]",
                  "  [tag strong][operator&special =] [variable now]",
                  "  [operator&special -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \"December 31, 2006\"])",
                  "     [operator&special =][string \"Happy\"]",
                  "     [operator&special =][string \"Belated\"]",
                  "     [operator&special =][string \"Birthday\"]");
            
              MT("multilineComment",
                  "[comment /]",
                  "  [comment Multiline]",
                  "  [comment Comment]");
            
              MT("hamlAfterRubyTag",
                "[attribute&qualifier .block]",
                "  [tag strong][operator&special =] [variable now]",
                "  [attribute&qualifier .test]",
                "     [operator&special =][variable now]",
                "  [attribute&qualifier .right]");
            
              MT("stretchedRuby",
                 "[operator&special =] [variable puts] [string \"Hello\"],",
                 "   [string \"World\"]");
            
              MT("interpolationInHashAttribute",
                 "[tag div]{[attribute id] = [string \"]#{[variable test]}[string _]#{[variable ting]}[string \"]} test");
            
              MT("interpolationInHTMLAttribute",
                 "[tag div]([attribute title]=[string \"]#{[variable test]}[string _]#{[variable ting]()}[string \"]) Test");
            })();
            
        • smalltalk
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Smalltalk mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="smalltalk.js"></script>
            <style>
                  .CodeMirror {border: 2px solid #dee; border-right-width: 10px;}
                  .CodeMirror-gutter {border: none; background: #dee;}
                  .CodeMirror-gutter pre {color: white; font-weight: bold;}
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Smalltalk</a>
              </ul>
            </div>
            
            <article>
            <h2>Smalltalk mode</h2>
            <form><textarea id="code" name="code">
            " 
                This is a test of the Smalltalk code
            "
            Seaside.WAComponent subclass: #MyCounter [
                | count |
                MyCounter class &gt;&gt; canBeRoot [ ^true ]
            
                initialize [
                    super initialize.
                    count := 0.
                ]
                states [ ^{ self } ]
                renderContentOn: html [
                    html heading: count.
                    html anchor callback: [ count := count + 1 ]; with: '++'.
                    html space.
                    html anchor callback: [ count := count - 1 ]; with: '--'.
                ]
            ]
            
            MyCounter registerAsApplication: 'mycounter'
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-stsrc",
                    indentUnit: 4
                  });
                </script>
            
                <p>Simple Smalltalk mode.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-stsrc</code>.</p>
              </article>
            
          • smalltalk.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('smalltalk', function(config) {
            
              var specialChars = /[+\-\/\\*~<>=@%|&?!.,:;^]/;
              var keywords = /true|false|nil|self|super|thisContext/;
            
              var Context = function(tokenizer, parent) {
                this.next = tokenizer;
                this.parent = parent;
              };
            
              var Token = function(name, context, eos) {
                this.name = name;
                this.context = context;
                this.eos = eos;
              };
            
              var State = function() {
                this.context = new Context(next, null);
                this.expectVariable = true;
                this.indentation = 0;
                this.userIndentationDelta = 0;
              };
            
              State.prototype.userIndent = function(indentation) {
                this.userIndentationDelta = indentation > 0 ? (indentation / config.indentUnit - this.indentation) : 0;
              };
            
              var next = function(stream, context, state) {
                var token = new Token(null, context, false);
                var aChar = stream.next();
            
                if (aChar === '"') {
                  token = nextComment(stream, new Context(nextComment, context));
            
                } else if (aChar === '\'') {
                  token = nextString(stream, new Context(nextString, context));
            
                } else if (aChar === '#') {
                  if (stream.peek() === '\'') {
                    stream.next();
                    token = nextSymbol(stream, new Context(nextSymbol, context));
                  } else {
                    if (stream.eatWhile(/[^\s.{}\[\]()]/))
                      token.name = 'string-2';
                    else
                      token.name = 'meta';
                  }
            
                } else if (aChar === '$') {
                  if (stream.next() === '<') {
                    stream.eatWhile(/[^\s>]/);
                    stream.next();
                  }
                  token.name = 'string-2';
            
                } else if (aChar === '|' && state.expectVariable) {
                  token.context = new Context(nextTemporaries, context);
            
                } else if (/[\[\]{}()]/.test(aChar)) {
                  token.name = 'bracket';
                  token.eos = /[\[{(]/.test(aChar);
            
                  if (aChar === '[') {
                    state.indentation++;
                  } else if (aChar === ']') {
                    state.indentation = Math.max(0, state.indentation - 1);
                  }
            
                } else if (specialChars.test(aChar)) {
                  stream.eatWhile(specialChars);
                  token.name = 'operator';
                  token.eos = aChar !== ';'; // ; cascaded message expression
            
                } else if (/\d/.test(aChar)) {
                  stream.eatWhile(/[\w\d]/);
                  token.name = 'number';
            
                } else if (/[\w_]/.test(aChar)) {
                  stream.eatWhile(/[\w\d_]/);
                  token.name = state.expectVariable ? (keywords.test(stream.current()) ? 'keyword' : 'variable') : null;
            
                } else {
                  token.eos = state.expectVariable;
                }
            
                return token;
              };
            
              var nextComment = function(stream, context) {
                stream.eatWhile(/[^"]/);
                return new Token('comment', stream.eat('"') ? context.parent : context, true);
              };
            
              var nextString = function(stream, context) {
                stream.eatWhile(/[^']/);
                return new Token('string', stream.eat('\'') ? context.parent : context, false);
              };
            
              var nextSymbol = function(stream, context) {
                stream.eatWhile(/[^']/);
                return new Token('string-2', stream.eat('\'') ? context.parent : context, false);
              };
            
              var nextTemporaries = function(stream, context) {
                var token = new Token(null, context, false);
                var aChar = stream.next();
            
                if (aChar === '|') {
                  token.context = context.parent;
                  token.eos = true;
            
                } else {
                  stream.eatWhile(/[^|]/);
                  token.name = 'variable';
                }
            
                return token;
              };
            
              return {
                startState: function() {
                  return new State;
                },
            
                token: function(stream, state) {
                  state.userIndent(stream.indentation());
            
                  if (stream.eatSpace()) {
                    return null;
                  }
            
                  var token = state.context.next(stream, state.context, state);
                  state.context = token.context;
                  state.expectVariable = token.eos;
            
                  return token.name;
                },
            
                blankLine: function(state) {
                  state.userIndent(0);
                },
            
                indent: function(state, textAfter) {
                  var i = state.context.next === next && textAfter && textAfter.charAt(0) === ']' ? -1 : state.userIndentationDelta;
                  return (state.indentation + i) * config.indentUnit;
                },
            
                electricChars: ']'
              };
            
            });
            
            CodeMirror.defineMIME('text/x-stsrc', {name: 'smalltalk'});
            
            });
            
        • smarty
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Smarty mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="smarty.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Smarty</a>
              </ul>
            </div>
            
            <article>
            <h2>Smarty mode</h2>
            <form><textarea id="code" name="code">
            {extends file="parent.tpl"}
            {include file="template.tpl"}
            
            {* some example Smarty content *}
            {if isset($name) && $name == 'Blog'}
              This is a {$var}.
              {$integer = 451}, {$array[] = "a"}, {$stringvar = "string"}
              {assign var='bob' value=$var.prop}
            {elseif $name == $foo}
              {function name=menu level=0}
                {foreach $data as $entry}
                  {if is_array($entry)}
                    - {$entry@key}
                    {menu data=$entry level=$level+1}
                  {else}
                    {$entry}
                  {/if}
                {/foreach}
              {/function}
            {/if}</textarea></form>
            
            <p>Mode for Smarty version 2 or 3, which allows for custom delimiter tags.</p>
            
            <p>Several configuration parameters are supported:</p>
            
            <ul>
              <li><code>leftDelimiter</code> and <code>rightDelimiter</code>,
              which should be strings that determine where the Smarty syntax
              starts and ends.</li>
              <li><code>version</code>, which should be 2 or 3.</li>
              <li><code>baseMode</code>, which can be a mode spec
              like <code>"text/html"</code> to set a different background mode.</li>
            </ul>
            
            <p><strong>MIME types defined:</strong> <code>text/x-smarty</code></p>
            
            <h3>Smarty 2, custom delimiters</h3>
            
            <form><textarea id="code2" name="code2">
            {--extends file="parent.tpl"--}
            {--include file="template.tpl"--}
            
            {--* some example Smarty content *--}
            {--if isset($name) && $name == 'Blog'--}
              This is a {--$var--}.
              {--$integer = 451--}, {--$array[] = "a"--}, {--$stringvar = "string"--}
              {--assign var='bob' value=$var.prop--}
            {--elseif $name == $foo--}
              {--function name=menu level=0--}
                {--foreach $data as $entry--}
                  {--if is_array($entry)--}
                    - {--$entry@key--}
                    {--menu data=$entry level=$level+1--}
                  {--else--}
                    {--$entry--}
                  {--/if--}
                {--/foreach--}
              {--/function--}
            {--/if--}</textarea></form>
            
            <h3>Smarty 3</h3>
            
            <textarea id="code3" name="code3">
            Nested tags {$foo={counter one=1 two={inception}}+3} are now valid in Smarty 3.
            
            <script>
            function test() {
              console.log("Smarty 3 permits single curly braces followed by whitespace to NOT slip into Smarty mode.");
            }
            </script>
            
            {assign var=foo value=[1,2,3]}
            {assign var=foo value=['y'=>'yellow','b'=>'blue']}
            {assign var=foo value=[1,[9,8],3]}
            
            {$foo=$bar+2} {* a comment *}
            {$foo.bar=1}  {* another comment *}
            {$foo = myfunct(($x+$y)*3)}
            {$foo = strlen($bar)}
            {$foo.bar.baz=1}, {$foo[]=1}
            
            Smarty "dot" syntax (note: embedded {} are used to address ambiguities):
            
            {$foo.a.b.c}      => $foo['a']['b']['c']
            {$foo.a.$b.c}     => $foo['a'][$b]['c']
            {$foo.a.{$b+4}.c} => $foo['a'][$b+4]['c']
            {$foo.a.{$b.c}}   => $foo['a'][$b['c']]
            
            {$object->method1($x)->method2($y)}</textarea>
            
            <script>
            var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
              lineNumbers: true,
              mode: "smarty"
            });
            var editor = CodeMirror.fromTextArea(document.getElementById("code2"), {
              lineNumbers: true,
              mode: {
                name: "smarty",
                leftDelimiter: "{--",
                rightDelimiter: "--}"
              }
            });
            var editor = CodeMirror.fromTextArea(document.getElementById("code3"), {
              lineNumbers: true,
              mode: {name: "smarty", version: 3, baseMode: "text/html"}
            });
            </script>
            
            </article>
            
          • smarty.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /**
             * Smarty 2 and 3 mode.
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("smarty", function(config, parserConf) {
                var rightDelimiter = parserConf.rightDelimiter || "}";
                var leftDelimiter = parserConf.leftDelimiter || "{";
                var version = parserConf.version || 2;
                var baseMode = CodeMirror.getMode(config, parserConf.baseMode || "null");
            
                var keyFunctions = ["debug", "extends", "function", "include", "literal"];
                var regs = {
                  operatorChars: /[+\-*&%=<>!?]/,
                  validIdentifier: /[a-zA-Z0-9_]/,
                  stringChar: /['"]/
                };
            
                var last;
                function cont(style, lastType) {
                  last = lastType;
                  return style;
                }
            
                function chain(stream, state, parser) {
                  state.tokenize = parser;
                  return parser(stream, state);
                }
            
                // Smarty 3 allows { and } surrounded by whitespace to NOT slip into Smarty mode
                function doesNotCount(stream, pos) {
                  if (pos == null) pos = stream.pos;
                  return version === 3 && leftDelimiter == "{" &&
                    (pos == stream.string.length || /\s/.test(stream.string.charAt(pos)));
                }
            
                function tokenTop(stream, state) {
                  var string = stream.string;
                  for (var scan = stream.pos;;) {
                    var nextMatch = string.indexOf(leftDelimiter, scan);
                    scan = nextMatch + leftDelimiter.length;
                    if (nextMatch == -1 || !doesNotCount(stream, nextMatch + leftDelimiter.length)) break;
                  }
                  if (nextMatch == stream.pos) {
                    stream.match(leftDelimiter);
                    if (stream.eat("*")) {
                      return chain(stream, state, tokenBlock("comment", "*" + rightDelimiter));
                    } else {
                      state.depth++;
                      state.tokenize = tokenSmarty;
                      last = "startTag";
                      return "tag";
                    }
                  }
            
                  if (nextMatch > -1) stream.string = string.slice(0, nextMatch);
                  var token = baseMode.token(stream, state.base);
                  if (nextMatch > -1) stream.string = string;
                  return token;
                }
            
                // parsing Smarty content
                function tokenSmarty(stream, state) {
                  if (stream.match(rightDelimiter, true)) {
                    if (version === 3) {
                      state.depth--;
                      if (state.depth <= 0) {
                        state.tokenize = tokenTop;
                      }
                    } else {
                      state.tokenize = tokenTop;
                    }
                    return cont("tag", null);
                  }
            
                  if (stream.match(leftDelimiter, true)) {
                    state.depth++;
                    return cont("tag", "startTag");
                  }
            
                  var ch = stream.next();
                  if (ch == "$") {
                    stream.eatWhile(regs.validIdentifier);
                    return cont("variable-2", "variable");
                  } else if (ch == "|") {
                    return cont("operator", "pipe");
                  } else if (ch == ".") {
                    return cont("operator", "property");
                  } else if (regs.stringChar.test(ch)) {
                    state.tokenize = tokenAttribute(ch);
                    return cont("string", "string");
                  } else if (regs.operatorChars.test(ch)) {
                    stream.eatWhile(regs.operatorChars);
                    return cont("operator", "operator");
                  } else if (ch == "[" || ch == "]") {
                    return cont("bracket", "bracket");
                  } else if (ch == "(" || ch == ")") {
                    return cont("bracket", "operator");
                  } else if (/\d/.test(ch)) {
                    stream.eatWhile(/\d/);
                    return cont("number", "number");
                  } else {
            
                    if (state.last == "variable") {
                      if (ch == "@") {
                        stream.eatWhile(regs.validIdentifier);
                        return cont("property", "property");
                      } else if (ch == "|") {
                        stream.eatWhile(regs.validIdentifier);
                        return cont("qualifier", "modifier");
                      }
                    } else if (state.last == "pipe") {
                      stream.eatWhile(regs.validIdentifier);
                      return cont("qualifier", "modifier");
                    } else if (state.last == "whitespace") {
                      stream.eatWhile(regs.validIdentifier);
                      return cont("attribute", "modifier");
                    } if (state.last == "property") {
                      stream.eatWhile(regs.validIdentifier);
                      return cont("property", null);
                    } else if (/\s/.test(ch)) {
                      last = "whitespace";
                      return null;
                    }
            
                    var str = "";
                    if (ch != "/") {
                      str += ch;
                    }
                    var c = null;
                    while (c = stream.eat(regs.validIdentifier)) {
                      str += c;
                    }
                    for (var i=0, j=keyFunctions.length; i<j; i++) {
                      if (keyFunctions[i] == str) {
                        return cont("keyword", "keyword");
                      }
                    }
                    if (/\s/.test(ch)) {
                      return null;
                    }
                    return cont("tag", "tag");
                  }
                }
            
                function tokenAttribute(quote) {
                  return function(stream, state) {
                    var prevChar = null;
                    var currChar = null;
                    while (!stream.eol()) {
                      currChar = stream.peek();
                      if (stream.next() == quote && prevChar !== '\\') {
                        state.tokenize = tokenSmarty;
                        break;
                      }
                      prevChar = currChar;
                    }
                    return "string";
                  };
                }
            
                function tokenBlock(style, terminator) {
                  return function(stream, state) {
                    while (!stream.eol()) {
                      if (stream.match(terminator)) {
                        state.tokenize = tokenTop;
                        break;
                      }
                      stream.next();
                    }
                    return style;
                  };
                }
            
                return {
                  startState: function() {
                    return {
                      base: CodeMirror.startState(baseMode),
                      tokenize: tokenTop,
                      last: null,
                      depth: 0
                    };
                  },
                  copyState: function(state) {
                    return {
                      base: CodeMirror.copyState(baseMode, state.base),
                      tokenize: state.tokenize,
                      last: state.last,
                      depth: state.depth
                    };
                  },
                  innerMode: function(state) {
                    if (state.tokenize == tokenTop)
                      return {mode: baseMode, state: state.base};
                  },
                  token: function(stream, state) {
                    var style = state.tokenize(stream, state);
                    state.last = last;
                    return style;
                  },
                  indent: function(state, text) {
                    if (state.tokenize == tokenTop && baseMode.indent)
                      return baseMode.indent(state.base, text);
                    else
                      return CodeMirror.Pass;
                  },
                  blockCommentStart: leftDelimiter + "*",
                  blockCommentEnd: "*" + rightDelimiter
                };
              });
            
              CodeMirror.defineMIME("text/x-smarty", "smarty");
            });
            
        • solr
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Solr mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="solr.js"></script>
            <style type="text/css">
              .CodeMirror {
                border-top: 1px solid black;
                border-bottom: 1px solid black;
              }
            
              .CodeMirror .cm-operator {
                color: orange;
              }
            </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Solr</a>
              </ul>
            </div>
            
            <article>
              <h2>Solr mode</h2>
            
              <div>
                <textarea id="code" name="code">author:Camus
            
            title:"The Rebel" and author:Camus
            
            philosophy:Existentialism -author:Kierkegaard
            
            hardToSpell:Dostoevsky~
            
            published:[194* TO 1960] and author:(Sartre or "Simone de Beauvoir")</textarea>
              </div>
            
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  mode: 'solr',
                  lineNumbers: true
                });
              </script>
            
              <p><strong>MIME types defined:</strong> <code>text/x-solr</code>.</p>
            </article>
            
          • solr.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("solr", function() {
              "use strict";
            
              var isStringChar = /[^\s\|\!\+\-\*\?\~\^\&\:\(\)\[\]\{\}\^\"\\]/;
              var isOperatorChar = /[\|\!\+\-\*\?\~\^\&]/;
              var isOperatorString = /^(OR|AND|NOT|TO)$/i;
            
              function isNumber(word) {
                return parseFloat(word, 10).toString() === word;
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) break;
                    escaped = !escaped && next == "\\";
                  }
            
                  if (!escaped) state.tokenize = tokenBase;
                  return "string";
                };
              }
            
              function tokenOperator(operator) {
                return function(stream, state) {
                  var style = "operator";
                  if (operator == "+")
                    style += " positive";
                  else if (operator == "-")
                    style += " negative";
                  else if (operator == "|")
                    stream.eat(/\|/);
                  else if (operator == "&")
                    stream.eat(/\&/);
                  else if (operator == "^")
                    style += " boost";
            
                  state.tokenize = tokenBase;
                  return style;
                };
              }
            
              function tokenWord(ch) {
                return function(stream, state) {
                  var word = ch;
                  while ((ch = stream.peek()) && ch.match(isStringChar) != null) {
                    word += stream.next();
                  }
            
                  state.tokenize = tokenBase;
                  if (isOperatorString.test(word))
                    return "operator";
                  else if (isNumber(word))
                    return "number";
                  else if (stream.peek() == ":")
                    return "field";
                  else
                    return "string";
                };
              }
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                if (ch == '"')
                  state.tokenize = tokenString(ch);
                else if (isOperatorChar.test(ch))
                  state.tokenize = tokenOperator(ch);
                else if (isStringChar.test(ch))
                  state.tokenize = tokenWord(ch);
            
                return (state.tokenize != tokenBase) ? state.tokenize(stream, state) : null;
              }
            
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase
                  };
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  return state.tokenize(stream, state);
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-solr", "solr");
            
            });
            
        • soy
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Soy (Closure Template) mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../javascript/javascript.js"></script>
            <script src="../css/css.js"></script>
            <script src="soy.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Soy (Closure Template)</a>
              </ul>
            </div>
            
            <article>
            <h2>Soy (Closure Template) mode</h2>
            <form><textarea id="code" name="code">
            {namespace example}
            
            /**
             * Says hello to the world.
             */
            {template .helloWorld}
              {@param name: string}
              {@param? score: number}
              Hello <b>{$name}</b>!
              <div>
                {if $score}
                  <em>{$score} points</em>
                {else}
                  no score
                {/if}
              </div>
            {/template}
            
            {template .alertHelloWorld kind="js"}
              alert('Hello World');
            {/template}
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-soy",
                    indentUnit: 2,
                    indentWithTabs: false
                  });
                </script>
            
                <p>A mode for <a href="https://developers.google.com/closure/templates/">Closure Templates</a> (Soy).</p>
                <p><strong>MIME type defined:</strong> <code>text/x-soy</code>.</p>
              </article>
            
          • soy.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              var indentingTags = ["template", "literal", "msg", "fallbackmsg", "let", "if", "elseif",
                                   "else", "switch", "case", "default", "foreach", "ifempty", "for",
                                   "call", "param", "deltemplate", "delcall", "log"];
            
              CodeMirror.defineMode("soy", function(config) {
                var textMode = CodeMirror.getMode(config, "text/plain");
                var modes = {
                  html: CodeMirror.getMode(config, {name: "text/html", multilineTagIndentFactor: 2, multilineTagIndentPastTag: false}),
                  attributes: textMode,
                  text: textMode,
                  uri: textMode,
                  css: CodeMirror.getMode(config, "text/css"),
                  js: CodeMirror.getMode(config, {name: "text/javascript", statementIndent: 2 * config.indentUnit})
                };
            
                function last(array) {
                  return array[array.length - 1];
                }
            
                function tokenUntil(stream, state, untilRegExp) {
                  var oldString = stream.string;
                  var match = untilRegExp.exec(oldString.substr(stream.pos));
                  if (match) {
                    // We don't use backUp because it backs up just the position, not the state.
                    // This uses an undocumented API.
                    stream.string = oldString.substr(0, stream.pos + match.index);
                  }
                  var result = stream.hideFirstChars(state.indent, function() {
                    return state.localMode.token(stream, state.localState);
                  });
                  stream.string = oldString;
                  return result;
                }
            
                return {
                  startState: function() {
                    return {
                      kind: [],
                      kindTag: [],
                      soyState: [],
                      indent: 0,
                      localMode: modes.html,
                      localState: CodeMirror.startState(modes.html)
                    };
                  },
            
                  copyState: function(state) {
                    return {
                      tag: state.tag, // Last seen Soy tag.
                      kind: state.kind.concat([]), // Values of kind="" attributes.
                      kindTag: state.kindTag.concat([]), // Opened tags with kind="" attributes.
                      soyState: state.soyState.concat([]),
                      indent: state.indent, // Indentation of the following line.
                      localMode: state.localMode,
                      localState: CodeMirror.copyState(state.localMode, state.localState)
                    };
                  },
            
                  token: function(stream, state) {
                    var match;
            
                    switch (last(state.soyState)) {
                      case "comment":
                        if (stream.match(/^.*?\*\//)) {
                          state.soyState.pop();
                        } else {
                          stream.skipToEnd();
                        }
                        return "comment";
            
                      case "variable":
                        if (stream.match(/^}/)) {
                          state.indent -= 2 * config.indentUnit;
                          state.soyState.pop();
                          return "variable-2";
                        }
                        stream.next();
                        return null;
            
                      case "tag":
                        if (stream.match(/^\/?}/)) {
                          if (state.tag == "/template" || state.tag == "/deltemplate") state.indent = 0;
                          else state.indent -= (stream.current() == "/}" || indentingTags.indexOf(state.tag) == -1 ? 2 : 1) * config.indentUnit;
                          state.soyState.pop();
                          return "keyword";
                        } else if (stream.match(/^([\w?]+)(?==)/)) {
                          if (stream.current() == "kind" && (match = stream.match(/^="([^"]+)/, false))) {
                            var kind = match[1];
                            state.kind.push(kind);
                            state.kindTag.push(state.tag);
                            state.localMode = modes[kind] || modes.html;
                            state.localState = CodeMirror.startState(state.localMode);
                          }
                          return "attribute";
                        } else if (stream.match(/^"/)) {
                          state.soyState.push("string");
                          return "string";
                        }
                        stream.next();
                        return null;
            
                      case "literal":
                        if (stream.match(/^(?=\{\/literal})/)) {
                          state.indent -= config.indentUnit;
                          state.soyState.pop();
                          return this.token(stream, state);
                        }
                        return tokenUntil(stream, state, /\{\/literal}/);
            
                      case "string":
                        if (stream.match(/^.*?"/)) {
                          state.soyState.pop();
                        } else {
                          stream.skipToEnd();
                        }
                        return "string";
                    }
            
                    if (stream.match(/^\/\*/)) {
                      state.soyState.push("comment");
                      return "comment";
                    } else if (stream.match(stream.sol() ? /^\s*\/\/.*/ : /^\s+\/\/.*/)) {
                      return "comment";
                    } else if (stream.match(/^\{\$[\w?]*/)) {
                      state.indent += 2 * config.indentUnit;
                      state.soyState.push("variable");
                      return "variable-2";
                    } else if (stream.match(/^\{literal}/)) {
                      state.indent += config.indentUnit;
                      state.soyState.push("literal");
                      return "keyword";
                    } else if (match = stream.match(/^\{([\/@\\]?[\w?]*)/)) {
                      if (match[1] != "/switch")
                        state.indent += (/^(\/|(else|elseif|case|default)$)/.test(match[1]) && state.tag != "switch" ? 1 : 2) * config.indentUnit;
                      state.tag = match[1];
                      if (state.tag == "/" + last(state.kindTag)) {
                        // We found the tag that opened the current kind="".
                        state.kind.pop();
                        state.kindTag.pop();
                        state.localMode = modes[last(state.kind)] || modes.html;
                        state.localState = CodeMirror.startState(state.localMode);
                      }
                      state.soyState.push("tag");
                      return "keyword";
                    }
            
                    return tokenUntil(stream, state, /\{|\s+\/\/|\/\*/);
                  },
            
                  indent: function(state, textAfter) {
                    var indent = state.indent, top = last(state.soyState);
                    if (top == "comment") return CodeMirror.Pass;
            
                    if (top == "literal") {
                      if (/^\{\/literal}/.test(textAfter)) indent -= config.indentUnit;
                    } else {
                      if (/^\s*\{\/(template|deltemplate)\b/.test(textAfter)) return 0;
                      if (/^\{(\/|(fallbackmsg|elseif|else|ifempty)\b)/.test(textAfter)) indent -= config.indentUnit;
                      if (state.tag != "switch" && /^\{(case|default)\b/.test(textAfter)) indent -= config.indentUnit;
                      if (/^\{\/switch\b/.test(textAfter)) indent -= config.indentUnit;
                    }
                    if (indent && state.localMode.indent)
                      indent += state.localMode.indent(state.localState, textAfter);
                    return indent;
                  },
            
                  innerMode: function(state) {
                    if (state.soyState.length && last(state.soyState) != "literal") return null;
                    else return {state: state.localState, mode: state.localMode};
                  },
            
                  electricInput: /^\s*\{(\/|\/template|\/deltemplate|\/switch|fallbackmsg|elseif|else|case|default|ifempty|\/literal\})$/,
                  lineComment: "//",
                  blockCommentStart: "/*",
                  blockCommentEnd: "*/",
                  blockCommentContinue: " * ",
                  fold: "indent"
                };
              }, "htmlmixed");
            
              CodeMirror.registerHelper("hintWords", "soy", indentingTags.concat(
                  ["delpackage", "namespace", "alias", "print", "css", "debugger"]));
            
              CodeMirror.defineMIME("text/x-soy", "soy");
            });
            
        • sparql
          • index.html
            <!doctype html>
            
            <title>CodeMirror: SPARQL mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="sparql.js"></script>
            <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">SPARQL</a>
              </ul>
            </div>
            
            <article>
            <h2>SPARQL mode</h2>
            <form><textarea id="code" name="code">
            PREFIX a: &lt;http://www.w3.org/2000/10/annotation-ns#>
            PREFIX dc: &lt;http://purl.org/dc/elements/1.1/>
            PREFIX foaf: &lt;http://xmlns.com/foaf/0.1/>
            PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#>
            
            # Comment!
            
            SELECT ?given ?family
            WHERE {
              {
                ?annot a:annotates &lt;http://www.w3.org/TR/rdf-sparql-query/> .
                ?annot dc:creator ?c .
                OPTIONAL {?c foaf:givenName ?given ;
                             foaf:familyName ?family }
              } UNION {
                ?c !foaf:knows/foaf:knows? ?thing.
                ?thing rdfs
              } MINUS {
                ?thing rdfs:label "剛柔流"@jp
              }
              FILTER isBlank(?c)
            }
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "application/sparql-query",
                    matchBrackets: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>application/sparql-query</code>.</p>
            
              </article>
            
          • sparql.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("sparql", function(config) {
              var indentUnit = config.indentUnit;
              var curPunc;
            
              function wordRegexp(words) {
                return new RegExp("^(?:" + words.join("|") + ")$", "i");
              }
              var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri",
                                    "iri", "uri", "bnode", "count", "sum", "min", "max", "avg", "sample",
                                    "group_concat", "rand", "abs", "ceil", "floor", "round", "concat", "substr", "strlen",
                                    "replace", "ucase", "lcase", "encode_for_uri", "contains", "strstarts", "strends",
                                    "strbefore", "strafter", "year", "month", "day", "hours", "minutes", "seconds",
                                    "timezone", "tz", "now", "uuid", "struuid", "md5", "sha1", "sha256", "sha384",
                                    "sha512", "coalesce", "if", "strlang", "strdt", "isnumeric", "regex", "exists",
                                    "isblank", "isliteral", "a"]);
              var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe",
                                         "ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional",
                                         "graph", "by", "asc", "desc", "as", "having", "undef", "values", "group",
                                         "minus", "in", "not", "service", "silent", "using", "insert", "delete", "union",
                                         "true", "false", "with",
                                         "data", "copy", "to", "move", "add", "create", "drop", "clear", "load"]);
              var operatorChars = /[*+\-<>=&|\^\/!\?]/;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                curPunc = null;
                if (ch == "$" || ch == "?") {
                  if(ch == "?" && stream.match(/\s/, false)){
                    return "operator";
                  }
                  stream.match(/^[\w\d]*/);
                  return "variable-2";
                }
                else if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) {
                  stream.match(/^[^\s\u00a0>]*>?/);
                  return "atom";
                }
                else if (ch == "\"" || ch == "'") {
                  state.tokenize = tokenLiteral(ch);
                  return state.tokenize(stream, state);
                }
                else if (/[{}\(\),\.;\[\]]/.test(ch)) {
                  curPunc = ch;
                  return "bracket";
                }
                else if (ch == "#") {
                  stream.skipToEnd();
                  return "comment";
                }
                else if (operatorChars.test(ch)) {
                  stream.eatWhile(operatorChars);
                  return "operator";
                }
                else if (ch == ":") {
                  stream.eatWhile(/[\w\d\._\-]/);
                  return "atom";
                }
                else if (ch == "@") {
                  stream.eatWhile(/[a-z\d\-]/i);
                  return "meta";
                }
                else {
                  stream.eatWhile(/[_\w\d]/);
                  if (stream.eat(":")) {
                    stream.eatWhile(/[\w\d_\-]/);
                    return "atom";
                  }
                  var word = stream.current();
                  if (ops.test(word))
                    return "builtin";
                  else if (keywords.test(word))
                    return "keyword";
                  else
                    return "variable";
                }
              }
            
              function tokenLiteral(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    escaped = !escaped && ch == "\\";
                  }
                  return "string";
                };
              }
            
              function pushContext(state, type, col) {
                state.context = {prev: state.context, indent: state.indent, col: col, type: type};
              }
              function popContext(state) {
                state.indent = state.context.indent;
                state.context = state.context.prev;
              }
            
              return {
                startState: function() {
                  return {tokenize: tokenBase,
                          context: null,
                          indent: 0,
                          col: 0};
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (state.context && state.context.align == null) state.context.align = false;
                    state.indent = stream.indentation();
                  }
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
            
                  if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") {
                    state.context.align = true;
                  }
            
                  if (curPunc == "(") pushContext(state, ")", stream.column());
                  else if (curPunc == "[") pushContext(state, "]", stream.column());
                  else if (curPunc == "{") pushContext(state, "}", stream.column());
                  else if (/[\]\}\)]/.test(curPunc)) {
                    while (state.context && state.context.type == "pattern") popContext(state);
                    if (state.context && curPunc == state.context.type) popContext(state);
                  }
                  else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state);
                  else if (/atom|string|variable/.test(style) && state.context) {
                    if (/[\}\]]/.test(state.context.type))
                      pushContext(state, "pattern", stream.column());
                    else if (state.context.type == "pattern" && !state.context.align) {
                      state.context.align = true;
                      state.context.col = stream.column();
                    }
                  }
            
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var firstChar = textAfter && textAfter.charAt(0);
                  var context = state.context;
                  if (/[\]\}]/.test(firstChar))
                    while (context && context.type == "pattern") context = context.prev;
            
                  var closing = context && firstChar == context.type;
                  if (!context)
                    return 0;
                  else if (context.type == "pattern")
                    return context.col;
                  else if (context.align)
                    return context.col + (closing ? 0 : 1);
                  else
                    return context.indent + (closing ? 0 : indentUnit);
                }
              };
            });
            
            CodeMirror.defineMIME("application/sparql-query", "sparql");
            
            });
            
        • spreadsheet
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Spreadsheet mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="spreadsheet.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Spreadsheet</a>
              </ul>
            </div>
            
            <article>
              <h2>Spreadsheet mode</h2>
              <form><textarea id="code" name="code">=IF(A1:B2, TRUE, FALSE) / 100</textarea></form>
            
              <script>
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                  lineNumbers: true,
                  matchBrackets: true,
                  extraKeys: {"Tab":  "indentAuto"}
                });
              </script>
            
              <p><strong>MIME types defined:</strong> <code>text/x-spreadsheet</code>.</p>
              
              <h3>The Spreadsheet Mode</h3>
              <p> Created by <a href="https://github.com/robertleeplummerjr">Robert Plummer</a></p>
            </article>
            
          • spreadsheet.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("spreadsheet", function () {
                return {
                  startState: function () {
                    return {
                      stringType: null,
                      stack: []
                    };
                  },
                  token: function (stream, state) {
                    if (!stream) return;
            
                    //check for state changes
                    if (state.stack.length === 0) {
                      //strings
                      if ((stream.peek() == '"') || (stream.peek() == "'")) {
                        state.stringType = stream.peek();
                        stream.next(); // Skip quote
                        state.stack.unshift("string");
                      }
                    }
            
                    //return state
                    //stack has
                    switch (state.stack[0]) {
                    case "string":
                      while (state.stack[0] === "string" && !stream.eol()) {
                        if (stream.peek() === state.stringType) {
                          stream.next(); // Skip quote
                          state.stack.shift(); // Clear flag
                        } else if (stream.peek() === "\\") {
                          stream.next();
                          stream.next();
                        } else {
                          stream.match(/^.[^\\\"\']*/);
                        }
                      }
                      return "string";
            
                    case "characterClass":
                      while (state.stack[0] === "characterClass" && !stream.eol()) {
                        if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./)))
                          state.stack.shift();
                      }
                      return "operator";
                    }
            
                    var peek = stream.peek();
            
                    //no stack
                    switch (peek) {
                    case "[":
                      stream.next();
                      state.stack.unshift("characterClass");
                      return "bracket";
                    case ":":
                      stream.next();
                      return "operator";
                    case "\\":
                      if (stream.match(/\\[a-z]+/)) return "string-2";
                      else return null;
                    case ".":
                    case ",":
                    case ";":
                    case "*":
                    case "-":
                    case "+":
                    case "^":
                    case "<":
                    case "/":
                    case "=":
                      stream.next();
                      return "atom";
                    case "$":
                      stream.next();
                      return "builtin";
                    }
            
                    if (stream.match(/\d+/)) {
                      if (stream.match(/^\w+/)) return "error";
                      return "number";
                    } else if (stream.match(/^[a-zA-Z_]\w*/)) {
                      if (stream.match(/(?=[\(.])/, false)) return "keyword";
                      return "variable-2";
                    } else if (["[", "]", "(", ")", "{", "}"].indexOf(peek) != -1) {
                      stream.next();
                      return "bracket";
                    } else if (!stream.eatSpace()) {
                      stream.next();
                    }
                    return null;
                  }
                };
              });
            
              CodeMirror.defineMIME("text/x-spreadsheet", "spreadsheet");
            });
            
        • sql
          • index.html
            <!doctype html>
            
            <title>CodeMirror: SQL Mode for CodeMirror</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css" />
            <script src="../../lib/codemirror.js"></script>
            <script src="sql.js"></script>
            <link rel="stylesheet" href="../../addon/hint/show-hint.css" />
            <script src="../../addon/hint/show-hint.js"></script>
            <script src="../../addon/hint/sql-hint.js"></script>
            <style>
            .CodeMirror {
                border-top: 1px solid black;
                border-bottom: 1px solid black;
            }
                    </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">SQL Mode for CodeMirror</a>
              </ul>
            </div>
            
            <article>
            <h2>SQL Mode for CodeMirror</h2>
            <form>
                        <textarea id="code" name="code">-- SQL Mode for CodeMirror
            SELECT SQL_NO_CACHE DISTINCT
            		@var1 AS `val1`, @'val2', @global.'sql_mode',
            		1.1 AS `float_val`, .14 AS `another_float`, 0.09e3 AS `int_with_esp`,
            		0xFA5 AS `hex`, x'fa5' AS `hex2`, 0b101 AS `bin`, b'101' AS `bin2`,
            		DATE '1994-01-01' AS `sql_date`, { T "1994-01-01" } AS `odbc_date`,
            		'my string', _utf8'your string', N'her string',
                    TRUE, FALSE, UNKNOWN
            	FROM DUAL
            	-- space needed after '--'
            	# 1 line comment
            	/* multiline
            	comment! */
            	LIMIT 1 OFFSET 0;
            </textarea>
                        </form>
                        <p><strong>MIME types defined:</strong> 
                        <code><a href="?mime=text/x-sql">text/x-sql</a></code>,
                        <code><a href="?mime=text/x-mysql">text/x-mysql</a></code>,
                        <code><a href="?mime=text/x-mariadb">text/x-mariadb</a></code>,
                        <code><a href="?mime=text/x-cassandra">text/x-cassandra</a></code>,
                        <code><a href="?mime=text/x-plsql">text/x-plsql</a></code>,
                        <code><a href="?mime=text/x-mssql">text/x-mssql</a></code>,
                        <code><a href="?mime=text/x-hive">text/x-hive</a></code>.
                    </p>
            <script>
            window.onload = function() {
              var mime = 'text/x-mariadb';
              // get mime type
              if (window.location.href.indexOf('mime=') > -1) {
                mime = window.location.href.substr(window.location.href.indexOf('mime=') + 5);
              }
              window.editor = CodeMirror.fromTextArea(document.getElementById('code'), {
                mode: mime,
                indentWithTabs: true,
                smartIndent: true,
                lineNumbers: true,
                matchBrackets : true,
                autofocus: true,
                extraKeys: {"Ctrl-Space": "autocomplete"},
                hintOptions: {tables: {
                  users: {name: null, score: null, birthDate: null},
                  countries: {name: null, population: null, size: null}
                }}
              });
            };
            </script>
            
            </article>
            
          • sql.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("sql", function(config, parserConfig) {
              "use strict";
            
              var client         = parserConfig.client || {},
                  atoms          = parserConfig.atoms || {"false": true, "true": true, "null": true},
                  builtin        = parserConfig.builtin || {},
                  keywords       = parserConfig.keywords || {},
                  operatorChars  = parserConfig.operatorChars || /^[*+\-%<>!=&|~^]/,
                  support        = parserConfig.support || {},
                  hooks          = parserConfig.hooks || {},
                  dateSQL        = parserConfig.dateSQL || {"date" : true, "time" : true, "timestamp" : true};
            
              function tokenBase(stream, state) {
                var ch = stream.next();
            
                // call hooks from the mime type
                if (hooks[ch]) {
                  var result = hooks[ch](stream, state);
                  if (result !== false) return result;
                }
            
                if (support.hexNumber == true &&
                  ((ch == "0" && stream.match(/^[xX][0-9a-fA-F]+/))
                  || (ch == "x" || ch == "X") && stream.match(/^'[0-9a-fA-F]+'/))) {
                  // hex
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/hexadecimal-literals.html
                  return "number";
                } else if (support.binaryNumber == true &&
                  (((ch == "b" || ch == "B") && stream.match(/^'[01]+'/))
                  || (ch == "0" && stream.match(/^b[01]+/)))) {
                  // bitstring
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/bit-field-literals.html
                  return "number";
                } else if (ch.charCodeAt(0) > 47 && ch.charCodeAt(0) < 58) {
                  // numbers
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/number-literals.html
                      stream.match(/^[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/);
                  support.decimallessFloat == true && stream.eat('.');
                  return "number";
                } else if (ch == "?" && (stream.eatSpace() || stream.eol() || stream.eat(";"))) {
                  // placeholders
                  return "variable-3";
                } else if (ch == "'" || (ch == '"' && support.doubleQuote)) {
                  // strings
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/string-literals.html
                  state.tokenize = tokenLiteral(ch);
                  return state.tokenize(stream, state);
                } else if ((((support.nCharCast == true && (ch == "n" || ch == "N"))
                    || (support.charsetCast == true && ch == "_" && stream.match(/[a-z][a-z0-9]*/i)))
                    && (stream.peek() == "'" || stream.peek() == '"'))) {
                  // charset casting: _utf8'str', N'str', n'str'
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/string-literals.html
                  return "keyword";
                } else if (/^[\(\),\;\[\]]/.test(ch)) {
                  // no highlightning
                  return null;
                } else if (support.commentSlashSlash && ch == "/" && stream.eat("/")) {
                  // 1-line comment
                  stream.skipToEnd();
                  return "comment";
                } else if ((support.commentHash && ch == "#")
                    || (ch == "-" && stream.eat("-") && (!support.commentSpaceRequired || stream.eat(" ")))) {
                  // 1-line comments
                  // ref: https://kb.askmonty.org/en/comment-syntax/
                  stream.skipToEnd();
                  return "comment";
                } else if (ch == "/" && stream.eat("*")) {
                  // multi-line comments
                  // ref: https://kb.askmonty.org/en/comment-syntax/
                  state.tokenize = tokenComment;
                  return state.tokenize(stream, state);
                } else if (ch == ".") {
                  // .1 for 0.1
                  if (support.zerolessFloat == true && stream.match(/^(?:\d+(?:e[+-]?\d+)?)/i)) {
                    return "number";
                  }
                  // .table_name (ODBC)
                  // // ref: http://dev.mysql.com/doc/refman/5.6/en/identifier-qualifiers.html
                  if (support.ODBCdotTable == true && stream.match(/^[a-zA-Z_]+/)) {
                    return "variable-2";
                  }
                } else if (operatorChars.test(ch)) {
                  // operators
                  stream.eatWhile(operatorChars);
                  return null;
                } else if (ch == '{' &&
                    (stream.match(/^( )*(d|D|t|T|ts|TS)( )*'[^']*'( )*}/) || stream.match(/^( )*(d|D|t|T|ts|TS)( )*"[^"]*"( )*}/))) {
                  // dates (weird ODBC syntax)
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-literals.html
                  return "number";
                } else {
                  stream.eatWhile(/^[_\w\d]/);
                  var word = stream.current().toLowerCase();
                  // dates (standard SQL syntax)
                  // ref: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-literals.html
                  if (dateSQL.hasOwnProperty(word) && (stream.match(/^( )+'[^']*'/) || stream.match(/^( )+"[^"]*"/)))
                    return "number";
                  if (atoms.hasOwnProperty(word)) return "atom";
                  if (builtin.hasOwnProperty(word)) return "builtin";
                  if (keywords.hasOwnProperty(word)) return "keyword";
                  if (client.hasOwnProperty(word)) return "string-2";
                  return null;
                }
              }
            
              // 'string', with char specified in quote escaped by '\'
              function tokenLiteral(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    escaped = !escaped && ch == "\\";
                  }
                  return "string";
                };
              }
              function tokenComment(stream, state) {
                while (true) {
                  if (stream.skipTo("*")) {
                    stream.next();
                    if (stream.eat("/")) {
                      state.tokenize = tokenBase;
                      break;
                    }
                  } else {
                    stream.skipToEnd();
                    break;
                  }
                }
                return "comment";
              }
            
              function pushContext(stream, state, type) {
                state.context = {
                  prev: state.context,
                  indent: stream.indentation(),
                  col: stream.column(),
                  type: type
                };
              }
            
              function popContext(state) {
                state.indent = state.context.indent;
                state.context = state.context.prev;
              }
            
              return {
                startState: function() {
                  return {tokenize: tokenBase, context: null};
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (state.context && state.context.align == null)
                      state.context.align = false;
                  }
                  if (stream.eatSpace()) return null;
            
                  var style = state.tokenize(stream, state);
                  if (style == "comment") return style;
            
                  if (state.context && state.context.align == null)
                    state.context.align = true;
            
                  var tok = stream.current();
                  if (tok == "(")
                    pushContext(stream, state, ")");
                  else if (tok == "[")
                    pushContext(stream, state, "]");
                  else if (state.context && state.context.type == tok)
                    popContext(state);
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var cx = state.context;
                  if (!cx) return CodeMirror.Pass;
                  var closing = textAfter.charAt(0) == cx.type;
                  if (cx.align) return cx.col + (closing ? 0 : 1);
                  else return cx.indent + (closing ? 0 : config.indentUnit);
                },
            
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                lineComment: support.commentSlashSlash ? "//" : support.commentHash ? "#" : null
              };
            });
            
            (function() {
              "use strict";
            
              // `identifier`
              function hookIdentifier(stream) {
                // MySQL/MariaDB identifiers
                // ref: http://dev.mysql.com/doc/refman/5.6/en/identifier-qualifiers.html
                var ch;
                while ((ch = stream.next()) != null) {
                  if (ch == "`" && !stream.eat("`")) return "variable-2";
                }
                stream.backUp(stream.current().length - 1);
                return stream.eatWhile(/\w/) ? "variable-2" : null;
              }
            
              // variable token
              function hookVar(stream) {
                // variables
                // @@prefix.varName @varName
                // varName can be quoted with ` or ' or "
                // ref: http://dev.mysql.com/doc/refman/5.5/en/user-variables.html
                if (stream.eat("@")) {
                  stream.match(/^session\./);
                  stream.match(/^local\./);
                  stream.match(/^global\./);
                }
            
                if (stream.eat("'")) {
                  stream.match(/^.*'/);
                  return "variable-2";
                } else if (stream.eat('"')) {
                  stream.match(/^.*"/);
                  return "variable-2";
                } else if (stream.eat("`")) {
                  stream.match(/^.*`/);
                  return "variable-2";
                } else if (stream.match(/^[0-9a-zA-Z$\.\_]+/)) {
                  return "variable-2";
                }
                return null;
              };
            
              // short client keyword token
              function hookClient(stream) {
                // \N means NULL
                // ref: http://dev.mysql.com/doc/refman/5.5/en/null-values.html
                if (stream.eat("N")) {
                    return "atom";
                }
                // \g, etc
                // ref: http://dev.mysql.com/doc/refman/5.5/en/mysql-commands.html
                return stream.match(/^[a-zA-Z.#!?]/) ? "variable-2" : null;
              }
            
              // these keywords are used by all SQL dialects (however, a mode can still overwrite it)
              var sqlKeywords = "alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where ";
            
              // turn a space-separated list into an array
              function set(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              // A generic SQL Mode. It's not a standard, it just try to support what is generally supported
              CodeMirror.defineMIME("text/x-sql", {
                name: "sql",
                keywords: set(sqlKeywords + "begin"),
                builtin: set("bool boolean bit blob enum long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision real date datetime year unsigned signed decimal numeric"),
                atoms: set("false true null unknown"),
                operatorChars: /^[*+\-%<>!=]/,
                dateSQL: set("date time timestamp"),
                support: set("ODBCdotTable doubleQuote binaryNumber hexNumber")
              });
            
              CodeMirror.defineMIME("text/x-mssql", {
                name: "sql",
                client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),
                keywords: set(sqlKeywords + "begin trigger proc view index for add constraint key primary foreign collate clustered nonclustered declare"),
                builtin: set("bigint numeric bit smallint decimal smallmoney int tinyint money float real char varchar text nchar nvarchar ntext binary varbinary image cursor timestamp hierarchyid uniqueidentifier sql_variant xml table "),
                atoms: set("false true null unknown"),
                operatorChars: /^[*+\-%<>!=]/,
                dateSQL: set("date datetimeoffset datetime2 smalldatetime datetime time"),
                hooks: {
                  "@":   hookVar
                }
              });
            
              CodeMirror.defineMIME("text/x-mysql", {
                name: "sql",
                client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),
                keywords: set(sqlKeywords + "accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general get global grant grants group groupby_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"),
                builtin: set("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"),
                atoms: set("false true null unknown"),
                operatorChars: /^[*+\-%<>!=&|^]/,
                dateSQL: set("date time timestamp"),
                support: set("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired"),
                hooks: {
                  "@":   hookVar,
                  "`":   hookIdentifier,
                  "\\":  hookClient
                }
              });
            
              CodeMirror.defineMIME("text/x-mariadb", {
                name: "sql",
                client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),
                keywords: set(sqlKeywords + "accessible action add after algorithm all always analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general generated get global grant grants group groupby_concat handler hard hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password persistent phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show shutdown signal slave slow smallint snapshot soft soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views virtual warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"),
                builtin: set("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"),
                atoms: set("false true null unknown"),
                operatorChars: /^[*+\-%<>!=&|^]/,
                dateSQL: set("date time timestamp"),
                support: set("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired"),
                hooks: {
                  "@":   hookVar,
                  "`":   hookIdentifier,
                  "\\":  hookClient
                }
              });
            
              // the query language used by Apache Cassandra is called CQL, but this mime type
              // is called Cassandra to avoid confusion with Contextual Query Language
              CodeMirror.defineMIME("text/x-cassandra", {
                name: "sql",
                client: { },
                keywords: set("add all allow alter and any apply as asc authorize batch begin by clustering columnfamily compact consistency count create custom delete desc distinct drop each_quorum exists filtering from grant if in index insert into key keyspace keyspaces level limit local_one local_quorum modify nan norecursive nosuperuser not of on one order password permission permissions primary quorum rename revoke schema select set storage superuser table three to token truncate ttl two type unlogged update use user users using values where with writetime"),
                builtin: set("ascii bigint blob boolean counter decimal double float frozen inet int list map static text timestamp timeuuid tuple uuid varchar varint"),
                atoms: set("false true infinity NaN"),
                operatorChars: /^[<>=]/,
                dateSQL: { },
                support: set("commentSlashSlash decimallessFloat"),
                hooks: { }
              });
            
              // this is based on Peter Raganitsch's 'plsql' mode
              CodeMirror.defineMIME("text/x-plsql", {
                name:       "sql",
                client:     set("appinfo arraysize autocommit autoprint autorecovery autotrace blockterminator break btitle cmdsep colsep compatibility compute concat copycommit copytypecheck define describe echo editfile embedded escape exec execute feedback flagger flush heading headsep instance linesize lno loboffset logsource long longchunksize markup native newpage numformat numwidth pagesize pause pno recsep recsepchar release repfooter repheader serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix tab term termout time timing trimout trimspool ttitle underline verify version wrap"),
                keywords:   set("abort accept access add all alter and any array arraylen as asc assert assign at attributes audit authorization avg base_table begin between binary_integer body boolean by case cast char char_base check close cluster clusters colauth column comment commit compress connect connected constant constraint crash create current currval cursor data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete desc digits dispose distinct do drop else elseif elsif enable end entry escape exception exception_init exchange exclusive exists exit external fast fetch file for force form from function generic goto grant group having identified if immediate in increment index indexes indicator initial initrans insert interface intersect into is key level library like limited local lock log logging long loop master maxextents maxtrans member minextents minus mislabel mode modify multiset new next no noaudit nocompress nologging noparallel not nowait number_base object of off offline on online only open option or order out package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior private privileges procedure public raise range raw read rebuild record ref references refresh release rename replace resource restrict return returning returns reverse revoke rollback row rowid rowlabel rownum rows run savepoint schema segment select separate session set share snapshot some space split sql start statement storage subtype successful synonym tabauth table tables tablespace task terminate then to trigger truncate type union unique unlimited unrecoverable unusable update use using validate value values variable view views when whenever where while with work"),
                builtin:    set("abs acos add_months ascii asin atan atan2 average bfile bfilename bigserial bit blob ceil character chartorowid chr clob concat convert cos cosh count dec decode deref dual dump dup_val_on_index empty error exp false float floor found glb greatest hextoraw initcap instr instrb int integer isopen last_day least lenght lenghtb ln lower lpad ltrim lub make_ref max min mlslabel mod months_between natural naturaln nchar nclob new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null number numeric nvarchar2 nvl others power rawtohex real reftohex round rowcount rowidtochar rowtype rpad rtrim serial sign signtype sin sinh smallint soundex sqlcode sqlerrm sqrt stddev string substr substrb sum sysdate tan tanh to_char text to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid unlogged upper user userenv varchar varchar2 variance varying vsize xml"),
                operatorChars: /^[*+\-%<>!=~]/,
                dateSQL:    set("date time timestamp"),
                support:    set("doubleQuote nCharCast zerolessFloat binaryNumber hexNumber")
              });
            
              // Created to support specific hive keywords
              CodeMirror.defineMIME("text/x-hive", {
                name: "sql",
                keywords: set("select alter $elem$ $key$ $value$ add after all analyze and archive as asc before between binary both bucket buckets by cascade case cast change cluster clustered clusterstatus collection column columns comment compute concatenate continue create cross cursor data database databases dbproperties deferred delete delimited desc describe directory disable distinct distribute drop else enable end escaped exclusive exists explain export extended external false fetch fields fileformat first format formatted from full function functions grant group having hold_ddltime idxproperties if import in index indexes inpath inputdriver inputformat insert intersect into is items join keys lateral left like limit lines load local location lock locks mapjoin materialized minus msck no_drop nocompress not of offline on option or order out outer outputdriver outputformat overwrite partition partitioned partitions percent plus preserve procedure purge range rcfile read readonly reads rebuild recordreader recordwriter recover reduce regexp rename repair replace restrict revoke right rlike row schema schemas semi sequencefile serde serdeproperties set shared show show_database sort sorted ssl statistics stored streamtable table tables tablesample tblproperties temporary terminated textfile then tmp to touch transform trigger true unarchive undo union uniquejoin unlock update use using utc utc_tmestamp view when where while with"),
                builtin: set("bool boolean long timestamp tinyint smallint bigint int float double date datetime unsigned string array struct map uniontype"),
                atoms: set("false true null unknown"),
                operatorChars: /^[*+\-%<>!=]/,
                dateSQL: set("date timestamp"),
                support: set("ODBCdotTable doubleQuote binaryNumber hexNumber")
              });
            }());
            
            });
            
            /*
              How Properties of Mime Types are used by SQL Mode
              =================================================
            
              keywords:
                A list of keywords you want to be highlighted.
              builtin:
                A list of builtin types you want to be highlighted (if you want types to be of class "builtin" instead of "keyword").
              operatorChars:
                All characters that must be handled as operators.
              client:
                Commands parsed and executed by the client (not the server).
              support:
                A list of supported syntaxes which are not common, but are supported by more than 1 DBMS.
                * ODBCdotTable: .tableName
                * zerolessFloat: .1
                * doubleQuote
                * nCharCast: N'string'
                * charsetCast: _utf8'string'
                * commentHash: use # char for comments
                * commentSlashSlash: use // for comments
                * commentSpaceRequired: require a space after -- for comments
              atoms:
                Keywords that must be highlighted as atoms,. Some DBMS's support more atoms than others:
                UNKNOWN, INFINITY, UNDERFLOW, NaN...
              dateSQL:
                Used for date/time SQL standard syntax, because not all DBMS's support same temporal types.
            */
            
        • stex
          • index.html
            <!doctype html>
            
            <title>CodeMirror: sTeX mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="stex.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">sTeX</a>
              </ul>
            </div>
            
            <article>
            <h2>sTeX mode</h2>
            <form><textarea id="code" name="code">
            \begin{module}[id=bbt-size]
            \importmodule[balanced-binary-trees]{balanced-binary-trees}
            \importmodule[\KWARCslides{dmath/en/cardinality}]{cardinality}
            
            \begin{frame}
              \frametitle{Size Lemma for Balanced Trees}
              \begin{itemize}
              \item
                \begin{assertion}[id=size-lemma,type=lemma] 
                Let $G=\tup{V,E}$ be a \termref[cd=binary-trees]{balanced binary tree} 
                of \termref[cd=graph-depth,name=vertex-depth]{depth}$n>i$, then the set
                 $\defeq{\livar{V}i}{\setst{\inset{v}{V}}{\gdepth{v} = i}}$ of
                \termref[cd=graphs-intro,name=node]{nodes} at 
                \termref[cd=graph-depth,name=vertex-depth]{depth} $i$ has
                \termref[cd=cardinality,name=cardinality]{cardinality} $\power2i$.
               \end{assertion}
              \item
                \begin{sproof}[id=size-lemma-pf,proofend=,for=size-lemma]{via induction over the depth $i$.}
                  \begin{spfcases}{We have to consider two cases}
                    \begin{spfcase}{$i=0$}
                      \begin{spfstep}[display=flow]
                        then $\livar{V}i=\set{\livar{v}r}$, where $\livar{v}r$ is the root, so
                        $\eq{\card{\livar{V}0},\card{\set{\livar{v}r}},1,\power20}$.
                      \end{spfstep}
                    \end{spfcase}
                    \begin{spfcase}{$i>0$}
                      \begin{spfstep}[display=flow]
                       then $\livar{V}{i-1}$ contains $\power2{i-1}$ vertexes 
                       \begin{justification}[method=byIH](IH)\end{justification}
                      \end{spfstep}
                      \begin{spfstep}
                       By the \begin{justification}[method=byDef]definition of a binary
                          tree\end{justification}, each $\inset{v}{\livar{V}{i-1}}$ is a leaf or has
                        two children that are at depth $i$.
                      \end{spfstep}
                      \begin{spfstep}
                       As $G$ is \termref[cd=balanced-binary-trees,name=balanced-binary-tree]{balanced} and $\gdepth{G}=n>i$, $\livar{V}{i-1}$ cannot contain
                        leaves.
                      \end{spfstep}
                      \begin{spfstep}[type=conclusion]
                       Thus $\eq{\card{\livar{V}i},{\atimes[cdot]{2,\card{\livar{V}{i-1}}}},{\atimes[cdot]{2,\power2{i-1}}},\power2i}$.
                      \end{spfstep}
                    \end{spfcase}
                  \end{spfcases}
                \end{sproof}
              \item 
                \begin{assertion}[id=fbbt,type=corollary]	
                  A fully balanced tree of depth $d$ has $\power2{d+1}-1$ nodes.
                \end{assertion}
              \item
                  \begin{sproof}[for=fbbt,id=fbbt-pf]{}
                    \begin{spfstep}
                      Let $\defeq{G}{\tup{V,E}}$ be a fully balanced tree
                    \end{spfstep}
                    \begin{spfstep}
                      Then $\card{V}=\Sumfromto{i}1d{\power2i}= \power2{d+1}-1$.
                    \end{spfstep}
                  \end{sproof}
                \end{itemize}
              \end{frame}
            \begin{note}
              \begin{omtext}[type=conclusion,for=binary-tree]
                This shows that balanced binary trees grow in breadth very quickly, a consequence of
                this is that they are very shallow (and this compute very fast), which is the essence of
                the next result.
              \end{omtext}
            \end{note}
            \end{module}
            
            %%% Local Variables: 
            %%% mode: LaTeX
            %%% TeX-master: "all"
            %%% End: \end{document}
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-stex</code>.</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#stex_*">normal</a>,  <a href="../../test/index.html#verbose,stex_*">verbose</a>.</p>
            
              </article>
            
          • stex.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*
             * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)
             * Licence: MIT
             */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("stex", function() {
                "use strict";
            
                function pushCommand(state, command) {
                  state.cmdState.push(command);
                }
            
                function peekCommand(state) {
                  if (state.cmdState.length > 0) {
                    return state.cmdState[state.cmdState.length - 1];
                  } else {
                    return null;
                  }
                }
            
                function popCommand(state) {
                  var plug = state.cmdState.pop();
                  if (plug) {
                    plug.closeBracket();
                  }
                }
            
                // returns the non-default plugin closest to the end of the list
                function getMostPowerful(state) {
                  var context = state.cmdState;
                  for (var i = context.length - 1; i >= 0; i--) {
                    var plug = context[i];
                    if (plug.name == "DEFAULT") {
                      continue;
                    }
                    return plug;
                  }
                  return { styleIdentifier: function() { return null; } };
                }
            
                function addPluginPattern(pluginName, cmdStyle, styles) {
                  return function () {
                    this.name = pluginName;
                    this.bracketNo = 0;
                    this.style = cmdStyle;
                    this.styles = styles;
                    this.argument = null;   // \begin and \end have arguments that follow. These are stored in the plugin
            
                    this.styleIdentifier = function() {
                      return this.styles[this.bracketNo - 1] || null;
                    };
                    this.openBracket = function() {
                      this.bracketNo++;
                      return "bracket";
                    };
                    this.closeBracket = function() {};
                  };
                }
            
                var plugins = {};
            
                plugins["importmodule"] = addPluginPattern("importmodule", "tag", ["string", "builtin"]);
                plugins["documentclass"] = addPluginPattern("documentclass", "tag", ["", "atom"]);
                plugins["usepackage"] = addPluginPattern("usepackage", "tag", ["atom"]);
                plugins["begin"] = addPluginPattern("begin", "tag", ["atom"]);
                plugins["end"] = addPluginPattern("end", "tag", ["atom"]);
            
                plugins["DEFAULT"] = function () {
                  this.name = "DEFAULT";
                  this.style = "tag";
            
                  this.styleIdentifier = this.openBracket = this.closeBracket = function() {};
                };
            
                function setState(state, f) {
                  state.f = f;
                }
            
                // called when in a normal (no environment) context
                function normal(source, state) {
                  var plug;
                  // Do we look like '\command' ?  If so, attempt to apply the plugin 'command'
                  if (source.match(/^\\[a-zA-Z@]+/)) {
                    var cmdName = source.current().slice(1);
                    plug = plugins[cmdName] || plugins["DEFAULT"];
                    plug = new plug();
                    pushCommand(state, plug);
                    setState(state, beginParams);
                    return plug.style;
                  }
            
                  // escape characters
                  if (source.match(/^\\[$&%#{}_]/)) {
                    return "tag";
                  }
            
                  // white space control characters
                  if (source.match(/^\\[,;!\/\\]/)) {
                    return "tag";
                  }
            
                  // find if we're starting various math modes
                  if (source.match("\\[")) {
                    setState(state, function(source, state){ return inMathMode(source, state, "\\]"); });
                    return "keyword";
                  }
                  if (source.match("$$")) {
                    setState(state, function(source, state){ return inMathMode(source, state, "$$"); });
                    return "keyword";
                  }
                  if (source.match("$")) {
                    setState(state, function(source, state){ return inMathMode(source, state, "$"); });
                    return "keyword";
                  }
            
                  var ch = source.next();
                  if (ch == "%") {
                    source.skipToEnd();
                    return "comment";
                  } else if (ch == '}' || ch == ']') {
                    plug = peekCommand(state);
                    if (plug) {
                      plug.closeBracket(ch);
                      setState(state, beginParams);
                    } else {
                      return "error";
                    }
                    return "bracket";
                  } else if (ch == '{' || ch == '[') {
                    plug = plugins["DEFAULT"];
                    plug = new plug();
                    pushCommand(state, plug);
                    return "bracket";
                  } else if (/\d/.test(ch)) {
                    source.eatWhile(/[\w.%]/);
                    return "atom";
                  } else {
                    source.eatWhile(/[\w\-_]/);
                    plug = getMostPowerful(state);
                    if (plug.name == 'begin') {
                      plug.argument = source.current();
                    }
                    return plug.styleIdentifier();
                  }
                }
            
                function inMathMode(source, state, endModeSeq) {
                  if (source.eatSpace()) {
                    return null;
                  }
                  if (source.match(endModeSeq)) {
                    setState(state, normal);
                    return "keyword";
                  }
                  if (source.match(/^\\[a-zA-Z@]+/)) {
                    return "tag";
                  }
                  if (source.match(/^[a-zA-Z]+/)) {
                    return "variable-2";
                  }
                  // escape characters
                  if (source.match(/^\\[$&%#{}_]/)) {
                    return "tag";
                  }
                  // white space control characters
                  if (source.match(/^\\[,;!\/]/)) {
                    return "tag";
                  }
                  // special math-mode characters
                  if (source.match(/^[\^_&]/)) {
                    return "tag";
                  }
                  // non-special characters
                  if (source.match(/^[+\-<>|=,\/@!*:;'"`~#?]/)) {
                    return null;
                  }
                  if (source.match(/^(\d+\.\d*|\d*\.\d+|\d+)/)) {
                    return "number";
                  }
                  var ch = source.next();
                  if (ch == "{" || ch == "}" || ch == "[" || ch == "]" || ch == "(" || ch == ")") {
                    return "bracket";
                  }
            
                  if (ch == "%") {
                    source.skipToEnd();
                    return "comment";
                  }
                  return "error";
                }
            
                function beginParams(source, state) {
                  var ch = source.peek(), lastPlug;
                  if (ch == '{' || ch == '[') {
                    lastPlug = peekCommand(state);
                    lastPlug.openBracket(ch);
                    source.eat(ch);
                    setState(state, normal);
                    return "bracket";
                  }
                  if (/[ \t\r]/.test(ch)) {
                    source.eat(ch);
                    return null;
                  }
                  setState(state, normal);
                  popCommand(state);
            
                  return normal(source, state);
                }
            
                return {
                  startState: function() {
                    return {
                      cmdState: [],
                      f: normal
                    };
                  },
                  copyState: function(s) {
                    return {
                      cmdState: s.cmdState.slice(),
                      f: s.f
                    };
                  },
                  token: function(stream, state) {
                    return state.f(stream, state);
                  },
                  blankLine: function(state) {
                    state.f = normal;
                    state.cmdState.length = 0;
                  },
                  lineComment: "%"
                };
              });
            
              CodeMirror.defineMIME("text/x-stex", "stex");
              CodeMirror.defineMIME("text/x-latex", "stex");
            
            });
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4}, "stex");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT("word",
                 "foo");
            
              MT("twoWords",
                 "foo bar");
            
              MT("beginEndDocument",
                 "[tag \\begin][bracket {][atom document][bracket }]",
                 "[tag \\end][bracket {][atom document][bracket }]");
            
              MT("beginEndEquation",
                 "[tag \\begin][bracket {][atom equation][bracket }]",
                 "  E=mc^2",
                 "[tag \\end][bracket {][atom equation][bracket }]");
            
              MT("beginModule",
                 "[tag \\begin][bracket {][atom module][bracket }[[]]]");
            
              MT("beginModuleId",
                 "[tag \\begin][bracket {][atom module][bracket }[[]id=bbt-size[bracket ]]]");
            
              MT("importModule",
                 "[tag \\importmodule][bracket [[][string b-b-t][bracket ]]{][builtin b-b-t][bracket }]");
            
              MT("importModulePath",
                 "[tag \\importmodule][bracket [[][tag \\KWARCslides][bracket {][string dmath/en/cardinality][bracket }]]{][builtin card][bracket }]");
            
              MT("psForPDF",
                 "[tag \\PSforPDF][bracket [[][atom 1][bracket ]]{]#1[bracket }]");
            
              MT("comment",
                 "[comment % foo]");
            
              MT("tagComment",
                 "[tag \\item][comment % bar]");
            
              MT("commentTag",
                 " [comment % \\item]");
            
              MT("commentLineBreak",
                 "[comment %]",
                 "foo");
            
              MT("tagErrorCurly",
                 "[tag \\begin][error }][bracket {]");
            
              MT("tagErrorSquare",
                 "[tag \\item][error ]]][bracket {]");
            
              MT("commentCurly",
                 "[comment % }]");
            
              MT("tagHash",
                 "the [tag \\#] key");
            
              MT("tagNumber",
                 "a [tag \\$][atom 5] stetson");
            
              MT("tagPercent",
                 "[atom 100][tag \\%] beef");
            
              MT("tagAmpersand",
                 "L [tag \\&] N");
            
              MT("tagUnderscore",
                 "foo[tag \\_]bar");
            
              MT("tagBracketOpen",
                 "[tag \\emph][bracket {][tag \\{][bracket }]");
            
              MT("tagBracketClose",
                 "[tag \\emph][bracket {][tag \\}][bracket }]");
            
              MT("tagLetterNumber",
                 "section [tag \\S][atom 1]");
            
              MT("textTagNumber",
                 "para [tag \\P][atom 2]");
            
              MT("thinspace",
                 "x[tag \\,]y");
            
              MT("thickspace",
                 "x[tag \\;]y");
            
              MT("negativeThinspace",
                 "x[tag \\!]y");
            
              MT("periodNotSentence",
                 "J.\\ L.\\ is");
            
              MT("periodSentence",
                 "X[tag \\@]. The");
            
              MT("italicCorrection",
                 "[bracket {][tag \\em] If[tag \\/][bracket }] I");
            
              MT("tagBracket",
                 "[tag \\newcommand][bracket {][tag \\pop][bracket }]");
            
              MT("inlineMathTagFollowedByNumber",
                 "[keyword $][tag \\pi][number 2][keyword $]");
            
              MT("inlineMath",
                 "[keyword $][number 3][variable-2 x][tag ^][number 2.45]-[tag \\sqrt][bracket {][tag \\$\\alpha][bracket }] = [number 2][keyword $] other text");
            
              MT("displayMath",
                 "More [keyword $$]\t[variable-2 S][tag ^][variable-2 n][tag \\sum] [variable-2 i][keyword $$] other text");
            
              MT("mathWithComment",
                 "[keyword $][variable-2 x] [comment % $]",
                 "[variable-2 y][keyword $] other text");
            
              MT("lineBreakArgument",
                "[tag \\\\][bracket [[][atom 1cm][bracket ]]]");
            })();
            
        • stylus
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Stylus mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../addon/hint/show-hint.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="stylus.js"></script>
            <script src="../../addon/hint/show-hint.js"></script>
            <script src="../../addon/hint/css-hint.js"></script>
            <style>.CodeMirror {background: #f8f8f8;} form{margin-bottom: .7em;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Stylus</a>
              </ul>
            </div>
            
            <article>
            <h2>Stylus mode</h2>
            <form><textarea id="code" name="code">
            /* Stylus mode */
            
            #id,
            .class,
            article
              font-family Arial, sans-serif
            
            #id,
            .class,
            article {
              font-family: Arial, sans-serif;
            }
            
            // Variables
            font-size-base = 16px
            line-height-base = 1.5
            font-family-base = "Helvetica Neue", Helvetica, Arial, sans-serif
            text-color = lighten(#000, 20%)
            
            body
              font font-size-base/line-height-base font-family-base
              color text-color
            
            body {
              font: 400 16px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
              color: #333;
            }
            
            // Variables
            link-color = darken(#428bca, 6.5%)
            link-hover-color = darken(link-color, 15%)
            link-decoration = none
            link-hover-decoration = false
            
            // Mixin
            tab-focus()
              outline thin dotted
              outline 5px auto -webkit-focus-ring-color
              outline-offset -2px
            
            a
              color link-color
              if link-decoration
                text-decoration link-decoration
              &:hover
              &:focus
                color link-hover-color
                if link-hover-decoration
                  text-decoration link-hover-decoration
              &:focus
                tab-focus()
            
            a {
              color: #3782c4;
              text-decoration: none;
            }
            a:hover,
            a:focus {
              color: #2f6ea7;
            }
            a:focus {
              outline: thin dotted;
              outline: 5px auto -webkit-focus-ring-color;
              outline-offset: -2px;
            }
            </textarea>
            </form>
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                extraKeys: {"Ctrl-Space": "autocomplete"},
                tabSize: 2
              });
            </script>
            
            <p><strong>MIME types defined:</strong> <code>text/x-styl</code>.</p>
            <p>Created by <a href="https://github.com/dmitrykiselyov">Dmitry Kiselyov</a></p>
            </article>
            
          • stylus.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Stylus mode created by Dmitry Kiselyov http://git.io/AaRB
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("stylus", function(config) {
                var indentUnit = config.indentUnit,
                    tagKeywords = keySet(tagKeywords_),
                    tagVariablesRegexp = /^(a|b|i|s|col|em)$/i,
                    propertyKeywords = keySet(propertyKeywords_),
                    nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_),
                    valueKeywords = keySet(valueKeywords_),
                    colorKeywords = keySet(colorKeywords_),
                    documentTypes = keySet(documentTypes_),
                    documentTypesRegexp = wordRegexp(documentTypes_),
                    mediaFeatures = keySet(mediaFeatures_),
                    mediaTypes = keySet(mediaTypes_),
                    fontProperties = keySet(fontProperties_),
                    operatorsRegexp = /^\s*([.]{2,3}|&&|\|\||\*\*|[?!=:]?=|[-+*\/%<>]=?|\?:|\~)/,
                    wordOperatorKeywordsRegexp = wordRegexp(wordOperatorKeywords_),
                    blockKeywords = keySet(blockKeywords_),
                    vendorPrefixesRegexp = new RegExp(/^\-(moz|ms|o|webkit)-/i),
                    commonAtoms = keySet(commonAtoms_),
                    firstWordMatch = "",
                    states = {},
                    ch,
                    style,
                    type,
                    override;
            
                /**
                 * Tokenizers
                 */
                function tokenBase(stream, state) {
                  firstWordMatch = stream.string.match(/(^[\w-]+\s*=\s*$)|(^\s*[\w-]+\s*=\s*[\w-])|(^\s*(\.|#|@|\$|\&|\[|\d|\+|::?|\{|\>|~|\/)?\s*[\w-]*([a-z0-9-]|\*|\/\*)(\(|,)?)/);
                  state.context.line.firstWord = firstWordMatch ? firstWordMatch[0].replace(/^\s*/, "") : "";
                  state.context.line.indent = stream.indentation();
                  ch = stream.peek();
            
                  // Line comment
                  if (stream.match("//")) {
                    stream.skipToEnd();
                    return ["comment", "comment"];
                  }
                  // Block comment
                  if (stream.match("/*")) {
                    state.tokenize = tokenCComment;
                    return tokenCComment(stream, state);
                  }
                  // String
                  if (ch == "\"" || ch == "'") {
                    stream.next();
                    state.tokenize = tokenString(ch);
                    return state.tokenize(stream, state);
                  }
                  // Def
                  if (ch == "@") {
                    stream.next();
                    stream.eatWhile(/[\w\\-]/);
                    return ["def", stream.current()];
                  }
                  // ID selector or Hex color
                  if (ch == "#") {
                    stream.next();
                    // Hex color
                    if (stream.match(/^[0-9a-f]{6}|[0-9a-f]{3}/i)) {
                      return ["atom", "atom"];
                    }
                    // ID selector
                    if (stream.match(/^[a-z][\w-]*/i)) {
                      return ["builtin", "hash"];
                    }
                  }
                  // Vendor prefixes
                  if (stream.match(vendorPrefixesRegexp)) {
                    return ["meta", "vendor-prefixes"];
                  }
                  // Numbers
                  if (stream.match(/^-?[0-9]?\.?[0-9]/)) {
                    stream.eatWhile(/[a-z%]/i);
                    return ["number", "unit"];
                  }
                  // !important|optional
                  if (ch == "!") {
                    stream.next();
                    return [stream.match(/^(important|optional)/i) ? "keyword": "operator", "important"];
                  }
                  // Class
                  if (ch == "." && stream.match(/^\.[a-z][\w-]*/i)) {
                    return ["qualifier", "qualifier"];
                  }
                  // url url-prefix domain regexp
                  if (stream.match(documentTypesRegexp)) {
                    if (stream.peek() == "(") state.tokenize = tokenParenthesized;
                    return ["property", "word"];
                  }
                  // Mixins / Functions
                  if (stream.match(/^[a-z][\w-]*\(/i)) {
                    stream.backUp(1);
                    return ["keyword", "mixin"];
                  }
                  // Block mixins
                  if (stream.match(/^(\+|-)[a-z][\w-]*\(/i)) {
                    stream.backUp(1);
                    return ["keyword", "block-mixin"];
                  }
                  // Parent Reference BEM naming
                  if (stream.string.match(/^\s*&/) && stream.match(/^[-_]+[a-z][\w-]*/)) {
                    return ["qualifier", "qualifier"];
                  }
                  // / Root Reference & Parent Reference
                  if (stream.match(/^(\/|&)(-|_|:|\.|#|[a-z])/)) {
                    stream.backUp(1);
                    return ["variable-3", "reference"];
                  }
                  if (stream.match(/^&{1}\s*$/)) {
                    return ["variable-3", "reference"];
                  }
                  // Variable
                  if (ch == "$" && stream.match(/^\$[\w-]+/i)) {
                    return ["variable-2", "variable-name"];
                  }
                  // Word operator
                  if (stream.match(wordOperatorKeywordsRegexp)) {
                    return ["operator", "operator"];
                  }
                  // Word
                  if (stream.match(/^[-_]*[a-z0-9]+[\w-]*/i)) {
                    if (stream.match(/^(\.|\[)[\w-\'\"\]]+/i, false)) {
                      if (!wordIsTag(stream.current())) {
                        stream.match(/[\w-]+/);
                        return ["variable-2", "variable-name"];
                      }
                    }
                    return ["variable-2", "word"];
                  }
                  // Operators
                  if (stream.match(operatorsRegexp)) {
                    return ["operator", stream.current()];
                  }
                  // Delimiters
                  if (/[:;,{}\[\]\(\)]/.test(ch)) {
                    stream.next();
                    return [null, ch];
                  }
                  // Non-detected items
                  stream.next();
                  return [null, null];
                }
            
                /**
                 * Token comment
                 */
                function tokenCComment(stream, state) {
                  var maybeEnd = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (maybeEnd && ch == "/") {
                      state.tokenize = null;
                      break;
                    }
                    maybeEnd = (ch == "*");
                  }
                  return ["comment", "comment"];
                }
            
                /**
                 * Token string
                 */
                function tokenString(quote) {
                  return function(stream, state) {
                    var escaped = false, ch;
                    while ((ch = stream.next()) != null) {
                      if (ch == quote && !escaped) {
                        if (quote == ")") stream.backUp(1);
                        break;
                      }
                      escaped = !escaped && ch == "\\";
                    }
                    if (ch == quote || !escaped && quote != ")") state.tokenize = null;
                    return ["string", "string"];
                  };
                }
            
                /**
                 * Token parenthesized
                 */
                function tokenParenthesized(stream, state) {
                  stream.next(); // Must be "("
                  if (!stream.match(/\s*[\"\')]/, false))
                    state.tokenize = tokenString(")");
                  else
                    state.tokenize = null;
                  return [null, "("];
                }
            
                /**
                 * Context management
                 */
                function Context(type, indent, prev, line) {
                  this.type = type;
                  this.indent = indent;
                  this.prev = prev;
                  this.line = line || {firstWord: "", indent: 0};
                }
            
                function pushContext(state, stream, type, indent) {
                  indent = indent >= 0 ? indent : indentUnit;
                  state.context = new Context(type, stream.indentation() + indent, state.context);
                  return type;
                }
            
                function popContext(state, currentIndent) {
                  var contextIndent = state.context.indent - indentUnit;
                  currentIndent = currentIndent || false;
                  state.context = state.context.prev;
                  if (currentIndent) state.context.indent = contextIndent;
                  return state.context.type;
                }
            
                function pass(type, stream, state) {
                  return states[state.context.type](type, stream, state);
                }
            
                function popAndPass(type, stream, state, n) {
                  for (var i = n || 1; i > 0; i--)
                    state.context = state.context.prev;
                  return pass(type, stream, state);
                }
            
            
                /**
                 * Parser
                 */
                function wordIsTag(word) {
                  return word.toLowerCase() in tagKeywords;
                }
            
                function wordIsProperty(word) {
                  word = word.toLowerCase();
                  return word in propertyKeywords || word in fontProperties;
                }
            
                function wordIsBlock(word) {
                  return word.toLowerCase() in blockKeywords;
                }
            
                function wordIsVendorPrefix(word) {
                  return word.toLowerCase().match(vendorPrefixesRegexp);
                }
            
                function wordAsValue(word) {
                  var wordLC = word.toLowerCase();
                  var override = "variable-2";
                  if (wordIsTag(word)) override = "tag";
                  else if (wordIsBlock(word)) override = "block-keyword";
                  else if (wordIsProperty(word)) override = "property";
                  else if (wordLC in valueKeywords || wordLC in commonAtoms) override = "atom";
                  else if (wordLC == "return" || wordLC in colorKeywords) override = "keyword";
            
                  // Font family
                  else if (word.match(/^[A-Z]/)) override = "string";
                  return override;
                }
            
                function typeIsBlock(type, stream) {
                  return ((endOfLine(stream) && (type == "{" || type == "]" || type == "hash" || type == "qualifier")) || type == "block-mixin");
                }
            
                function typeIsInterpolation(type, stream) {
                  return type == "{" && stream.match(/^\s*\$?[\w-]+/i, false);
                }
            
                function typeIsPseudo(type, stream) {
                  return type == ":" && stream.match(/^[a-z-]+/, false);
                }
            
                function startOfLine(stream) {
                  return stream.sol() || stream.string.match(new RegExp("^\\s*" + escapeRegExp(stream.current())));
                }
            
                function endOfLine(stream) {
                  return stream.eol() || stream.match(/^\s*$/, false);
                }
            
                function firstWordOfLine(line) {
                  var re = /^\s*[-_]*[a-z0-9]+[\w-]*/i;
                  var result = typeof line == "string" ? line.match(re) : line.string.match(re);
                  return result ? result[0].replace(/^\s*/, "") : "";
                }
            
            
                /**
                 * Block
                 */
                states.block = function(type, stream, state) {
                  if ((type == "comment" && startOfLine(stream)) ||
                      (type == "," && endOfLine(stream)) ||
                      type == "mixin") {
                    return pushContext(state, stream, "block", 0);
                  }
                  if (typeIsInterpolation(type, stream)) {
                    return pushContext(state, stream, "interpolation");
                  }
                  if (endOfLine(stream) && type == "]") {
                    if (!/^\s*(\.|#|:|\[|\*|&)/.test(stream.string) && !wordIsTag(firstWordOfLine(stream))) {
                      return pushContext(state, stream, "block", 0);
                    }
                  }
                  if (typeIsBlock(type, stream, state)) {
                    return pushContext(state, stream, "block");
                  }
                  if (type == "}" && endOfLine(stream)) {
                    return pushContext(state, stream, "block", 0);
                  }
                  if (type == "variable-name") {
                    if ((stream.indentation() == 0 && startOfLine(stream)) || wordIsBlock(firstWordOfLine(stream))) {
                      return pushContext(state, stream, "variableName");
                    }
                    else {
                      return pushContext(state, stream, "variableName", 0);
                    }
                  }
                  if (type == "=") {
                    if (!endOfLine(stream) && !wordIsBlock(firstWordOfLine(stream))) {
                      return pushContext(state, stream, "block", 0);
                    }
                    return pushContext(state, stream, "block");
                  }
                  if (type == "*") {
                    if (endOfLine(stream) || stream.match(/\s*(,|\.|#|\[|:|{)/,false)) {
                      override = "tag";
                      return pushContext(state, stream, "block");
                    }
                  }
                  if (typeIsPseudo(type, stream)) {
                    return pushContext(state, stream, "pseudo");
                  }
                  if (/@(font-face|media|supports|(-moz-)?document)/.test(type)) {
                    return pushContext(state, stream, endOfLine(stream) ? "block" : "atBlock");
                  }
                  if (/@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
                    return pushContext(state, stream, "keyframes");
                  }
                  if (/@extends?/.test(type)) {
                    return pushContext(state, stream, "extend", 0);
                  }
                  if (type && type.charAt(0) == "@") {
            
                    // Property Lookup
                    if (stream.indentation() > 0 && wordIsProperty(stream.current().slice(1))) {
                      override = "variable-2";
                      return "block";
                    }
                    if (/(@import|@require|@charset)/.test(type)) {
                      return pushContext(state, stream, "block", 0);
                    }
                    return pushContext(state, stream, "block");
                  }
                  if (type == "reference" && endOfLine(stream)) {
                    return pushContext(state, stream, "block");
                  }
                  if (type == "(") {
                    return pushContext(state, stream, "parens");
                  }
            
                  if (type == "vendor-prefixes") {
                    return pushContext(state, stream, "vendorPrefixes");
                  }
                  if (type == "word") {
                    var word = stream.current();
                    override = wordAsValue(word);
            
                    if (override == "property") {
                      if (startOfLine(stream)) {
                        return pushContext(state, stream, "block", 0);
                      } else {
                        override = "atom";
                        return "block";
                      }
                    }
            
                    if (override == "tag") {
            
                      // tag is a css value
                      if (/embed|menu|pre|progress|sub|table/.test(word)) {
                        if (wordIsProperty(firstWordOfLine(stream))) {
                          override = "atom";
                          return "block";
                        }
                      }
            
                      // tag is an attribute
                      if (stream.string.match(new RegExp("\\[\\s*" + word + "|" + word +"\\s*\\]"))) {
                        override = "atom";
                        return "block";
                      }
            
                      // tag is a variable
                      if (tagVariablesRegexp.test(word)) {
                        if ((startOfLine(stream) && stream.string.match(/=/)) ||
                            (!startOfLine(stream) &&
                             !stream.string.match(/^(\s*\.|#|\&|\[|\/|>|\*)/) &&
                             !wordIsTag(firstWordOfLine(stream)))) {
                          override = "variable-2";
                          if (wordIsBlock(firstWordOfLine(stream)))  return "block";
                          return pushContext(state, stream, "block", 0);
                        }
                      }
            
                      if (endOfLine(stream)) return pushContext(state, stream, "block");
                    }
                    if (override == "block-keyword") {
                      override = "keyword";
            
                      // Postfix conditionals
                      if (stream.current(/(if|unless)/) && !startOfLine(stream)) {
                        return "block";
                      }
                      return pushContext(state, stream, "block");
                    }
                    if (word == "return") return pushContext(state, stream, "block", 0);
                  }
                  return state.context.type;
                };
            
            
                /**
                 * Parens
                 */
                states.parens = function(type, stream, state) {
                  if (type == "(") return pushContext(state, stream, "parens");
                  if (type == ")") {
                    if (state.context.prev.type == "parens") {
                      return popContext(state);
                    }
                    if ((stream.string.match(/^[a-z][\w-]*\(/i) && endOfLine(stream)) ||
                        wordIsBlock(firstWordOfLine(stream)) ||
                        /(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(firstWordOfLine(stream)) ||
                        (!stream.string.match(/^-?[a-z][\w-\.\[\]\'\"]*\s*=/) &&
                         wordIsTag(firstWordOfLine(stream)))) {
                      return pushContext(state, stream, "block");
                    }
                    if (stream.string.match(/^[\$-]?[a-z][\w-\.\[\]\'\"]*\s*=/) ||
                        stream.string.match(/^\s*(\(|\)|[0-9])/) ||
                        stream.string.match(/^\s+[a-z][\w-]*\(/i) ||
                        stream.string.match(/^\s+[\$-]?[a-z]/i)) {
                      return pushContext(state, stream, "block", 0);
                    }
                    if (endOfLine(stream)) return pushContext(state, stream, "block");
                    else return pushContext(state, stream, "block", 0);
                  }
                  if (type && type.charAt(0) == "@" && wordIsProperty(stream.current().slice(1))) {
                    override = "variable-2";
                  }
                  if (type == "word") {
                    var word = stream.current();
                    override = wordAsValue(word);
                    if (override == "tag" && tagVariablesRegexp.test(word)) {
                      override = "variable-2";
                    }
                    if (override == "property" || word == "to") override = "atom";
                  }
                  if (type == "variable-name") {
                    return pushContext(state, stream, "variableName");
                  }
                  if (typeIsPseudo(type, stream)) {
                    return pushContext(state, stream, "pseudo");
                  }
                  return state.context.type;
                };
            
            
                /**
                 * Vendor prefixes
                 */
                states.vendorPrefixes = function(type, stream, state) {
                  if (type == "word") {
                    override = "property";
                    return pushContext(state, stream, "block", 0);
                  }
                  return popContext(state);
                };
            
            
                /**
                 * Pseudo
                 */
                states.pseudo = function(type, stream, state) {
                  if (!wordIsProperty(firstWordOfLine(stream.string))) {
                    stream.match(/^[a-z-]+/);
                    override = "variable-3";
                    if (endOfLine(stream)) return pushContext(state, stream, "block");
                    return popContext(state);
                  }
                  return popAndPass(type, stream, state);
                };
            
            
                /**
                 * atBlock
                 */
                states.atBlock = function(type, stream, state) {
                  if (type == "(") return pushContext(state, stream, "atBlock_parens");
                  if (typeIsBlock(type, stream, state)) {
                    return pushContext(state, stream, "block");
                  }
                  if (typeIsInterpolation(type, stream)) {
                    return pushContext(state, stream, "interpolation");
                  }
                  if (type == "word") {
                    var word = stream.current().toLowerCase();
                    if (/^(only|not|and|or)$/.test(word))
                      override = "keyword";
                    else if (documentTypes.hasOwnProperty(word))
                      override = "tag";
                    else if (mediaTypes.hasOwnProperty(word))
                      override = "attribute";
                    else if (mediaFeatures.hasOwnProperty(word))
                      override = "property";
                    else if (nonStandardPropertyKeywords.hasOwnProperty(word))
                      override = "string-2";
                    else override = wordAsValue(stream.current());
                    if (override == "tag" && endOfLine(stream)) {
                      return pushContext(state, stream, "block");
                    }
                  }
                  if (type == "operator" && /^(not|and|or)$/.test(stream.current())) {
                    override = "keyword";
                  }
                  return state.context.type;
                };
            
                states.atBlock_parens = function(type, stream, state) {
                  if (type == "{" || type == "}") return state.context.type;
                  if (type == ")") {
                    if (endOfLine(stream)) return pushContext(state, stream, "block");
                    else return pushContext(state, stream, "atBlock");
                  }
                  if (type == "word") {
                    var word = stream.current().toLowerCase();
                    override = wordAsValue(word);
                    if (/^(max|min)/.test(word)) override = "property";
                    if (override == "tag") {
                      tagVariablesRegexp.test(word) ? override = "variable-2" : override = "atom";
                    }
                    return state.context.type;
                  }
                  return states.atBlock(type, stream, state);
                };
            
            
                /**
                 * Keyframes
                 */
                states.keyframes = function(type, stream, state) {
                  if (stream.indentation() == "0" && ((type == "}" && startOfLine(stream)) || type == "]" || type == "hash"
                                                      || type == "qualifier" || wordIsTag(stream.current()))) {
                    return popAndPass(type, stream, state);
                  }
                  if (type == "{") return pushContext(state, stream, "keyframes");
                  if (type == "}") {
                    if (startOfLine(stream)) return popContext(state, true);
                    else return pushContext(state, stream, "keyframes");
                  }
                  if (type == "unit" && /^[0-9]+\%$/.test(stream.current())) {
                    return pushContext(state, stream, "keyframes");
                  }
                  if (type == "word") {
                    override = wordAsValue(stream.current());
                    if (override == "block-keyword") {
                      override = "keyword";
                      return pushContext(state, stream, "keyframes");
                    }
                  }
                  if (/@(font-face|media|supports|(-moz-)?document)/.test(type)) {
                    return pushContext(state, stream, endOfLine(stream) ? "block" : "atBlock");
                  }
                  if (type == "mixin") {
                    return pushContext(state, stream, "block", 0);
                  }
                  return state.context.type;
                };
            
            
                /**
                 * Interpolation
                 */
                states.interpolation = function(type, stream, state) {
                  if (type == "{") popContext(state) && pushContext(state, stream, "block");
                  if (type == "}") {
                    if (stream.string.match(/^\s*(\.|#|:|\[|\*|&|>|~|\+|\/)/i) ||
                        (stream.string.match(/^\s*[a-z]/i) && wordIsTag(firstWordOfLine(stream)))) {
                      return pushContext(state, stream, "block");
                    }
                    if (!stream.string.match(/^(\{|\s*\&)/) ||
                        stream.match(/\s*[\w-]/,false)) {
                      return pushContext(state, stream, "block", 0);
                    }
                    return pushContext(state, stream, "block");
                  }
                  if (type == "variable-name") {
                    return pushContext(state, stream, "variableName", 0);
                  }
                  if (type == "word") {
                    override = wordAsValue(stream.current());
                    if (override == "tag") override = "atom";
                  }
                  return state.context.type;
                };
            
            
                /**
                 * Extend/s
                 */
                states.extend = function(type, stream, state) {
                  if (type == "[" || type == "=") return "extend";
                  if (type == "]") return popContext(state);
                  if (type == "word") {
                    override = wordAsValue(stream.current());
                    return "extend";
                  }
                  return popContext(state);
                };
            
            
                /**
                 * Variable name
                 */
                states.variableName = function(type, stream, state) {
                  if (type == "string" || type == "[" || type == "]" || stream.current().match(/^(\.|\$)/)) {
                    if (stream.current().match(/^\.[\w-]+/i)) override = "variable-2";
                    if (endOfLine(stream)) return popContext(state);
                    return "variableName";
                  }
                  return popAndPass(type, stream, state);
                };
            
            
                return {
                  startState: function(base) {
                    return {
                      tokenize: null,
                      state: "block",
                      context: new Context("block", base || 0, null)
                    };
                  },
                  token: function(stream, state) {
                    if (!state.tokenize && stream.eatSpace()) return null;
                    style = (state.tokenize || tokenBase)(stream, state);
                    if (style && typeof style == "object") {
                      type = style[1];
                      style = style[0];
                    }
                    override = style;
                    state.state = states[state.state](type, stream, state);
                    return override;
                  },
                  indent: function(state, textAfter, line) {
            
                    var cx = state.context,
                        ch = textAfter && textAfter.charAt(0),
                        indent = cx.indent,
                        lineFirstWord = firstWordOfLine(textAfter),
                        lineIndent = line.length - line.replace(/^\s*/, "").length,
                        prevLineFirstWord = state.context.prev ? state.context.prev.line.firstWord : "",
                        prevLineIndent = state.context.prev ? state.context.prev.line.indent : lineIndent;
            
                    if (cx.prev &&
                        (ch == "}" && (cx.type == "block" || cx.type == "atBlock" || cx.type == "keyframes") ||
                         ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
                         ch == "{" && (cx.type == "at"))) {
                      indent = cx.indent - indentUnit;
                      cx = cx.prev;
                    } else if (!(/(\})/.test(ch))) {
                      if (/@|\$|\d/.test(ch) ||
                          /^\{/.test(textAfter) ||
            /^\s*\/(\/|\*)/.test(textAfter) ||
                          /^\s*\/\*/.test(prevLineFirstWord) ||
                          /^\s*[\w-\.\[\]\'\"]+\s*(\?|:|\+)?=/i.test(textAfter) ||
            /^(\+|-)?[a-z][\w-]*\(/i.test(textAfter) ||
            /^return/.test(textAfter) ||
                          wordIsBlock(lineFirstWord)) {
                        indent = lineIndent;
                      } else if (/(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(ch) || wordIsTag(lineFirstWord)) {
                        if (/\,\s*$/.test(prevLineFirstWord)) {
                          indent = prevLineIndent;
                        } else if (/^\s+/.test(line) && (/(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(prevLineFirstWord) || wordIsTag(prevLineFirstWord))) {
                          indent = lineIndent <= prevLineIndent ? prevLineIndent : prevLineIndent + indentUnit;
                        } else {
                          indent = lineIndent;
                        }
                      } else if (!/,\s*$/.test(line) && (wordIsVendorPrefix(lineFirstWord) || wordIsProperty(lineFirstWord))) {
                        if (wordIsBlock(prevLineFirstWord)) {
                          indent = lineIndent <= prevLineIndent ? prevLineIndent : prevLineIndent + indentUnit;
                        } else if (/^\{/.test(prevLineFirstWord)) {
                          indent = lineIndent <= prevLineIndent ? lineIndent : prevLineIndent + indentUnit;
                        } else if (wordIsVendorPrefix(prevLineFirstWord) || wordIsProperty(prevLineFirstWord)) {
                          indent = lineIndent >= prevLineIndent ? prevLineIndent : lineIndent;
                        } else if (/^(\.|#|:|\[|\*|&|@|\+|\-|>|~|\/)/.test(prevLineFirstWord) ||
                                  /=\s*$/.test(prevLineFirstWord) ||
                                  wordIsTag(prevLineFirstWord) ||
                                  /^\$[\w-\.\[\]\'\"]/.test(prevLineFirstWord)) {
                          indent = prevLineIndent + indentUnit;
                        } else {
                          indent = lineIndent;
                        }
                      }
                    }
                    return indent;
                  },
                  electricChars: "}",
                  lineComment: "//",
                  fold: "indent"
                };
              });
            
              // developer.mozilla.org/en-US/docs/Web/HTML/Element
              var tagKeywords_ = ["a","abbr","address","area","article","aside","audio", "b", "base","bdi", "bdo","bgsound","blockquote","body","br","button","canvas","caption","cite", "code","col","colgroup","data","datalist","dd","del","details","dfn","div", "dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1", "h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe", "img","input","ins","kbd","keygen","label","legend","li","link","main","map", "mark","marquee","menu","menuitem","meta","meter","nav","nobr","noframes", "noscript","object","ol","optgroup","option","output","p","param","pre", "progress","q","rp","rt","ruby","s","samp","script","section","select", "small","source","span","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","track", "u","ul","var","video"];
            
              // github.com/codemirror/CodeMirror/blob/master/mode/css/css.js
              var documentTypes_ = ["domain", "regexp", "url", "url-prefix"];
              var mediaTypes_ = ["all","aural","braille","handheld","print","projection","screen","tty","tv","embossed"];
              var mediaFeatures_ = ["width","min-width","max-width","height","min-height","max-height","device-width","min-device-width","max-device-width","device-height","min-device-height","max-device-height","aspect-ratio","min-aspect-ratio","max-aspect-ratio","device-aspect-ratio","min-device-aspect-ratio","max-device-aspect-ratio","color","min-color","max-color","color-index","min-color-index","max-color-index","monochrome","min-monochrome","max-monochrome","resolution","min-resolution","max-resolution","scan","grid"];
              var propertyKeywords_ = ["align-content","align-items","align-self","alignment-adjust","alignment-baseline","anchor-point","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","azimuth","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","binding","bleed","bookmark-label","bookmark-level","bookmark-state","bookmark-target","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","color","color-profile","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","crop","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","drop-initial-after-adjust","drop-initial-after-align","drop-initial-before-adjust","drop-initial-before-align","drop-initial-size","drop-initial-value","elevation","empty-cells","fit","fit-position","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","float-offset","flow-from","flow-into","font","font-feature-settings","font-family","font-kerning","font-language-override","font-size","font-size-adjust","font-stretch","font-style","font-synthesis","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-weight","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-position","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","inline-box-align","justify-content","left","letter-spacing","line-break","line-height","line-stacking","line-stacking-ruby","line-stacking-shift","line-stacking-strategy","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marker-offset","marks","marquee-direction","marquee-loop","marquee-play-count","marquee-speed","marquee-style","max-height","max-width","min-height","min-width","move-to","nav-down","nav-index","nav-left","nav-right","nav-up","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-style","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","page-policy","pause","pause-after","pause-before","perspective","perspective-origin","pitch","pitch-range","play-during","position","presentation-level","punctuation-trim","quotes","region-break-after","region-break-before","region-break-inside","region-fragment","rendering-intent","resize","rest","rest-after","rest-before","richness","right","rotation","rotation-point","ruby-align","ruby-overhang","ruby-position","ruby-span","shape-image-threshold","shape-inside","shape-margin","shape-outside","size","speak","speak-as","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","string-set","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-height","text-indent","text-justify","text-outline","text-overflow","text-shadow","text-size-adjust","text-space-collapse","text-transform","text-underline-position","text-wrap","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","volume","white-space","widows","width","word-break","word-spacing","word-wrap","z-index","clip-path","clip-rule","mask","enable-background","filter","flood-color","flood-opacity","lighting-color","stop-color","stop-opacity","pointer-events","color-interpolation","color-interpolation-filters","color-rendering","fill","fill-opacity","fill-rule","image-rendering","marker","marker-end","marker-mid","marker-start","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-rendering","baseline-shift","dominant-baseline","glyph-orientation-horizontal","glyph-orientation-vertical","text-anchor","writing-mode","font-smoothing","osx-font-smoothing"];
              var nonStandardPropertyKeywords_ = ["scrollbar-arrow-color","scrollbar-base-color","scrollbar-dark-shadow-color","scrollbar-face-color","scrollbar-highlight-color","scrollbar-shadow-color","scrollbar-3d-light-color","scrollbar-track-color","shape-inside","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","zoom"];
              var fontProperties_ = ["font-family","src","unicode-range","font-variant","font-feature-settings","font-stretch","font-weight","font-style"];
              var colorKeywords_ = ["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"];
              var valueKeywords_ = ["above","absolute","activeborder","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","bullets","button","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","column","compact","condensed","contain","content","content-box","context-menu","continuous","copy","counter","counters","cover","crop","cross","crosshair","currentcolor","cursive","cyclic","dashed","decimal","decimal-leading-zero","default","default-button","destination-atop","destination-in","destination-out","destination-over","devanagari","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","flex","footnotes","forwards","from","geometricPrecision","georgian","graytext","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao","large","larger","left","level","lighter","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","malayalam","match","matrix","matrix3d","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider","media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row-resize","rtl","run-in","running","s-resize","sans-serif","scale","scale3d","scaleX","scaleY","scaleZ","scroll","scrollbar","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","semi-condensed","semi-expanded","separate","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","solid","somali","source-atop","source-in","source-out","source-over","space","spell-out","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","symbolic","symbols","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","x-large","x-small","xor","xx-large","xx-small","bicubic","optimizespeed","grayscale"];
            
              var wordOperatorKeywords_ = ["in","and","or","not","is not","is a","is","isnt","defined","if unless"],
                  blockKeywords_ = ["for","if","else","unless", "from", "to"],
                  commonAtoms_ = ["null","true","false","href","title","type","not-allowed","readonly","disabled"],
                  commonDef_ = ["@font-face", "@keyframes", "@media", "@viewport", "@page", "@host", "@supports", "@block", "@css"];
            
              var hintWords = tagKeywords_.concat(documentTypes_,mediaTypes_,mediaFeatures_,
                                                  propertyKeywords_,nonStandardPropertyKeywords_,
                                                  colorKeywords_,valueKeywords_,fontProperties_,
                                                  wordOperatorKeywords_,blockKeywords_,
                                                  commonAtoms_,commonDef_);
            
              function wordRegexp(words) {
                words = words.sort(function(a,b){return b > a;});
                return new RegExp("^((" + words.join(")|(") + "))\\b");
              }
            
              function keySet(array) {
                var keys = {};
                for (var i = 0; i < array.length; ++i) keys[array[i]] = true;
                return keys;
              }
            
              function escapeRegExp(text) {
                return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
              }
            
              CodeMirror.registerHelper("hintWords", "stylus", hintWords);
              CodeMirror.defineMIME("text/x-styl", "stylus");
            });
            
        • tcl
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Tcl mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/night.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="tcl.js"></script>
            <script src="../../addon/scroll/scrollpastend.js"></script>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Tcl</a>
              </ul>
            </div>
            
            <article>
            <h2>Tcl mode</h2>
            <form><textarea id="code" name="code">
            ##############################################################################################
            ##  ##     whois.tcl for eggdrop by Ford_Lawnmower irc.geekshed.net #Script-Help        ##  ##
            ##############################################################################################
            ## To use this script you must set channel flag +whois (ie .chanset #chan +whois)           ##
            ##############################################################################################
            ##      ____                __                 ###########################################  ##
            ##     / __/___ _ ___ _ ___/ /____ ___   ___   ###########################################  ##
            ##    / _/ / _ `// _ `// _  // __// _ \ / _ \  ###########################################  ##
            ##   /___/ \_, / \_, / \_,_//_/   \___// .__/  ###########################################  ##
            ##        /___/ /___/                 /_/      ###########################################  ##
            ##                                             ###########################################  ##
            ##############################################################################################
            ##  ##                             Start Setup.                                         ##  ##
            ##############################################################################################
            namespace eval whois {
            ## change cmdchar to the trigger you want to use                                        ##  ##
              variable cmdchar "!"
            ## change command to the word trigger you would like to use.                            ##  ##
            ## Keep in mind, This will also change the .chanset +/-command                          ##  ##
              variable command "whois"
            ## change textf to the colors you want for the text.                                    ##  ##
              variable textf "\017\00304"
            ## change tagf to the colors you want for tags:                                         ##  ##
              variable tagf "\017\002"
            ## Change logo to the logo you want at the start of the line.                           ##  ##
              variable logo "\017\00304\002\[\00306W\003hois\00304\]\017"
            ## Change lineout to the results you want. Valid results are channel users modes topic  ##  ##
              variable lineout "channel users modes topic"
            ##############################################################################################
            ##  ##                           End Setup.                                              ## ##
            ##############################################################################################
              variable channel ""
              setudef flag $whois::command
              bind pub -|- [string trimleft $whois::cmdchar]${whois::command} whois::list
              bind raw -|- "311" whois::311
              bind raw -|- "312" whois::312
              bind raw -|- "319" whois::319
              bind raw -|- "317" whois::317
              bind raw -|- "313" whois::multi
              bind raw -|- "310" whois::multi
              bind raw -|- "335" whois::multi
              bind raw -|- "301" whois::301
              bind raw -|- "671" whois::multi
              bind raw -|- "320" whois::multi
              bind raw -|- "401" whois::multi
              bind raw -|- "318" whois::318
              bind raw -|- "307" whois::307
            }
            proc whois::311 {from key text} {
              if {[regexp -- {^[^\s]+\s(.+?)\s(.+?)\s(.+?)\s\*\s\:(.+)$} $text wholematch nick ident host realname]} {
                putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Host:${whois::textf} \
                    $nick \(${ident}@${host}\) ${whois::tagf}Realname:${whois::textf} $realname"
              }
            }
            proc whois::multi {from key text} {
              if {[regexp {\:(.*)$} $text match $key]} {
                putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Note:${whois::textf} [subst $$key]"
                    return 1
              }
            }
            proc whois::312 {from key text} {
              regexp {([^\s]+)\s\:} $text match server
              putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Server:${whois::textf} $server"
            }
            proc whois::319 {from key text} {
              if {[regexp {.+\:(.+)$} $text match channels]} {
                putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Channels:${whois::textf} $channels"
              }
            }
            proc whois::317 {from key text} {
              if {[regexp -- {.*\s(\d+)\s(\d+)\s\:} $text wholematch idle signon]} {
                putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Connected:${whois::textf} \
                    [ctime $signon] ${whois::tagf}Idle:${whois::textf} [duration $idle]"
              }
            }
            proc whois::301 {from key text} {
              if {[regexp {^.+\s[^\s]+\s\:(.*)$} $text match awaymsg]} {
                putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Away:${whois::textf} $awaymsg"
              }
            }
            proc whois::318 {from key text} {
              namespace eval whois {
                    variable channel ""
              }
              variable whois::channel ""
            }
            proc whois::307 {from key text} {
              putserv "PRIVMSG $whois::channel :${whois::logo} ${whois::tagf}Services:${whois::textf} Registered Nick"
            }
            proc whois::list {nick host hand chan text} {
              if {[lsearch -exact [channel info $chan] "+${whois::command}"] != -1} {
                namespace eval whois {
                      variable channel ""
                    }
                variable whois::channel $chan
                putserv "WHOIS $text"
              }
            }
            putlog "\002*Loaded* \017\00304\002\[\00306W\003hois\00304\]\017 \002by \
            Ford_Lawnmower irc.GeekShed.net #Script-Help"
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    theme: "night",
                    lineNumbers: true,
                    indentUnit: 2,
                    scrollPastEnd: true,
                    mode: "text/x-tcl"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-tcl</code>.</p>
            
              </article>
            
          • tcl.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            //tcl mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("tcl", function() {
              function parseWords(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
              var keywords = parseWords("Tcl safe after append array auto_execok auto_import auto_load " +
                    "auto_mkindex auto_mkindex_old auto_qualify auto_reset bgerror " +
                    "binary break catch cd close concat continue dde eof encoding error " +
                    "eval exec exit expr fblocked fconfigure fcopy file fileevent filename " +
                    "filename flush for foreach format gets glob global history http if " +
                    "incr info interp join lappend lindex linsert list llength load lrange " +
                    "lreplace lsearch lset lsort memory msgcat namespace open package parray " +
                    "pid pkg::create pkg_mkIndex proc puts pwd re_syntax read regex regexp " +
                    "registry regsub rename resource return scan seek set socket source split " +
                    "string subst switch tcl_endOfWord tcl_findLibrary tcl_startOfNextWord " +
                    "tcl_wordBreakAfter tcl_startOfPreviousWord tcl_wordBreakBefore tcltest " +
                    "tclvars tell time trace unknown unset update uplevel upvar variable " +
                "vwait");
                var functions = parseWords("if elseif else and not or eq ne in ni for foreach while switch");
                var isOperatorChar = /[+\-*&%=<>!?^\/\|]/;
                function chain(stream, state, f) {
                  state.tokenize = f;
                  return f(stream, state);
                }
                function tokenBase(stream, state) {
                  var beforeParams = state.beforeParams;
                  state.beforeParams = false;
                  var ch = stream.next();
                  if ((ch == '"' || ch == "'") && state.inParams)
                    return chain(stream, state, tokenString(ch));
                  else if (/[\[\]{}\(\),;\.]/.test(ch)) {
                    if (ch == "(" && beforeParams) state.inParams = true;
                    else if (ch == ")") state.inParams = false;
                      return null;
                  }
                  else if (/\d/.test(ch)) {
                    stream.eatWhile(/[\w\.]/);
                    return "number";
                  }
                  else if (ch == "#" && stream.eat("*")) {
                    return chain(stream, state, tokenComment);
                  }
                  else if (ch == "#" && stream.match(/ *\[ *\[/)) {
                    return chain(stream, state, tokenUnparsed);
                  }
                  else if (ch == "#" && stream.eat("#")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                  else if (ch == '"') {
                    stream.skipTo(/"/);
                    return "comment";
                  }
                  else if (ch == "$") {
                    stream.eatWhile(/[$_a-z0-9A-Z\.{:]/);
                    stream.eatWhile(/}/);
                    state.beforeParams = true;
                    return "builtin";
                  }
                  else if (isOperatorChar.test(ch)) {
                    stream.eatWhile(isOperatorChar);
                    return "comment";
                  }
                  else {
                    stream.eatWhile(/[\w\$_{}\xa1-\uffff]/);
                    var word = stream.current().toLowerCase();
                    if (keywords && keywords.propertyIsEnumerable(word))
                      return "keyword";
                    if (functions && functions.propertyIsEnumerable(word)) {
                      state.beforeParams = true;
                      return "keyword";
                    }
                    return null;
                  }
                }
                function tokenString(quote) {
                  return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {
                      end = true;
                      break;
                    }
                    escaped = !escaped && next == "\\";
                  }
                  if (end) state.tokenize = tokenBase;
                    return "string";
                  };
                }
                function tokenComment(stream, state) {
                  var maybeEnd = false, ch;
                  while (ch = stream.next()) {
                    if (ch == "#" && maybeEnd) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    maybeEnd = (ch == "*");
                  }
                  return "comment";
                }
                function tokenUnparsed(stream, state) {
                  var maybeEnd = 0, ch;
                  while (ch = stream.next()) {
                    if (ch == "#" && maybeEnd == 2) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    if (ch == "]")
                      maybeEnd++;
                    else if (ch != " ")
                      maybeEnd = 0;
                  }
                  return "meta";
                }
                return {
                  startState: function() {
                    return {
                      tokenize: tokenBase,
                      beforeParams: false,
                      inParams: false
                    };
                  },
                  token: function(stream, state) {
                    if (stream.eatSpace()) return null;
                    return state.tokenize(stream, state);
                  }
                };
            });
            CodeMirror.defineMIME("text/x-tcl", "tcl");
            
            });
            
        • textile
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Textile mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="textile.js"></script>
            <style>.CodeMirror {background: #f8f8f8;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/marijnh/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class="active" href="#">Textile</a>
              </ul>
            </div>
            
            <article>
                <h2>Textile mode</h2>
                <form><textarea id="code" name="code">
            h1. Textile Mode
            
            A paragraph without formatting.
            
            p. A simple Paragraph.
            
            
            h2. Phrase Modifiers
            
            Here are some simple phrase modifiers: *strong*, _emphasis_, **bold**, and __italic__.
            
            A ??citation??, -deleted text-, +inserted text+, some ^superscript^, and some ~subscript~.
            
            A %span element% and @code element@
            
            A "link":http://example.com, a "link with (alt text)":urlAlias
            
            [urlAlias]http://example.com/
            
            An image: !http://example.com/image.png! and an image with a link: !http://example.com/image.png!:http://example.com
            
            A sentence with a footnote.[123]
            
            fn123. The footnote is defined here.
            
            Registered(r), Trademark(tm), and Copyright(c)
            
            
            h2. Headers
            
            h1. Top level
            h2. Second level
            h3. Third level
            h4. Fourth level
            h5. Fifth level
            h6. Lowest level
            
            
            h2.  Lists
            
            * An unordered list
            ** foo bar
            *** foo bar
            **** foo bar
            ** foo bar
            
            # An ordered list
            ## foo bar
            ### foo bar
            #### foo bar
            ## foo bar
            
            - definition list := description
            - another item    := foo bar
            - spanning ines   :=
                                 foo bar
            
                                 foo bar =:
            
            
            h2. Attributes
            
            Layouts and phrase modifiers can be modified with various kinds of attributes: alignment, CSS ID, CSS class names, language, padding, and CSS styles.
            
            h3. Alignment
            
            div<. left align
            div>. right align
            
            h3. CSS ID and class name
            
            You are a %(my-id#my-classname) rad% person.
            
            h3. Language
            
            p[en_CA]. Strange weather, eh?
            
            h3. Horizontal Padding
            
            p(())). 2em left padding, 3em right padding
            
            h3. CSS styling
            
            p{background: red}. Fire!
            
            
            h2. Table
            
            |_.              Header 1               |_.      Header 2        |
            |{background:#ddd}. Cell with background|         Normal         |
            |\2.         Cell spanning 2 columns                             |
            |/2.         Cell spanning 2 rows       |(cell-class). one       |
            |                                                two             |
            |>.                  Right aligned cell |<. Left aligned cell    |
            
            
            h3. A table with attributes:
            
            table(#prices).
            |Adults|$5|
            |Children|$2|
            
            
            h2. Code blocks
            
            bc.
            function factorial(n) {
                if (n === 0) {
                    return 1;
                }
                return n * factorial(n - 1);
            }
            
            pre..
                            ,,,,,,
                        o#'9MMHb':'-,o,
                     .oH":HH$' "' ' -*R&o,
                    dMMM*""'`'      .oM"HM?.
                   ,MMM'          "HLbd< ?&H\
                  .:MH ."\          ` MM  MM&b
                 . "*H    -        &MMMMMMMMMH:
                 .    dboo        MMMMMMMMMMMM.
                 .   dMMMMMMb      *MMMMMMMMMP.
                 .    MMMMMMMP        *MMMMMP .
                      `#MMMMM           MM6P ,
                   '    `MMMP"           HM*`,
                    '    :MM             .- ,
                     '.   `#?..  .       ..'
                        -.   .         .-
                          ''-.oo,oo.-''
            
            \. _(9>
             \==_)
              -'=
            
            h2. Temporarily disabling textile markup
            
            notextile. Don't __touch this!__
            
            Surround text with double-equals to disable textile inline. Example: Use ==*asterisks*== for *strong* text.
            
            
            h2. HTML
            
            Some block layouts are simply textile versions of HTML tags with the same name, like @div@, @pre@, and @p@. HTML tags can also exist on their own line:
            
            <section>
              <h1>Title</h1>
              <p>Hello!</p>
            </section>
            
            </textarea></form>
                <script>
                    var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                        lineNumbers: true,
                        mode: "text/x-textile"
                    });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-textile</code>.</p>
            
                <p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#textile_*">normal</a>,  <a href="../../test/index.html#verbose,textile_*">verbose</a>.</p>
            
            </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4}, 'textile');
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT('simpleParagraphs',
                  'Some text.',
                  '',
                  'Some more text.');
            
              /*
               * Phrase Modifiers
               */
            
              MT('em',
                  'foo [em _bar_]');
            
              MT('emBoogus',
                  'code_mirror');
            
              MT('strong',
                  'foo [strong *bar*]');
            
              MT('strongBogus',
                  '3 * 3 = 9');
            
              MT('italic',
                  'foo [em __bar__]');
            
              MT('italicBogus',
                  'code__mirror');
            
              MT('bold',
                  'foo [strong **bar**]');
            
              MT('boldBogus',
                  '3 ** 3 = 27');
            
              MT('simpleLink',
                  '[link "CodeMirror":http://codemirror.net]');
            
              MT('referenceLink',
                  '[link "CodeMirror":code_mirror]',
                  'Normal Text.',
                  '[link [[code_mirror]]http://codemirror.net]');
            
              MT('footCite',
                  'foo bar[qualifier [[1]]]');
            
              MT('footCiteBogus',
                  'foo bar[[1a2]]');
            
              MT('special-characters',
                      'Registered [tag (r)], ' +
                      'Trademark [tag (tm)], and ' +
                      'Copyright [tag (c)] 2008');
            
              MT('cite',
                  "A book is [keyword ??The Count of Monte Cristo??] by Dumas.");
            
              MT('additionAndDeletion',
                  'The news networks declared [negative -Al Gore-] ' +
                    '[positive +George W. Bush+] the winner in Florida.');
            
              MT('subAndSup',
                  'f(x, n) = log [builtin ~4~] x [builtin ^n^]');
            
              MT('spanAndCode',
                  'A [quote %span element%] and [atom @code element@]');
            
              MT('spanBogus',
                  'Percentage 25% is not a span.');
            
              MT('citeBogus',
                  'Question? is not a citation.');
            
              MT('codeBogus',
                  'user@example.com');
            
              MT('subBogus',
                  '~username');
            
              MT('supBogus',
                  'foo ^ bar');
            
              MT('deletionBogus',
                  '3 - 3 = 0');
            
              MT('additionBogus',
                  '3 + 3 = 6');
            
              MT('image',
                  'An image: [string !http://www.example.com/image.png!]');
            
              MT('imageWithAltText',
                  'An image: [string !http://www.example.com/image.png (Alt Text)!]');
            
              MT('imageWithUrl',
                  'An image: [string !http://www.example.com/image.png!:http://www.example.com/]');
            
              /*
               * Headers
               */
            
              MT('h1',
                  '[header&header-1 h1. foo]');
            
              MT('h2',
                  '[header&header-2 h2. foo]');
            
              MT('h3',
                  '[header&header-3 h3. foo]');
            
              MT('h4',
                  '[header&header-4 h4. foo]');
            
              MT('h5',
                  '[header&header-5 h5. foo]');
            
              MT('h6',
                  '[header&header-6 h6. foo]');
            
              MT('h7Bogus',
                  'h7. foo');
            
              MT('multipleHeaders',
                  '[header&header-1 h1. Heading 1]',
                  '',
                  'Some text.',
                  '',
                  '[header&header-2 h2. Heading 2]',
                  '',
                  'More text.');
            
              MT('h1inline',
                  '[header&header-1 h1. foo ][header&header-1&em _bar_][header&header-1  baz]');
            
              /*
               * Lists
               */
            
              MT('ul',
                  'foo',
                  'bar',
                  '',
                  '[variable-2 * foo]',
                  '[variable-2 * bar]');
            
              MT('ulNoBlank',
                  'foo',
                  'bar',
                  '[variable-2 * foo]',
                  '[variable-2 * bar]');
            
              MT('ol',
                  'foo',
                  'bar',
                  '',
                  '[variable-2 # foo]',
                  '[variable-2 # bar]');
            
              MT('olNoBlank',
                  'foo',
                  'bar',
                  '[variable-2 # foo]',
                  '[variable-2 # bar]');
            
              MT('ulFormatting',
                  '[variable-2 * ][variable-2&em _foo_][variable-2  bar]',
                  '[variable-2 * ][variable-2&strong *][variable-2&em&strong _foo_]' +
                    '[variable-2&strong *][variable-2  bar]',
                  '[variable-2 * ][variable-2&strong *foo*][variable-2  bar]');
            
              MT('olFormatting',
                  '[variable-2 # ][variable-2&em _foo_][variable-2  bar]',
                  '[variable-2 # ][variable-2&strong *][variable-2&em&strong _foo_]' +
                    '[variable-2&strong *][variable-2  bar]',
                  '[variable-2 # ][variable-2&strong *foo*][variable-2  bar]');
            
              MT('ulNested',
                  '[variable-2 * foo]',
                  '[variable-3 ** bar]',
                  '[keyword *** bar]',
                  '[variable-2 **** bar]',
                  '[variable-3 ** bar]');
            
              MT('olNested',
                  '[variable-2 # foo]',
                  '[variable-3 ## bar]',
                  '[keyword ### bar]',
                  '[variable-2 #### bar]',
                  '[variable-3 ## bar]');
            
              MT('ulNestedWithOl',
                  '[variable-2 * foo]',
                  '[variable-3 ## bar]',
                  '[keyword *** bar]',
                  '[variable-2 #### bar]',
                  '[variable-3 ** bar]');
            
              MT('olNestedWithUl',
                  '[variable-2 # foo]',
                  '[variable-3 ** bar]',
                  '[keyword ### bar]',
                  '[variable-2 **** bar]',
                  '[variable-3 ## bar]');
            
              MT('definitionList',
                  '[number - coffee := Hot ][number&em _and_][number  black]',
                  '',
                  'Normal text.');
            
              MT('definitionListSpan',
                  '[number - coffee :=]',
                  '',
                  '[number Hot ][number&em _and_][number  black =:]',
                  '',
                  'Normal text.');
            
              MT('boo',
                  '[number - dog := woof woof]',
                  '[number - cat := meow meow]',
                  '[number - whale :=]',
                  '[number Whale noises.]',
                  '',
                  '[number Also, ][number&em _splashing_][number . =:]');
            
              /*
               * Attributes
               */
            
              MT('divWithAttribute',
                  '[punctuation div][punctuation&attribute (#my-id)][punctuation . foo bar]');
            
              MT('divWithAttributeAnd2emRightPadding',
                  '[punctuation div][punctuation&attribute (#my-id)((][punctuation . foo bar]');
            
              MT('divWithClassAndId',
                  '[punctuation div][punctuation&attribute (my-class#my-id)][punctuation . foo bar]');
            
              MT('paragraphWithCss',
                  'p[attribute {color:red;}]. foo bar');
            
              MT('paragraphNestedStyles',
                  'p. [strong *foo ][strong&em _bar_][strong *]');
            
              MT('paragraphWithLanguage',
                  'p[attribute [[fr]]]. Parlez-vous français?');
            
              MT('paragraphLeftAlign',
                  'p[attribute <]. Left');
            
              MT('paragraphRightAlign',
                  'p[attribute >]. Right');
            
              MT('paragraphRightAlign',
                  'p[attribute =]. Center');
            
              MT('paragraphJustified',
                  'p[attribute <>]. Justified');
            
              MT('paragraphWithLeftIndent1em',
                  'p[attribute (]. Left');
            
              MT('paragraphWithRightIndent1em',
                  'p[attribute )]. Right');
            
              MT('paragraphWithLeftIndent2em',
                  'p[attribute ((]. Left');
            
              MT('paragraphWithRightIndent2em',
                  'p[attribute ))]. Right');
            
              MT('paragraphWithLeftIndent3emRightIndent2em',
                  'p[attribute ((())]. Right');
            
              MT('divFormatting',
                  '[punctuation div. ][punctuation&strong *foo ]' +
                    '[punctuation&strong&em _bar_][punctuation&strong *]');
            
              MT('phraseModifierAttributes',
                  'p[attribute (my-class)]. This is a paragraph that has a class and' +
                  ' this [em _][em&attribute (#special-phrase)][em emphasized phrase_]' +
                  ' has an id.');
            
              MT('linkWithClass',
                  '[link "(my-class). This is a link with class":http://redcloth.org]');
            
              /*
               * Layouts
               */
            
              MT('paragraphLayouts',
                  'p. This is one paragraph.',
                  '',
                  'p. This is another.');
            
              MT('div',
                  '[punctuation div. foo bar]');
            
              MT('pre',
                  '[operator pre. Text]');
            
              MT('bq.',
                  '[bracket bq. foo bar]',
                  '',
                  'Normal text.');
            
              MT('footnote',
                  '[variable fn123. foo ][variable&strong *bar*]');
            
              /*
               * Spanning Layouts
               */
            
              MT('bq..ThenParagraph',
                  '[bracket bq.. foo bar]',
                  '',
                  '[bracket More quote.]',
                  'p. Normal Text');
            
              MT('bq..ThenH1',
                  '[bracket bq.. foo bar]',
                  '',
                  '[bracket More quote.]',
                  '[header&header-1 h1. Header Text]');
            
              MT('bc..ThenParagraph',
                  '[atom bc.. # Some ruby code]',
                  '[atom obj = {foo: :bar}]',
                  '[atom puts obj]',
                  '',
                  '[atom obj[[:love]] = "*love*"]',
                  '[atom puts obj.love.upcase]',
                  '',
                  'p. Normal text.');
            
              MT('fn1..ThenParagraph',
                  '[variable fn1.. foo bar]',
                  '',
                  '[variable More.]',
                  'p. Normal Text');
            
              MT('pre..ThenParagraph',
                  '[operator pre.. foo bar]',
                  '',
                  '[operator More.]',
                  'p. Normal Text');
            
              /*
               * Tables
               */
            
              MT('table',
                  '[variable-3&operator |_. name |_. age|]',
                  '[variable-3 |][variable-3&strong *Walter*][variable-3 |   5  |]',
                  '[variable-3 |Florence|   6  |]',
                  '',
                  'p. Normal text.');
            
              MT('tableWithAttributes',
                  '[variable-3&operator |_. name |_. age|]',
                  '[variable-3 |][variable-3&attribute /2.][variable-3  Jim |]',
                  '[variable-3 |][variable-3&attribute \\2{color: red}.][variable-3  Sam |]');
            
              /*
               * HTML
               */
            
              MT('html',
                  '[comment <div id="wrapper">]',
                  '[comment <section id="introduction">]',
                  '',
                  '[header&header-1 h1. Welcome]',
                  '',
                  '[variable-2 * Item one]',
                  '[variable-2 * Item two]',
                  '',
                  '[comment <a href="http://example.com">Example</a>]',
                  '',
                  '[comment </section>]',
                  '[comment </div>]');
            
              MT('inlineHtml',
                  'I can use HTML directly in my [comment <span class="youbetcha">Textile</span>].');
            
              /*
               * No-Textile
               */
            
              MT('notextile',
                '[string-2 notextile. *No* formatting]');
            
              MT('notextileInline',
                  'Use [string-2 ==*asterisks*==] for [strong *strong*] text.');
            
              MT('notextileWithPre',
                  '[operator pre. *No* formatting]');
            
              MT('notextileWithSpanningPre',
                  '[operator pre.. *No* formatting]',
                  '',
                  '[operator *No* formatting]');
            
              /* Only toggling phrases between non-word chars. */
            
              MT('phrase-in-word',
                 'foo_bar_baz');
            
              MT('phrase-non-word',
                 '[negative -x-] aaa-bbb ccc-ddd [negative -eee-] fff [negative -ggg-]');
            
              MT('phrase-lone-dash',
                 'foo - bar - baz');
            })();
            
          • textile.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") { // CommonJS
                mod(require("../../lib/codemirror"));
              } else if (typeof define == "function" && define.amd) { // AMD
                define(["../../lib/codemirror"], mod);
              } else { // Plain browser env
                mod(CodeMirror);
              }
            })(function(CodeMirror) {
              "use strict";
            
              var TOKEN_STYLES = {
                addition: "positive",
                attributes: "attribute",
                bold: "strong",
                cite: "keyword",
                code: "atom",
                definitionList: "number",
                deletion: "negative",
                div: "punctuation",
                em: "em",
                footnote: "variable",
                footCite: "qualifier",
                header: "header",
                html: "comment",
                image: "string",
                italic: "em",
                link: "link",
                linkDefinition: "link",
                list1: "variable-2",
                list2: "variable-3",
                list3: "keyword",
                notextile: "string-2",
                pre: "operator",
                p: "property",
                quote: "bracket",
                span: "quote",
                specialChar: "tag",
                strong: "strong",
                sub: "builtin",
                sup: "builtin",
                table: "variable-3",
                tableHeading: "operator"
              };
            
              function startNewLine(stream, state) {
                state.mode = Modes.newLayout;
                state.tableHeading = false;
            
                if (state.layoutType === "definitionList" && state.spanningLayout &&
                    stream.match(RE("definitionListEnd"), false))
                  state.spanningLayout = false;
              }
            
              function handlePhraseModifier(stream, state, ch) {
                if (ch === "_") {
                  if (stream.eat("_"))
                    return togglePhraseModifier(stream, state, "italic", /__/, 2);
                  else
                    return togglePhraseModifier(stream, state, "em", /_/, 1);
                }
            
                if (ch === "*") {
                  if (stream.eat("*")) {
                    return togglePhraseModifier(stream, state, "bold", /\*\*/, 2);
                  }
                  return togglePhraseModifier(stream, state, "strong", /\*/, 1);
                }
            
                if (ch === "[") {
                  if (stream.match(/\d+\]/)) state.footCite = true;
                  return tokenStyles(state);
                }
            
                if (ch === "(") {
                  var spec = stream.match(/^(r|tm|c)\)/);
                  if (spec)
                    return tokenStylesWith(state, TOKEN_STYLES.specialChar);
                }
            
                if (ch === "<" && stream.match(/(\w+)[^>]+>[^<]+<\/\1>/))
                  return tokenStylesWith(state, TOKEN_STYLES.html);
            
                if (ch === "?" && stream.eat("?"))
                  return togglePhraseModifier(stream, state, "cite", /\?\?/, 2);
            
                if (ch === "=" && stream.eat("="))
                  return togglePhraseModifier(stream, state, "notextile", /==/, 2);
            
                if (ch === "-" && !stream.eat("-"))
                  return togglePhraseModifier(stream, state, "deletion", /-/, 1);
            
                if (ch === "+")
                  return togglePhraseModifier(stream, state, "addition", /\+/, 1);
            
                if (ch === "~")
                  return togglePhraseModifier(stream, state, "sub", /~/, 1);
            
                if (ch === "^")
                  return togglePhraseModifier(stream, state, "sup", /\^/, 1);
            
                if (ch === "%")
                  return togglePhraseModifier(stream, state, "span", /%/, 1);
            
                if (ch === "@")
                  return togglePhraseModifier(stream, state, "code", /@/, 1);
            
                if (ch === "!") {
                  var type = togglePhraseModifier(stream, state, "image", /(?:\([^\)]+\))?!/, 1);
                  stream.match(/^:\S+/); // optional Url portion
                  return type;
                }
                return tokenStyles(state);
              }
            
              function togglePhraseModifier(stream, state, phraseModifier, closeRE, openSize) {
                var charBefore = stream.pos > openSize ? stream.string.charAt(stream.pos - openSize - 1) : null;
                var charAfter = stream.peek();
                if (state[phraseModifier]) {
                  if ((!charAfter || /\W/.test(charAfter)) && charBefore && /\S/.test(charBefore)) {
                    var type = tokenStyles(state);
                    state[phraseModifier] = false;
                    return type;
                  }
                } else if ((!charBefore || /\W/.test(charBefore)) && charAfter && /\S/.test(charAfter) &&
                           stream.match(new RegExp("^.*\\S" + closeRE.source + "(?:\\W|$)"), false)) {
                  state[phraseModifier] = true;
                  state.mode = Modes.attributes;
                }
                return tokenStyles(state);
              };
            
              function tokenStyles(state) {
                var disabled = textileDisabled(state);
                if (disabled) return disabled;
            
                var styles = [];
                if (state.layoutType) styles.push(TOKEN_STYLES[state.layoutType]);
            
                styles = styles.concat(activeStyles(
                  state, "addition", "bold", "cite", "code", "deletion", "em", "footCite",
                  "image", "italic", "link", "span", "strong", "sub", "sup", "table", "tableHeading"));
            
                if (state.layoutType === "header")
                  styles.push(TOKEN_STYLES.header + "-" + state.header);
            
                return styles.length ? styles.join(" ") : null;
              }
            
              function textileDisabled(state) {
                var type = state.layoutType;
            
                switch(type) {
                case "notextile":
                case "code":
                case "pre":
                  return TOKEN_STYLES[type];
                default:
                  if (state.notextile)
                    return TOKEN_STYLES.notextile + (type ? (" " + TOKEN_STYLES[type]) : "");
                  return null;
                }
              }
            
              function tokenStylesWith(state, extraStyles) {
                var disabled = textileDisabled(state);
                if (disabled) return disabled;
            
                var type = tokenStyles(state);
                if (extraStyles)
                  return type ? (type + " " + extraStyles) : extraStyles;
                else
                  return type;
              }
            
              function activeStyles(state) {
                var styles = [];
                for (var i = 1; i < arguments.length; ++i) {
                  if (state[arguments[i]])
                    styles.push(TOKEN_STYLES[arguments[i]]);
                }
                return styles;
              }
            
              function blankLine(state) {
                var spanningLayout = state.spanningLayout, type = state.layoutType;
            
                for (var key in state) if (state.hasOwnProperty(key))
                  delete state[key];
            
                state.mode = Modes.newLayout;
                if (spanningLayout) {
                  state.layoutType = type;
                  state.spanningLayout = true;
                }
              }
            
              var REs = {
                cache: {},
                single: {
                  bc: "bc",
                  bq: "bq",
                  definitionList: /- [^(?::=)]+:=+/,
                  definitionListEnd: /.*=:\s*$/,
                  div: "div",
                  drawTable: /\|.*\|/,
                  foot: /fn\d+/,
                  header: /h[1-6]/,
                  html: /\s*<(?:\/)?(\w+)(?:[^>]+)?>(?:[^<]+<\/\1>)?/,
                  link: /[^"]+":\S/,
                  linkDefinition: /\[[^\s\]]+\]\S+/,
                  list: /(?:#+|\*+)/,
                  notextile: "notextile",
                  para: "p",
                  pre: "pre",
                  table: "table",
                  tableCellAttributes: /[\/\\]\d+/,
                  tableHeading: /\|_\./,
                  tableText: /[^"_\*\[\(\?\+~\^%@|-]+/,
                  text: /[^!"_=\*\[\(<\?\+~\^%@-]+/
                },
                attributes: {
                  align: /(?:<>|<|>|=)/,
                  selector: /\([^\(][^\)]+\)/,
                  lang: /\[[^\[\]]+\]/,
                  pad: /(?:\(+|\)+){1,2}/,
                  css: /\{[^\}]+\}/
                },
                createRe: function(name) {
                  switch (name) {
                  case "drawTable":
                    return REs.makeRe("^", REs.single.drawTable, "$");
                  case "html":
                    return REs.makeRe("^", REs.single.html, "(?:", REs.single.html, ")*", "$");
                  case "linkDefinition":
                    return REs.makeRe("^", REs.single.linkDefinition, "$");
                  case "listLayout":
                    return REs.makeRe("^", REs.single.list, RE("allAttributes"), "*\\s+");
                  case "tableCellAttributes":
                    return REs.makeRe("^", REs.choiceRe(REs.single.tableCellAttributes,
                                                        RE("allAttributes")), "+\\.");
                  case "type":
                    return REs.makeRe("^", RE("allTypes"));
                  case "typeLayout":
                    return REs.makeRe("^", RE("allTypes"), RE("allAttributes"),
                                      "*\\.\\.?", "(\\s+|$)");
                  case "attributes":
                    return REs.makeRe("^", RE("allAttributes"), "+");
            
                  case "allTypes":
                    return REs.choiceRe(REs.single.div, REs.single.foot,
                                        REs.single.header, REs.single.bc, REs.single.bq,
                                        REs.single.notextile, REs.single.pre, REs.single.table,
                                        REs.single.para);
            
                  case "allAttributes":
                    return REs.choiceRe(REs.attributes.selector, REs.attributes.css,
                                        REs.attributes.lang, REs.attributes.align, REs.attributes.pad);
            
                  default:
                    return REs.makeRe("^", REs.single[name]);
                  }
                },
                makeRe: function() {
                  var pattern = "";
                  for (var i = 0; i < arguments.length; ++i) {
                    var arg = arguments[i];
                    pattern += (typeof arg === "string") ? arg : arg.source;
                  }
                  return new RegExp(pattern);
                },
                choiceRe: function() {
                  var parts = [arguments[0]];
                  for (var i = 1; i < arguments.length; ++i) {
                    parts[i * 2 - 1] = "|";
                    parts[i * 2] = arguments[i];
                  }
            
                  parts.unshift("(?:");
                  parts.push(")");
                  return REs.makeRe.apply(null, parts);
                }
              };
            
              function RE(name) {
                return (REs.cache[name] || (REs.cache[name] = REs.createRe(name)));
              }
            
              var Modes = {
                newLayout: function(stream, state) {
                  if (stream.match(RE("typeLayout"), false)) {
                    state.spanningLayout = false;
                    return (state.mode = Modes.blockType)(stream, state);
                  }
                  var newMode;
                  if (!textileDisabled(state)) {
                    if (stream.match(RE("listLayout"), false))
                      newMode = Modes.list;
                    else if (stream.match(RE("drawTable"), false))
                      newMode = Modes.table;
                    else if (stream.match(RE("linkDefinition"), false))
                      newMode = Modes.linkDefinition;
                    else if (stream.match(RE("definitionList")))
                      newMode = Modes.definitionList;
                    else if (stream.match(RE("html"), false))
                      newMode = Modes.html;
                  }
                  return (state.mode = (newMode || Modes.text))(stream, state);
                },
            
                blockType: function(stream, state) {
                  var match, type;
                  state.layoutType = null;
            
                  if (match = stream.match(RE("type")))
                    type = match[0];
                  else
                    return (state.mode = Modes.text)(stream, state);
            
                  if (match = type.match(RE("header"))) {
                    state.layoutType = "header";
                    state.header = parseInt(match[0][1]);
                  } else if (type.match(RE("bq"))) {
                    state.layoutType = "quote";
                  } else if (type.match(RE("bc"))) {
                    state.layoutType = "code";
                  } else if (type.match(RE("foot"))) {
                    state.layoutType = "footnote";
                  } else if (type.match(RE("notextile"))) {
                    state.layoutType = "notextile";
                  } else if (type.match(RE("pre"))) {
                    state.layoutType = "pre";
                  } else if (type.match(RE("div"))) {
                    state.layoutType = "div";
                  } else if (type.match(RE("table"))) {
                    state.layoutType = "table";
                  }
            
                  state.mode = Modes.attributes;
                  return tokenStyles(state);
                },
            
                text: function(stream, state) {
                  if (stream.match(RE("text"))) return tokenStyles(state);
            
                  var ch = stream.next();
                  if (ch === '"')
                    return (state.mode = Modes.link)(stream, state);
                  return handlePhraseModifier(stream, state, ch);
                },
            
                attributes: function(stream, state) {
                  state.mode = Modes.layoutLength;
            
                  if (stream.match(RE("attributes")))
                    return tokenStylesWith(state, TOKEN_STYLES.attributes);
                  else
                    return tokenStyles(state);
                },
            
                layoutLength: function(stream, state) {
                  if (stream.eat(".") && stream.eat("."))
                    state.spanningLayout = true;
            
                  state.mode = Modes.text;
                  return tokenStyles(state);
                },
            
                list: function(stream, state) {
                  var match = stream.match(RE("list"));
                  state.listDepth = match[0].length;
                  var listMod = (state.listDepth - 1) % 3;
                  if (!listMod)
                    state.layoutType = "list1";
                  else if (listMod === 1)
                    state.layoutType = "list2";
                  else
                    state.layoutType = "list3";
            
                  state.mode = Modes.attributes;
                  return tokenStyles(state);
                },
            
                link: function(stream, state) {
                  state.mode = Modes.text;
                  if (stream.match(RE("link"))) {
                    stream.match(/\S+/);
                    return tokenStylesWith(state, TOKEN_STYLES.link);
                  }
                  return tokenStyles(state);
                },
            
                linkDefinition: function(stream, state) {
                  stream.skipToEnd();
                  return tokenStylesWith(state, TOKEN_STYLES.linkDefinition);
                },
            
                definitionList: function(stream, state) {
                  stream.match(RE("definitionList"));
            
                  state.layoutType = "definitionList";
            
                  if (stream.match(/\s*$/))
                    state.spanningLayout = true;
                  else
                    state.mode = Modes.attributes;
            
                  return tokenStyles(state);
                },
            
                html: function(stream, state) {
                  stream.skipToEnd();
                  return tokenStylesWith(state, TOKEN_STYLES.html);
                },
            
                table: function(stream, state) {
                  state.layoutType = "table";
                  return (state.mode = Modes.tableCell)(stream, state);
                },
            
                tableCell: function(stream, state) {
                  if (stream.match(RE("tableHeading")))
                    state.tableHeading = true;
                  else
                    stream.eat("|");
            
                  state.mode = Modes.tableCellAttributes;
                  return tokenStyles(state);
                },
            
                tableCellAttributes: function(stream, state) {
                  state.mode = Modes.tableText;
            
                  if (stream.match(RE("tableCellAttributes")))
                    return tokenStylesWith(state, TOKEN_STYLES.attributes);
                  else
                    return tokenStyles(state);
                },
            
                tableText: function(stream, state) {
                  if (stream.match(RE("tableText")))
                    return tokenStyles(state);
            
                  if (stream.peek() === "|") { // end of cell
                    state.mode = Modes.tableCell;
                    return tokenStyles(state);
                  }
                  return handlePhraseModifier(stream, state, stream.next());
                }
              };
            
              CodeMirror.defineMode("textile", function() {
                return {
                  startState: function() {
                    return { mode: Modes.newLayout };
                  },
                  token: function(stream, state) {
                    if (stream.sol()) startNewLine(stream, state);
                    return state.mode(stream, state);
                  },
                  blankLine: blankLine
                };
              });
            
              CodeMirror.defineMIME("text/x-textile", "textile");
            });
            
        • tiddlywiki
          • index.html
            <!doctype html>
            
            <title>CodeMirror: TiddlyWiki mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="tiddlywiki.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="tiddlywiki.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">TiddlyWiki</a>
              </ul>
            </div>
            
            <article>
            <h2>TiddlyWiki mode</h2>
            
            
            <div><textarea id="code" name="code">
            !TiddlyWiki Formatting
            * Rendered versions can be found at: http://www.tiddlywiki.com/#Reference
            
            |!Option            | !Syntax            |
            |bold font          | ''bold''           |
            |italic type        | //italic//         |
            |underlined text    | __underlined__     |
            |strikethrough text | --strikethrough--  |
            |superscript text   | super^^script^^    |
            |subscript text     | sub~~script~~      |
            |highlighted text   | @@highlighted@@    |
            |preformatted text  | {{{preformatted}}} |
            
            !Block Elements
            <<<
            !Heading 1
            
            !!Heading 2
            
            !!!Heading 3
            
            !!!!Heading 4
            
            !!!!!Heading 5
            <<<
            
            !!Lists
            <<<
            * unordered list, level 1
            ** unordered list, level 2
            *** unordered list, level 3
            
            # ordered list, level 1
            ## ordered list, level 2
            ### unordered list, level 3
            
            ; definition list, term
            : definition list, description
            <<<
            
            !!Blockquotes
            <<<
            > blockquote, level 1
            >> blockquote, level 2
            >>> blockquote, level 3
            
            > blockquote
            <<<
            
            !!Preformatted Text
            <<<
            {{{
            preformatted (e.g. code)
            }}}
            <<<
            
            !!Code Sections
            <<<
            {{{
            Text style code
            }}}
            
            //{{{
            JS styled code. TiddlyWiki mixed mode should support highlighter switching in the future.
            //}}}
            
            <!--{{{-->
            XML styled code. TiddlyWiki mixed mode should support highlighter switching in the future.
            <!--}}}-->
            <<<
            
            !!Tables
            <<<
            |CssClass|k
            |!heading column 1|!heading column 2|
            |row 1, column 1|row 1, column 2|
            |row 2, column 1|row 2, column 2|
            |>|COLSPAN|
            |ROWSPAN| ... |
            |~| ... |
            |CssProperty:value;...| ... |
            |caption|c
            
            ''Annotation:''
            * The {{{>}}} marker creates a "colspan", causing the current cell to merge with the one to the right.
            * The {{{~}}} marker creates a "rowspan", causing the current cell to merge with the one above.
            <<<
            !!Images /% TODO %/
            cf. [[TiddlyWiki.com|http://www.tiddlywiki.com/#EmbeddedImages]]
            
            !Hyperlinks
            * [[WikiWords|WikiWord]] are automatically transformed to hyperlinks to the respective tiddler
            ** the automatic transformation can be suppressed by preceding the respective WikiWord with a tilde ({{{~}}}): {{{~WikiWord}}}
            * [[PrettyLinks]] are enclosed in square brackets and contain the desired tiddler name: {{{[[tiddler name]]}}}
            ** optionally, a custom title or description can be added, separated by a pipe character ({{{|}}}): {{{[[title|target]]}}}<br>'''N.B.:''' In this case, the target can also be any website (i.e. URL).
            
            !Custom Styling
            * {{{@@CssProperty:value;CssProperty:value;...@@}}}<br>''N.B.:'' CSS color definitions should use lowercase letters to prevent the inadvertent creation of WikiWords.
            * <html><code>{{customCssClass{...}}}</code></html>
            * raw HTML can be inserted by enclosing the respective code in HTML tags: {{{<html> ... </html>}}}
            
            !Special Markers
            * {{{<br>}}} forces a manual line break
            * {{{----}}} creates a horizontal ruler
            * [[HTML entities|http://www.tiddlywiki.com/#HtmlEntities]]
            * [[HTML entities local|HtmlEntities]]
            * {{{<<macroName>>}}} calls the respective [[macro|Macros]]
            * To hide text within a tiddler so that it is not displayed, it can be wrapped in {{{/%}}} and {{{%/}}}.<br/>This can be a useful trick for hiding drafts or annotating complex markup.
            * To prevent wiki markup from taking effect for a particular section, that section can be enclosed in three double quotes: e.g. {{{"""WikiWord"""}}}.
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: 'tiddlywiki',      
                    lineNumbers: true,
                    matchBrackets: true
                  });
                </script>
            
                <p>TiddlyWiki mode supports a single configuration.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-tiddlywiki</code>.</p>
              </article>
            
          • tiddlywiki.css
            span.cm-underlined {
              text-decoration: underline;
            }
            span.cm-strikethrough {
              text-decoration: line-through;
            }
            span.cm-brace {
              color: #170;
              font-weight: bold;
            }
            span.cm-table {
              color: blue;
              font-weight: bold;
            }
            
          • tiddlywiki.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /***
                |''Name''|tiddlywiki.js|
                |''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror|
                |''Author''|PMario|
                |''Version''|0.1.7|
                |''Status''|''stable''|
                |''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]|
                |''Documentation''|http://codemirror.tiddlyspace.com/|
                |''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|
                |''CoreVersion''|2.5.0|
                |''Requires''|codemirror.js|
                |''Keywords''|syntax highlighting color code mirror codemirror|
                ! Info
                CoreVersion parameter is needed for TiddlyWiki only!
            ***/
            //{{{
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("tiddlywiki", function () {
              // Tokenizer
              var textwords = {};
            
              var keywords = function () {
                function kw(type) {
                  return { type: type, style: "macro"};
                }
                return {
                  "allTags": kw('allTags'), "closeAll": kw('closeAll'), "list": kw('list'),
                  "newJournal": kw('newJournal'), "newTiddler": kw('newTiddler'),
                  "permaview": kw('permaview'), "saveChanges": kw('saveChanges'),
                  "search": kw('search'), "slider": kw('slider'),   "tabs": kw('tabs'),
                  "tag": kw('tag'), "tagging": kw('tagging'),       "tags": kw('tags'),
                  "tiddler": kw('tiddler'), "timeline": kw('timeline'),
                  "today": kw('today'), "version": kw('version'),   "option": kw('option'),
            
                  "with": kw('with'),
                  "filter": kw('filter')
                };
              }();
            
              var isSpaceName = /[\w_\-]/i,
              reHR = /^\-\-\-\-+$/,                                 // <hr>
              reWikiCommentStart = /^\/\*\*\*$/,            // /***
              reWikiCommentStop = /^\*\*\*\/$/,             // ***/
              reBlockQuote = /^<<<$/,
            
              reJsCodeStart = /^\/\/\{\{\{$/,                       // //{{{ js block start
              reJsCodeStop = /^\/\/\}\}\}$/,                        // //}}} js stop
              reXmlCodeStart = /^<!--\{\{\{-->$/,           // xml block start
              reXmlCodeStop = /^<!--\}\}\}-->$/,            // xml stop
            
              reCodeBlockStart = /^\{\{\{$/,                        // {{{ TW text div block start
              reCodeBlockStop = /^\}\}\}$/,                 // }}} TW text stop
            
              reUntilCodeStop = /.*?\}\}\}/;
            
              function chain(stream, state, f) {
                state.tokenize = f;
                return f(stream, state);
              }
            
              function jsTokenBase(stream, state) {
                var sol = stream.sol(), ch;
            
                state.block = false;        // indicates the start of a code block.
            
                ch = stream.peek();         // don't eat, to make matching simpler
            
                // check start of  blocks
                if (sol && /[<\/\*{}\-]/.test(ch)) {
                  if (stream.match(reCodeBlockStart)) {
                    state.block = true;
                    return chain(stream, state, twTokenCode);
                  }
                  if (stream.match(reBlockQuote)) {
                    return 'quote';
                  }
                  if (stream.match(reWikiCommentStart) || stream.match(reWikiCommentStop)) {
                    return 'comment';
                  }
                  if (stream.match(reJsCodeStart) || stream.match(reJsCodeStop) || stream.match(reXmlCodeStart) || stream.match(reXmlCodeStop)) {
                    return 'comment';
                  }
                  if (stream.match(reHR)) {
                    return 'hr';
                  }
                } // sol
                ch = stream.next();
            
                if (sol && /[\/\*!#;:>|]/.test(ch)) {
                  if (ch == "!") { // tw header
                    stream.skipToEnd();
                    return "header";
                  }
                  if (ch == "*") { // tw list
                    stream.eatWhile('*');
                    return "comment";
                  }
                  if (ch == "#") { // tw numbered list
                    stream.eatWhile('#');
                    return "comment";
                  }
                  if (ch == ";") { // definition list, term
                    stream.eatWhile(';');
                    return "comment";
                  }
                  if (ch == ":") { // definition list, description
                    stream.eatWhile(':');
                    return "comment";
                  }
                  if (ch == ">") { // single line quote
                    stream.eatWhile(">");
                    return "quote";
                  }
                  if (ch == '|') {
                    return 'header';
                  }
                }
            
                if (ch == '{' && stream.match(/\{\{/)) {
                  return chain(stream, state, twTokenCode);
                }
            
                // rudimentary html:// file:// link matching. TW knows much more ...
                if (/[hf]/i.test(ch)) {
                  if (/[ti]/i.test(stream.peek()) && stream.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i)) {
                    return "link";
                  }
                }
                // just a little string indicator, don't want to have the whole string covered
                if (ch == '"') {
                  return 'string';
                }
                if (ch == '~') {    // _no_ CamelCase indicator should be bold
                  return 'brace';
                }
                if (/[\[\]]/.test(ch)) { // check for [[..]]
                  if (stream.peek() == ch) {
                    stream.next();
                    return 'brace';
                  }
                }
                if (ch == "@") {    // check for space link. TODO fix @@...@@ highlighting
                  stream.eatWhile(isSpaceName);
                  return "link";
                }
                if (/\d/.test(ch)) {        // numbers
                  stream.eatWhile(/\d/);
                  return "number";
                }
                if (ch == "/") { // tw invisible comment
                  if (stream.eat("%")) {
                    return chain(stream, state, twTokenComment);
                  }
                  else if (stream.eat("/")) { //
                    return chain(stream, state, twTokenEm);
                  }
                }
                if (ch == "_") { // tw underline
                  if (stream.eat("_")) {
                    return chain(stream, state, twTokenUnderline);
                  }
                }
                // strikethrough and mdash handling
                if (ch == "-") {
                  if (stream.eat("-")) {
                    // if strikethrough looks ugly, change CSS.
                    if (stream.peek() != ' ')
                      return chain(stream, state, twTokenStrike);
                    // mdash
                    if (stream.peek() == ' ')
                      return 'brace';
                  }
                }
                if (ch == "'") { // tw bold
                  if (stream.eat("'")) {
                    return chain(stream, state, twTokenStrong);
                  }
                }
                if (ch == "<") { // tw macro
                  if (stream.eat("<")) {
                    return chain(stream, state, twTokenMacro);
                  }
                }
                else {
                  return null;
                }
            
                // core macro handling
                stream.eatWhile(/[\w\$_]/);
                var word = stream.current(),
                known = textwords.propertyIsEnumerable(word) && textwords[word];
            
                return known ? known.style : null;
              } // jsTokenBase()
            
              // tw invisible comment
              function twTokenComment(stream, state) {
                var maybeEnd = false,
                ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = jsTokenBase;
                    break;
                  }
                  maybeEnd = (ch == "%");
                }
                return "comment";
              }
            
              // tw strong / bold
              function twTokenStrong(stream, state) {
                var maybeEnd = false,
                ch;
                while (ch = stream.next()) {
                  if (ch == "'" && maybeEnd) {
                    state.tokenize = jsTokenBase;
                    break;
                  }
                  maybeEnd = (ch == "'");
                }
                return "strong";
              }
            
              // tw code
              function twTokenCode(stream, state) {
                var sb = state.block;
            
                if (sb && stream.current()) {
                  return "comment";
                }
            
                if (!sb && stream.match(reUntilCodeStop)) {
                  state.tokenize = jsTokenBase;
                  return "comment";
                }
            
                if (sb && stream.sol() && stream.match(reCodeBlockStop)) {
                  state.tokenize = jsTokenBase;
                  return "comment";
                }
            
                stream.next();
                return "comment";
              }
            
              // tw em / italic
              function twTokenEm(stream, state) {
                var maybeEnd = false,
                ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = jsTokenBase;
                    break;
                  }
                  maybeEnd = (ch == "/");
                }
                return "em";
              }
            
              // tw underlined text
              function twTokenUnderline(stream, state) {
                var maybeEnd = false,
                ch;
                while (ch = stream.next()) {
                  if (ch == "_" && maybeEnd) {
                    state.tokenize = jsTokenBase;
                    break;
                  }
                  maybeEnd = (ch == "_");
                }
                return "underlined";
              }
            
              // tw strike through text looks ugly
              // change CSS if needed
              function twTokenStrike(stream, state) {
                var maybeEnd = false, ch;
            
                while (ch = stream.next()) {
                  if (ch == "-" && maybeEnd) {
                    state.tokenize = jsTokenBase;
                    break;
                  }
                  maybeEnd = (ch == "-");
                }
                return "strikethrough";
              }
            
              // macro
              function twTokenMacro(stream, state) {
                var ch, word, known;
            
                if (stream.current() == '<<') {
                  return 'macro';
                }
            
                ch = stream.next();
                if (!ch) {
                  state.tokenize = jsTokenBase;
                  return null;
                }
                if (ch == ">") {
                  if (stream.peek() == '>') {
                    stream.next();
                    state.tokenize = jsTokenBase;
                    return "macro";
                  }
                }
            
                stream.eatWhile(/[\w\$_]/);
                word = stream.current();
                known = keywords.propertyIsEnumerable(word) && keywords[word];
            
                if (known) {
                  return known.style, word;
                }
                else {
                  return null, word;
                }
              }
            
              // Interface
              return {
                startState: function () {
                  return {
                    tokenize: jsTokenBase,
                    indented: 0,
                    level: 0
                  };
                },
            
                token: function (stream, state) {
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
                  return style;
                },
            
                electricChars: ""
              };
            });
            
            CodeMirror.defineMIME("text/x-tiddlywiki", "tiddlywiki");
            });
            
            //}}}
            
        • tiki
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Tiki wiki mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="tiki.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="tiki.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Tiki wiki</a>
              </ul>
            </div>
            
            <article>
            <h2>Tiki wiki mode</h2>
            
            
            <div><textarea id="code" name="code">
            Headings
            !Header 1
            !!Header 2
            !!!Header 3
            !!!!Header 4
            !!!!!Header 5
            !!!!!!Header 6
            
            Styling
            -=titlebar=-
            ^^ Box on multi
            lines
            of content^^
            __bold__
            ''italic''
            ===underline===
            ::center::
            --Line Through--
            
            Operators
            ~np~No parse~/np~
            
            Link
            [link|desc|nocache]
            
            Wiki
            ((Wiki))
            ((Wiki|desc))
            ((Wiki|desc|timeout))
            
            Table
            ||row1 col1|row1 col2|row1 col3
            row2 col1|row2 col2|row2 col3
            row3 col1|row3 col2|row3 col3||
            
            Lists:
            *bla
            **bla-1
            ++continue-bla-1
            ***bla-2
            ++continue-bla-1
            *bla
            +continue-bla
            #bla
            ** tra-la-la
            +continue-bla
            #bla
            
            Plugin (standard):
            {PLUGIN(attr="my attr")}
            Plugin Body
            {PLUGIN}
            
            Plugin (inline):
            {plugin attr="my attr"}
            </textarea></div>
            
            <script type="text/javascript">
            	var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: 'tiki',      
                    lineNumbers: true
                });
            </script>
            
            </article>
            
          • tiki.css
            .cm-tw-syntaxerror {
            	color: #FFF;
            	background-color: #900;
            }
            
            .cm-tw-deleted {
            	text-decoration: line-through;
            }
            
            .cm-tw-header5 {
            	font-weight: bold;
            }
            .cm-tw-listitem:first-child { /*Added first child to fix duplicate padding when highlighting*/
            	padding-left: 10px;
            }
            
            .cm-tw-box {
            	border-top-width: 0px ! important;
            	border-style: solid;
            	border-width: 1px;
            	border-color: inherit;
            }
            
            .cm-tw-underline {
            	text-decoration: underline;
            }
          • tiki.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('tiki', function(config) {
              function inBlock(style, terminator, returnTokenizer) {
                return function(stream, state) {
                  while (!stream.eol()) {
                    if (stream.match(terminator)) {
                      state.tokenize = inText;
                      break;
                    }
                    stream.next();
                  }
            
                  if (returnTokenizer) state.tokenize = returnTokenizer;
            
                  return style;
                };
              }
            
              function inLine(style) {
                return function(stream, state) {
                  while(!stream.eol()) {
                    stream.next();
                  }
                  state.tokenize = inText;
                  return style;
                };
              }
            
              function inText(stream, state) {
                function chain(parser) {
                  state.tokenize = parser;
                  return parser(stream, state);
                }
            
                var sol = stream.sol();
                var ch = stream.next();
            
                //non start of line
                switch (ch) { //switch is generally much faster than if, so it is used here
                case "{": //plugin
                  stream.eat("/");
                  stream.eatSpace();
                  stream.eatWhile(/[^\s\u00a0=\"\'\/?(}]/);
                  state.tokenize = inPlugin;
                  return "tag";
                case "_": //bold
                  if (stream.eat("_"))
                    return chain(inBlock("strong", "__", inText));
                  break;
                case "'": //italics
                  if (stream.eat("'"))
                    return chain(inBlock("em", "''", inText));
                  break;
                case "(":// Wiki Link
                  if (stream.eat("("))
                    return chain(inBlock("variable-2", "))", inText));
                  break;
                case "[":// Weblink
                  return chain(inBlock("variable-3", "]", inText));
                  break;
                case "|": //table
                  if (stream.eat("|"))
                    return chain(inBlock("comment", "||"));
                  break;
                case "-":
                  if (stream.eat("=")) {//titleBar
                    return chain(inBlock("header string", "=-", inText));
                  } else if (stream.eat("-")) {//deleted
                    return chain(inBlock("error tw-deleted", "--", inText));
                  }
                  break;
                case "=": //underline
                  if (stream.match("=="))
                    return chain(inBlock("tw-underline", "===", inText));
                  break;
                case ":":
                  if (stream.eat(":"))
                    return chain(inBlock("comment", "::"));
                  break;
                case "^": //box
                  return chain(inBlock("tw-box", "^"));
                  break;
                case "~": //np
                  if (stream.match("np~"))
                    return chain(inBlock("meta", "~/np~"));
                  break;
                }
            
                //start of line types
                if (sol) {
                  switch (ch) {
                  case "!": //header at start of line
                    if (stream.match('!!!!!')) {
                      return chain(inLine("header string"));
                    } else if (stream.match('!!!!')) {
                      return chain(inLine("header string"));
                    } else if (stream.match('!!!')) {
                      return chain(inLine("header string"));
                    } else if (stream.match('!!')) {
                      return chain(inLine("header string"));
                    } else {
                      return chain(inLine("header string"));
                    }
                    break;
                  case "*": //unordered list line item, or <li /> at start of line
                  case "#": //ordered list line item, or <li /> at start of line
                  case "+": //ordered list line item, or <li /> at start of line
                    return chain(inLine("tw-listitem bracket"));
                    break;
                  }
                }
            
                //stream.eatWhile(/[&{]/); was eating up plugins, turned off to act less like html and more like tiki
                return null;
              }
            
              var indentUnit = config.indentUnit;
            
              // Return variables for tokenizers
              var pluginName, type;
              function inPlugin(stream, state) {
                var ch = stream.next();
                var peek = stream.peek();
            
                if (ch == "}") {
                  state.tokenize = inText;
                  //type = ch == ")" ? "endPlugin" : "selfclosePlugin"; inPlugin
                  return "tag";
                } else if (ch == "(" || ch == ")") {
                  return "bracket";
                } else if (ch == "=") {
                  type = "equals";
            
                  if (peek == ">") {
                    ch = stream.next();
                    peek = stream.peek();
                  }
            
                  //here we detect values directly after equal character with no quotes
                  if (!/[\'\"]/.test(peek)) {
                    state.tokenize = inAttributeNoQuote();
                  }
                  //end detect values
            
                  return "operator";
                } else if (/[\'\"]/.test(ch)) {
                  state.tokenize = inAttribute(ch);
                  return state.tokenize(stream, state);
                } else {
                  stream.eatWhile(/[^\s\u00a0=\"\'\/?]/);
                  return "keyword";
                }
              }
            
              function inAttribute(quote) {
                return function(stream, state) {
                  while (!stream.eol()) {
                    if (stream.next() == quote) {
                      state.tokenize = inPlugin;
                      break;
                    }
                  }
                  return "string";
                };
              }
            
              function inAttributeNoQuote() {
                return function(stream, state) {
                  while (!stream.eol()) {
                    var ch = stream.next();
                    var peek = stream.peek();
                    if (ch == " " || ch == "," || /[ )}]/.test(peek)) {
                  state.tokenize = inPlugin;
                  break;
                }
              }
              return "string";
            };
                                 }
            
            var curState, setStyle;
            function pass() {
              for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
            }
            
            function cont() {
              pass.apply(null, arguments);
              return true;
            }
            
            function pushContext(pluginName, startOfLine) {
              var noIndent = curState.context && curState.context.noIndent;
              curState.context = {
                prev: curState.context,
                pluginName: pluginName,
                indent: curState.indented,
                startOfLine: startOfLine,
                noIndent: noIndent
              };
            }
            
            function popContext() {
              if (curState.context) curState.context = curState.context.prev;
            }
            
            function element(type) {
              if (type == "openPlugin") {curState.pluginName = pluginName; return cont(attributes, endplugin(curState.startOfLine));}
              else if (type == "closePlugin") {
                var err = false;
                if (curState.context) {
                  err = curState.context.pluginName != pluginName;
                  popContext();
                } else {
                  err = true;
                }
                if (err) setStyle = "error";
                return cont(endcloseplugin(err));
              }
              else if (type == "string") {
                if (!curState.context || curState.context.name != "!cdata") pushContext("!cdata");
                if (curState.tokenize == inText) popContext();
                return cont();
              }
              else return cont();
            }
            
            function endplugin(startOfLine) {
              return function(type) {
                if (
                  type == "selfclosePlugin" ||
                    type == "endPlugin"
                )
                  return cont();
                if (type == "endPlugin") {pushContext(curState.pluginName, startOfLine); return cont();}
                return cont();
              };
            }
            
            function endcloseplugin(err) {
              return function(type) {
                if (err) setStyle = "error";
                if (type == "endPlugin") return cont();
                return pass();
              };
            }
            
            function attributes(type) {
              if (type == "keyword") {setStyle = "attribute"; return cont(attributes);}
              if (type == "equals") return cont(attvalue, attributes);
              return pass();
            }
            function attvalue(type) {
              if (type == "keyword") {setStyle = "string"; return cont();}
              if (type == "string") return cont(attvaluemaybe);
              return pass();
            }
            function attvaluemaybe(type) {
              if (type == "string") return cont(attvaluemaybe);
              else return pass();
            }
            return {
              startState: function() {
                return {tokenize: inText, cc: [], indented: 0, startOfLine: true, pluginName: null, context: null};
              },
              token: function(stream, state) {
                if (stream.sol()) {
                  state.startOfLine = true;
                  state.indented = stream.indentation();
                }
                if (stream.eatSpace()) return null;
            
                setStyle = type = pluginName = null;
                var style = state.tokenize(stream, state);
                if ((style || type) && style != "comment") {
                  curState = state;
                  while (true) {
                    var comb = state.cc.pop() || element;
                    if (comb(type || style)) break;
                  }
                }
                state.startOfLine = false;
                return setStyle || style;
              },
              indent: function(state, textAfter) {
                var context = state.context;
                if (context && context.noIndent) return 0;
                if (context && /^{\//.test(textAfter))
                    context = context.prev;
                    while (context && !context.startOfLine)
                      context = context.prev;
                    if (context) return context.indent + indentUnit;
                    else return 0;
                   },
                electricChars: "/"
              };
            });
            
            CodeMirror.defineMIME("text/tiki", "tiki");
            
            });
            
        • toml
          • index.html
            <!doctype html>
            
            <title>CodeMirror: TOML Mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="toml.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">TOML Mode</a>
              </ul>
            </div>
            
            <article>
            <h2>TOML Mode</h2>
            <form><textarea id="code" name="code">
            # This is a TOML document. Boom.
            
            title = "TOML Example"
            
            [owner]
            name = "Tom Preston-Werner"
            organization = "GitHub"
            bio = "GitHub Cofounder &amp; CEO\nLikes tater tots and beer."
            dob = 1979-05-27T07:32:00Z # First class dates? Why not?
            
            [database]
            server = "192.168.1.1"
            ports = [ 8001, 8001, 8002 ]
            connection_max = 5000
            enabled = true
            
            [servers]
            
              # You can indent as you please. Tabs or spaces. TOML don't care.
              [servers.alpha]
              ip = "10.0.0.1"
              dc = "eqdc10"
              
              [servers.beta]
              ip = "10.0.0.2"
              dc = "eqdc10"
              
            [clients]
            data = [ ["gamma", "delta"], [1, 2] ]
            
            # Line breaks are OK when inside arrays
            hosts = [
              "alpha",
              "omega"
            ]
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: {name: "toml"},
                    lineNumbers: true
                  });
                </script>
                <h3>The TOML Mode</h3>
                  <p> Created by Forbes Lindesay.</p>
                <p><strong>MIME type defined:</strong> <code>text/x-toml</code>.</p>
              </article>
            
          • toml.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("toml", function () {
              return {
                startState: function () {
                  return {
                    inString: false,
                    stringType: "",
                    lhs: true,
                    inArray: 0
                  };
                },
                token: function (stream, state) {
                  //check for state changes
                  if (!state.inString && ((stream.peek() == '"') || (stream.peek() == "'"))) {
                    state.stringType = stream.peek();
                    stream.next(); // Skip quote
                    state.inString = true; // Update state
                  }
                  if (stream.sol() && state.inArray === 0) {
                    state.lhs = true;
                  }
                  //return state
                  if (state.inString) {
                    while (state.inString && !stream.eol()) {
                      if (stream.peek() === state.stringType) {
                        stream.next(); // Skip quote
                        state.inString = false; // Clear flag
                      } else if (stream.peek() === '\\') {
                        stream.next();
                        stream.next();
                      } else {
                        stream.match(/^.[^\\\"\']*/);
                      }
                    }
                    return state.lhs ? "property string" : "string"; // Token style
                  } else if (state.inArray && stream.peek() === ']') {
                    stream.next();
                    state.inArray--;
                    return 'bracket';
                  } else if (state.lhs && stream.peek() === '[' && stream.skipTo(']')) {
                    stream.next();//skip closing ]
                    // array of objects has an extra open & close []
                    if (stream.peek() === ']') stream.next();
                    return "atom";
                  } else if (stream.peek() === "#") {
                    stream.skipToEnd();
                    return "comment";
                  } else if (stream.eatSpace()) {
                    return null;
                  } else if (state.lhs && stream.eatWhile(function (c) { return c != '=' && c != ' '; })) {
                    return "property";
                  } else if (state.lhs && stream.peek() === "=") {
                    stream.next();
                    state.lhs = false;
                    return null;
                  } else if (!state.lhs && stream.match(/^\d\d\d\d[\d\-\:\.T]*Z/)) {
                    return 'atom'; //date
                  } else if (!state.lhs && (stream.match('true') || stream.match('false'))) {
                    return 'atom';
                  } else if (!state.lhs && stream.peek() === '[') {
                    state.inArray++;
                    stream.next();
                    return 'bracket';
                  } else if (!state.lhs && stream.match(/^\-?\d+(?:\.\d+)?/)) {
                    return 'number';
                  } else if (!stream.eatSpace()) {
                    stream.next();
                  }
                  return null;
                }
              };
            });
            
            CodeMirror.defineMIME('text/x-toml', 'toml');
            
            });
            
        • tornado
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Tornado template mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/mode/overlay.js"></script>
            <script src="../xml/xml.js"></script>
            <script src="../htmlmixed/htmlmixed.js"></script>
            <script src="tornado.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/marijnh/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Tornado</a>
              </ul>
            </div>
            
            <article>
            <h2>Tornado template mode</h2>
            <form><textarea id="code" name="code">
            <!doctype html>
            <html>
                <head>
                    <title>My Tornado web application</title>
                </head>
                <body>
                    <h1>
                        {{ title }}
                    </h1>
                    <ul class="my-list">
                        {% for item in items %}
                            <li>{% item.name %}</li>
                        {% empty %}
                            <li>You have no items in your list.</li>
                        {% end %}
                    </ul>
                </body>
            </html>
            </textarea></form>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    mode: "tornado",
                    indentUnit: 4,
                    indentWithTabs: true
                  });
                </script>
            
                <p>Mode for HTML with embedded Tornado template markup.</p>
            
                <p><strong>MIME types defined:</strong> <code>text/x-tornado</code></p>
              </article>
            
          • tornado.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"),
                    require("../../addon/mode/overlay"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror", "../htmlmixed/htmlmixed",
                        "../../addon/mode/overlay"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("tornado:inner", function() {
                var keywords = ["and","as","assert","autoescape","block","break","class","comment","context",
                                "continue","datetime","def","del","elif","else","end","escape","except",
                                "exec","extends","false","finally","for","from","global","if","import","in",
                                "include","is","json_encode","lambda","length","linkify","load","module",
                                "none","not","or","pass","print","put","raise","raw","return","self","set",
                                "squeeze","super","true","try","url_escape","while","with","without","xhtml_escape","yield"];
                keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b");
            
                function tokenBase (stream, state) {
                  stream.eatWhile(/[^\{]/);
                  var ch = stream.next();
                  if (ch == "{") {
                    if (ch = stream.eat(/\{|%|#/)) {
                      state.tokenize = inTag(ch);
                      return "tag";
                    }
                  }
                }
                function inTag (close) {
                  if (close == "{") {
                    close = "}";
                  }
                  return function (stream, state) {
                    var ch = stream.next();
                    if ((ch == close) && stream.eat("}")) {
                      state.tokenize = tokenBase;
                      return "tag";
                    }
                    if (stream.match(keywords)) {
                      return "keyword";
                    }
                    return close == "#" ? "comment" : "string";
                  };
                }
                return {
                  startState: function () {
                    return {tokenize: tokenBase};
                  },
                  token: function (stream, state) {
                    return state.tokenize(stream, state);
                  }
                };
              });
            
              CodeMirror.defineMode("tornado", function(config) {
                var htmlBase = CodeMirror.getMode(config, "text/html");
                var tornadoInner = CodeMirror.getMode(config, "tornado:inner");
                return CodeMirror.overlayMode(htmlBase, tornadoInner);
              });
            
              CodeMirror.defineMIME("text/x-tornado", "tornado");
            });
            
        • troff
          • index.html
            <!doctype html>
            
            <title>CodeMirror: troff mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel=stylesheet href=../../lib/codemirror.css>
            <script src=../../lib/codemirror.js></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src=troff.js></script>
            <style type=text/css>
              .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
            </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">troff</a>
              </ul>
            </div>
            
            <article>
            <h2>troff</h2>
            
            
            <textarea id=code>
            '\" t
            .\"     Title: mkvextract
            .TH "MKVEXTRACT" "1" "2015\-02\-28" "MKVToolNix 7\&.7\&.0" "User Commands"
            .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            .ie \n(.g .ds Aq \(aq
            .el       .ds Aq '
            .\" -----------------------------------------------------------------
            .nh
            .\" disable justification (adjust text to left margin only)
            .ad l
            .\" -----------------------------------------------------------------
            .SH "NAME"
            mkvextract \- extract tracks from Matroska(TM) files into other files
            .SH "SYNOPSIS"
            .HP \w'\fBmkvextract\fR\ 'u
            \fBmkvextract\fR {mode} {source\-filename} [options] [extraction\-spec]
            .SH "DESCRIPTION"
            .PP
            .B mkvextract
            extracts specific parts from a
            .I Matroska(TM)
            file to other useful formats\&. The first argument,
            \fBmode\fR, tells
            \fBmkvextract\fR(1)
            what to extract\&. Currently supported is the extraction of
            tracks,
            tags,
            attachments,
            chapters,
            CUE sheets,
            timecodes
            and
            cues\&. The second argument is the name of the source file\&. It must be a
            Matroska(TM)
            file\&. All following arguments are options and extraction specifications; both of which depend on the selected mode\&.
            .SS "Common options"
            .PP
            The following options are available in all modes and only described once in this section\&.
            .PP
            \fB\-f\fR, \fB\-\-parse\-fully\fR
            .RS 4
            Sets the parse mode to \*(Aqfull\*(Aq\&. The default mode does not parse the whole file but uses the meta seek elements for locating the required elements of a source file\&. In 99% of all cases this is enough\&. But for files that do not contain meta seek elements or which are damaged the user might have to use this mode\&. A full scan of a file can take a couple of minutes while a fast scan only takes seconds\&.
            .RE
            .PP
            \fB\-\-command\-line\-charset\fR \fIcharacter\-set\fR
            .RS 4
            Sets the character set to convert strings given on the command line from\&. It defaults to the character set given by system\*(Aqs current locale\&.
            .RE
            .PP
            \fB\-\-output\-charset\fR \fIcharacter\-set\fR
            .RS 4
            Sets the character set to which strings are converted that are to be output\&. It defaults to the character set given by system\*(Aqs current locale\&.
            .RE
            .PP
            \fB\-r\fR, \fB\-\-redirect\-output\fR \fIfile\-name\fR
            .RS 4
            Writes all messages to the file
            \fIfile\-name\fR
            instead of to the console\&. While this can be done easily with output redirection there are cases in which this option is needed: when the terminal reinterprets the output before writing it to a file\&. The character set set with
            \fB\-\-output\-charset\fR
            is honored\&.
            .RE
            .PP
            \fB\-\-ui\-language\fR \fIcode\fR
            .RS 4
            Forces the translations for the language
            \fIcode\fR
            to be used (e\&.g\&. \*(Aqde_DE\*(Aq for the German translations)\&. It is preferable to use the environment variables
            \fILANG\fR,
            \fILC_MESSAGES\fR
            and
            \fILC_ALL\fR
            though\&. Entering \*(Aqlist\*(Aq as the
            \fIcode\fR
            will cause
            \fBmkvextract\fR(1)
            to output a list of available translations\&.
            
            .\" [...]
            
            .SH "SEE ALSO"
            .PP
            \fBmkvmerge\fR(1),
            \fBmkvinfo\fR(1),
            \fBmkvpropedit\fR(1),
            \fBmmg\fR(1)
            .SH "WWW"
            .PP
            The latest version can always be found at
            \m[blue]\fBthe MKVToolNix homepage\fR\m[]\&\s-2\u[1]\d\s+2\&.
            .SH "AUTHOR"
            .PP
            \(co \fBMoritz Bunkus\fR <\&moritz@bunkus\&.org\&>
            .RS 4
            Developer
            .RE
            .SH "NOTES"
            .IP " 1." 4
            the MKVToolNix homepage
            .RS 4
            \%https://www.bunkus.org/videotools/mkvtoolnix/
            .RE
            </textarea>
            
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
                mode: 'troff',
                lineNumbers: true,
                matchBrackets: false
              });
            </script>
            
            <p><strong>MIME types defined:</strong> <code>troff</code>.</p>
            </article>
            
          • troff.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object")
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd)
                define(["../../lib/codemirror"], mod);
              else
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('troff', function() {
            
              var words = {};
            
              function tokenBase(stream) {
                if (stream.eatSpace()) return null;
            
                var sol = stream.sol();
                var ch = stream.next();
            
                if (ch === '\\') {
                  if (stream.match('fB') || stream.match('fR') || stream.match('fI') ||
                      stream.match('u')  || stream.match('d')  ||
                      stream.match('%')  || stream.match('&')) {
                    return 'string';
                  }
                  if (stream.match('m[')) {
                    stream.skipTo(']');
                    stream.next();
                    return 'string';
                  }
                  if (stream.match('s+') || stream.match('s-')) {
                    stream.eatWhile(/[\d-]/);
                    return 'string';
                  }
                  if (stream.match('\(') || stream.match('*\(')) {
                    stream.eatWhile(/[\w-]/);
                    return 'string';
                  }
                  return 'string';
                }
                if (sol && (ch === '.' || ch === '\'')) {
                  if (stream.eat('\\') && stream.eat('\"')) {
                    stream.skipToEnd();
                    return 'comment';
                  }
                }
                if (sol && ch === '.') {
                  if (stream.match('B ') || stream.match('I ') || stream.match('R ')) {
                    return 'attribute';
                  }
                  if (stream.match('TH ') || stream.match('SH ') || stream.match('SS ') || stream.match('HP ')) {
                    stream.skipToEnd();
                    return 'quote';
                  }
                  if ((stream.match(/[A-Z]/) && stream.match(/[A-Z]/)) || (stream.match(/[a-z]/) && stream.match(/[a-z]/))) {
                    return 'attribute';
                  }
                }
                stream.eatWhile(/[\w-]/);
                var cur = stream.current();
                return words.hasOwnProperty(cur) ? words[cur] : null;
              }
            
              function tokenize(stream, state) {
                return (state.tokens[0] || tokenBase) (stream, state);
              };
            
              return {
                startState: function() {return {tokens:[]};},
                token: function(stream, state) {
                  return tokenize(stream, state);
                }
              };
            });
            
            CodeMirror.defineMIME('troff', 'troff');
            
            });
            
        • ttcn
          • index.html
            <!doctype html>
            
            <title>CodeMirror: TTCN mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="ttcn.js"></script>
            <style type="text/css">
                .CodeMirror {
                    border-top: 1px solid black;
                    border-bottom: 1px solid black;
                }
            </style>
            <div id=nav>
                <a href="http://codemirror.net"><h1>CodeMirror</h1>
                    <img id=logo src="../../doc/logo.png">
                </a>
            
                <ul>
                    <li><a href="../../index.html">Home</a>
                    <li><a href="../../doc/manual.html">Manual</a>
                    <li><a href="https://github.com/codemirror/codemirror">Code</a>
                </ul>
                <ul>
                    <li><a href="../index.html">Language modes</a>
                    <li><a class=active href="http://en.wikipedia.org/wiki/TTCN">TTCN</a>
                </ul>
            </div>
            <article>
                <h2>TTCN example</h2>
                <div>
                    <textarea id="ttcn-code">
            module Templates {
              /* import types from ASN.1 */
              import from Types language "ASN.1:1997" all;
            
              /* During the conversion phase from ASN.1 to TTCN-3 */
              /* - the minus sign (Message-Type) within the identifiers will be replaced by underscore (Message_Type)*/
              /* - the ASN.1 identifiers matching a TTCN-3 keyword (objid) will be postfixed with an underscore (objid_)*/
            
              // simple types
            
              template SenderID localObjid := objid {itu_t(0) identified_organization(4) etsi(0)};
            
              // complex types
            
              /* ASN.1 Message-Type mapped to TTCN-3 Message_Type */
              template Message receiveMsg(template (present) Message_Type p_messageType) := {
                header := p_messageType,
                body := ?
              }
            
              /* ASN.1 objid mapped to TTCN-3 objid_ */
              template Message sendInviteMsg := {
                  header := inviteType,
                  body := {
                    /* optional fields may be assigned by omit or may be ignored/skipped */
                    description := "Invite Message",
                    data := 'FF'O,
                    objid_ := localObjid
                  }
              }
            
              template Message sendAcceptMsg modifies sendInviteMsg := {
                  header := acceptType,
                  body := {
                    description := "Accept Message"
                  }
                };
            
              template Message sendErrorMsg modifies sendInviteMsg := {
                  header := errorType,
                  body := {
                    description := "Error Message"
                  }
                };
            
              template Message expectedErrorMsg := {
                  header := errorType,
                  body := ?
                };
            
              template Message expectedInviteMsg modifies expectedErrorMsg := {
                  header := inviteType
                };
            
              template Message expectedAcceptMsg modifies expectedErrorMsg := {
                  header := acceptType
                };
            
            } with { encode "BER:1997" }
                    </textarea>
                </div>
            
                <script> 
                  var ttcnEditor = CodeMirror.fromTextArea(document.getElementById("ttcn-code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-ttcn"
                  });
                  ttcnEditor.setSize(600, 860);
                  var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
                  CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
                </script>
                <br/>
                <p><strong>Language:</strong> Testing and Test Control Notation
                    (<a href="http://en.wikipedia.org/wiki/TTCN">TTCN</a>)
                </p>
                <p><strong>MIME types defined:</strong> <code>text/x-ttcn,
                    text/x-ttcn3, text/x-ttcnpp</code>.</p>
                <br/>
                <p>The development of this mode has been sponsored by <a href="http://www.ericsson.com/">Ericsson
                </a>.</p>
                <p>Coded by Asmelash Tsegay Gebretsadkan </p>
            </article>
            
            
          • ttcn.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("ttcn", function(config, parserConfig) {
                var indentUnit = config.indentUnit,
                    keywords = parserConfig.keywords || {},
                    builtin = parserConfig.builtin || {},
                    timerOps = parserConfig.timerOps || {},
                    portOps  = parserConfig.portOps || {},
                    configOps = parserConfig.configOps || {},
                    verdictOps = parserConfig.verdictOps || {},
                    sutOps = parserConfig.sutOps || {},
                    functionOps = parserConfig.functionOps || {},
            
                    verdictConsts = parserConfig.verdictConsts || {},
                    booleanConsts = parserConfig.booleanConsts || {},
                    otherConsts   = parserConfig.otherConsts || {},
            
                    types = parserConfig.types || {},
                    visibilityModifiers = parserConfig.visibilityModifiers || {},
                    templateMatch = parserConfig.templateMatch || {},
                    multiLineStrings = parserConfig.multiLineStrings,
                    indentStatements = parserConfig.indentStatements !== false;
                var isOperatorChar = /[+\-*&@=<>!\/]/;
                var curPunc;
            
                function tokenBase(stream, state) {
                  var ch = stream.next();
            
                  if (ch == '"' || ch == "'") {
                    state.tokenize = tokenString(ch);
                    return state.tokenize(stream, state);
                  }
                  if (/[\[\]{}\(\),;\\:\?\.]/.test(ch)) {
                    curPunc = ch;
                    return "punctuation";
                  }
                  if (ch == "#"){
                    stream.skipToEnd();
                    return "atom preprocessor";
                  }
                  if (ch == "%"){
                    stream.eatWhile(/\b/);
                    return "atom ttcn3Macros";
                  }
                  if (/\d/.test(ch)) {
                    stream.eatWhile(/[\w\.]/);
                    return "number";
                  }
                  if (ch == "/") {
                    if (stream.eat("*")) {
                      state.tokenize = tokenComment;
                      return tokenComment(stream, state);
                    }
                    if (stream.eat("/")) {
                      stream.skipToEnd();
                      return "comment";
                    }
                  }
                  if (isOperatorChar.test(ch)) {
                    if(ch == "@"){
                      if(stream.match("try") || stream.match("catch")
                          || stream.match("lazy")){
                        return "keyword";
                      }
                    }
                    stream.eatWhile(isOperatorChar);
                    return "operator";
                  }
                  stream.eatWhile(/[\w\$_\xa1-\uffff]/);
                  var cur = stream.current();
            
                  if (keywords.propertyIsEnumerable(cur)) return "keyword";
                  if (builtin.propertyIsEnumerable(cur)) return "builtin";
            
                  if (timerOps.propertyIsEnumerable(cur)) return "def timerOps";
                  if (configOps.propertyIsEnumerable(cur)) return "def configOps";
                  if (verdictOps.propertyIsEnumerable(cur)) return "def verdictOps";
                  if (portOps.propertyIsEnumerable(cur)) return "def portOps";
                  if (sutOps.propertyIsEnumerable(cur)) return "def sutOps";
                  if (functionOps.propertyIsEnumerable(cur)) return "def functionOps";
            
                  if (verdictConsts.propertyIsEnumerable(cur)) return "string verdictConsts";
                  if (booleanConsts.propertyIsEnumerable(cur)) return "string booleanConsts";
                  if (otherConsts.propertyIsEnumerable(cur)) return "string otherConsts";
            
                  if (types.propertyIsEnumerable(cur)) return "builtin types";
                  if (visibilityModifiers.propertyIsEnumerable(cur))
                    return "builtin visibilityModifiers";
                  if (templateMatch.propertyIsEnumerable(cur)) return "atom templateMatch";
            
                  return "variable";
                }
            
                function tokenString(quote) {
                  return function(stream, state) {
                    var escaped = false, next, end = false;
                    while ((next = stream.next()) != null) {
                      if (next == quote && !escaped){
                        var afterQuote = stream.peek();
                        //look if the character after the quote is like the B in '10100010'B
                        if (afterQuote){
                          afterQuote = afterQuote.toLowerCase();
                          if(afterQuote == "b" || afterQuote == "h" || afterQuote == "o")
                            stream.next();
                        }
                        end = true; break;
                      }
                      escaped = !escaped && next == "\\";
                    }
                    if (end || !(escaped || multiLineStrings))
                      state.tokenize = null;
                    return "string";
                  };
                }
            
                function tokenComment(stream, state) {
                  var maybeEnd = false, ch;
                  while (ch = stream.next()) {
                    if (ch == "/" && maybeEnd) {
                      state.tokenize = null;
                      break;
                    }
                    maybeEnd = (ch == "*");
                  }
                  return "comment";
                }
            
                function Context(indented, column, type, align, prev) {
                  this.indented = indented;
                  this.column = column;
                  this.type = type;
                  this.align = align;
                  this.prev = prev;
                }
            
                function pushContext(state, col, type) {
                  var indent = state.indented;
                  if (state.context && state.context.type == "statement")
                    indent = state.context.indented;
                  return state.context = new Context(indent, col, type, null, state.context);
                }
            
                function popContext(state) {
                  var t = state.context.type;
                  if (t == ")" || t == "]" || t == "}")
                    state.indented = state.context.indented;
                  return state.context = state.context.prev;
                }
            
                //Interface
                return {
                  startState: function(basecolumn) {
                    return {
                      tokenize: null,
                      context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
                      indented: 0,
                      startOfLine: true
                    };
                  },
            
                  token: function(stream, state) {
                    var ctx = state.context;
                    if (stream.sol()) {
                      if (ctx.align == null) ctx.align = false;
                      state.indented = stream.indentation();
                      state.startOfLine = true;
                    }
                    if (stream.eatSpace()) return null;
                    curPunc = null;
                    var style = (state.tokenize || tokenBase)(stream, state);
                    if (style == "comment") return style;
                    if (ctx.align == null) ctx.align = true;
            
                    if ((curPunc == ";" || curPunc == ":" || curPunc == ",")
                        && ctx.type == "statement"){
                      popContext(state);
                    }
                    else if (curPunc == "{") pushContext(state, stream.column(), "}");
                    else if (curPunc == "[") pushContext(state, stream.column(), "]");
                    else if (curPunc == "(") pushContext(state, stream.column(), ")");
                    else if (curPunc == "}") {
                      while (ctx.type == "statement") ctx = popContext(state);
                      if (ctx.type == "}") ctx = popContext(state);
                      while (ctx.type == "statement") ctx = popContext(state);
                    }
                    else if (curPunc == ctx.type) popContext(state);
                    else if (indentStatements &&
                        (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') ||
                        (ctx.type == "statement" && curPunc == "newstatement")))
                      pushContext(state, stream.column(), "statement");
            
                    state.startOfLine = false;
            
                    return style;
                  },
            
                  electricChars: "{}",
                  blockCommentStart: "/*",
                  blockCommentEnd: "*/",
                  lineComment: "//",
                  fold: "brace"
                };
              });
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              function def(mimes, mode) {
                if (typeof mimes == "string") mimes = [mimes];
                var words = [];
                function add(obj) {
                  if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))
                    words.push(prop);
                }
            
                add(mode.keywords);
                add(mode.builtin);
                add(mode.timerOps);
                add(mode.portOps);
            
                if (words.length) {
                  mode.helperType = mimes[0];
                  CodeMirror.registerHelper("hintWords", mimes[0], words);
                }
            
                for (var i = 0; i < mimes.length; ++i)
                  CodeMirror.defineMIME(mimes[i], mode);
              }
            
              def(["text/x-ttcn", "text/x-ttcn3", "text/x-ttcnpp"], {
                name: "ttcn",
                keywords: words("activate address alive all alt altstep and and4b any" +
                " break case component const continue control deactivate" +
                " display do else encode enumerated except exception" +
                " execute extends extension external for from function" +
                " goto group if import in infinity inout interleave" +
                " label language length log match message mixed mod" +
                " modifies module modulepar mtc noblock not not4b nowait" +
                " of on optional or or4b out override param pattern port" +
                " procedure record recursive rem repeat return runs select" +
                " self sender set signature system template testcase to" +
                " type union value valueof var variant while with xor xor4b"),
                builtin: words("bit2hex bit2int bit2oct bit2str char2int char2oct encvalue" +
                " decomp decvalue float2int float2str hex2bit hex2int" +
                " hex2oct hex2str int2bit int2char int2float int2hex" +
                " int2oct int2str int2unichar isbound ischosen ispresent" +
                " isvalue lengthof log2str oct2bit oct2char oct2hex oct2int" +
                " oct2str regexp replace rnd sizeof str2bit str2float" +
                " str2hex str2int str2oct substr unichar2int unichar2char" +
                " enum2int"),
                types: words("anytype bitstring boolean char charstring default float" +
                " hexstring integer objid octetstring universal verdicttype timer"),
                timerOps: words("read running start stop timeout"),
                portOps: words("call catch check clear getcall getreply halt raise receive" +
                " reply send trigger"),
                configOps: words("create connect disconnect done kill killed map unmap"),
                verdictOps: words("getverdict setverdict"),
                sutOps: words("action"),
                functionOps: words("apply derefers refers"),
            
                verdictConsts: words("error fail inconc none pass"),
                booleanConsts: words("true false"),
                otherConsts: words("null NULL omit"),
            
                visibilityModifiers: words("private public friend"),
                templateMatch: words("complement ifpresent subset superset permutation"),
                multiLineStrings: true
              });
            });
            
        • ttcn-cfg
          • index.html
            <!doctype html>
            
            <title>CodeMirror: TTCN-CFG mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="ttcn-cfg.js"></script>
            <style type="text/css">
                .CodeMirror {
                    border-top: 1px solid black;
                    border-bottom: 1px solid black;
                }
            </style>
            <div id=nav>
                <a href="http://codemirror.net"><h1>CodeMirror</h1>
                    <img id=logo src="../../doc/logo.png">
                </a>
            
                <ul>
                    <li><a href="../../index.html">Home</a>
                    <li><a href="../../doc/manual.html">Manual</a>
                    <li><a href="https://github.com/codemirror/codemirror">Code</a>
                </ul>
                <ul>
                    <li><a href="../index.html">Language modes</a>
                    <li><a class=active href="http://en.wikipedia.org/wiki/TTCN">TTCN-CFG</a>
                </ul>
            </div>
            <article>
                <h2>TTCN-CFG example</h2>
                <div>
                    <textarea id="ttcn-cfg-code">
            [MODULE_PARAMETERS]
            # This section shall contain the values of all parameters that are defined in your TTCN-3 modules.
            
            [LOGGING]
            # In this section you can specify the name of the log file and the classes of events
            # you want to log into the file or display on console (standard error).
            
            LogFile := "logs/%e.%h-%r.%s"
            FileMask := LOG_ALL | DEBUG | MATCHING
            ConsoleMask := ERROR | WARNING | TESTCASE | STATISTICS | PORTEVENT
            
            LogSourceInfo := Yes
            AppendFile := No
            TimeStampFormat := DateTime
            LogEventTypes := Yes
            SourceInfoFormat := Single
            LogEntityName := Yes
            
            [TESTPORT_PARAMETERS]
            # In this section you can specify parameters that are passed to Test Ports.
            
            [DEFINE]
            # In this section you can create macro definitions,
            # that can be used in other configuration file sections except [INCLUDE].
            
            [INCLUDE]
            # To use configuration settings given in other configuration files,
            # the configuration files just need to be listed in this section, with their full or relative pathnames.
            
            [EXTERNAL_COMMANDS]
            # This section can define external commands (shell scripts) to be executed by the ETS
            # whenever a control part or test case is started or terminated.
            
            BeginTestCase := ""
            EndTestCase := ""
            BeginControlPart := ""
            EndControlPart := ""
            
            [EXECUTE]
            # In this section you can specify what parts of your test suite you want to execute.
            
            [GROUPS]
            # In this section you can specify groups of hosts. These groups can be used inside the
            # [COMPONENTS] section to restrict the creation of certain PTCs to a given set of hosts.
            
            [COMPONENTS]
            # This section consists of rules restricting the location of created PTCs.
            
            [MAIN_CONTROLLER]
            # The options herein control the behavior of MC.
            
            TCPPort := 0
            KillTimer := 10.0
            NumHCs := 0
            LocalAddress :=
                    </textarea>
                </div>
            
                <script> 
                  var ttcnEditor = CodeMirror.fromTextArea(document.getElementById("ttcn-cfg-code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    mode: "text/x-ttcn-cfg"
                  });
                  ttcnEditor.setSize(600, 860);
                  var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
                  CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
                </script>
                <br/>
                <p><strong>Language:</strong> Testing and Test Control Notation -
                    Configuration files
                    (<a href="http://en.wikipedia.org/wiki/TTCN">TTCN-CFG</a>)
                </p>
                <p><strong>MIME types defined:</strong> <code>text/x-ttcn-cfg</code>.</p>
            
                <br/>
                <p>The development of this mode has been sponsored by <a href="http://www.ericsson.com/">Ericsson
                </a>.</p>
                <p>Coded by Asmelash Tsegay Gebretsadkan </p>
            </article>
            
            
          • ttcn-cfg.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
              "use strict";
            
              CodeMirror.defineMode("ttcn-cfg", function(config, parserConfig) {
                var indentUnit = config.indentUnit,
                    keywords = parserConfig.keywords || {},
                    fileNCtrlMaskOptions = parserConfig.fileNCtrlMaskOptions || {},
                    externalCommands = parserConfig.externalCommands || {},
                    multiLineStrings = parserConfig.multiLineStrings,
                    indentStatements = parserConfig.indentStatements !== false;
                var isOperatorChar = /[\|]/;
                var curPunc;
            
                function tokenBase(stream, state) {
                  var ch = stream.next();
                  if (ch == '"' || ch == "'") {
                    state.tokenize = tokenString(ch);
                    return state.tokenize(stream, state);
                  }
                  if (/[:=]/.test(ch)) {
                    curPunc = ch;
                    return "punctuation";
                  }
                  if (ch == "#"){
                    stream.skipToEnd();
                    return "comment";
                  }
                  if (/\d/.test(ch)) {
                    stream.eatWhile(/[\w\.]/);
                    return "number";
                  }
                  if (isOperatorChar.test(ch)) {
                    stream.eatWhile(isOperatorChar);
                    return "operator";
                  }
                  if (ch == "["){
                    stream.eatWhile(/[\w_\]]/);
                    return "number sectionTitle";
                  }
            
                  stream.eatWhile(/[\w\$_]/);
                  var cur = stream.current();
                  if (keywords.propertyIsEnumerable(cur)) return "keyword";
                  if (fileNCtrlMaskOptions.propertyIsEnumerable(cur))
                    return "negative fileNCtrlMaskOptions";
                  if (externalCommands.propertyIsEnumerable(cur)) return "negative externalCommands";
            
                  return "variable";
                }
            
                function tokenString(quote) {
                  return function(stream, state) {
                    var escaped = false, next, end = false;
                    while ((next = stream.next()) != null) {
                      if (next == quote && !escaped){
                        var afterNext = stream.peek();
                        //look if the character if the quote is like the B in '10100010'B
                        if (afterNext){
                          afterNext = afterNext.toLowerCase();
                          if(afterNext == "b" || afterNext == "h" || afterNext == "o")
                            stream.next();
                        }
                        end = true; break;
                      }
                      escaped = !escaped && next == "\\";
                    }
                    if (end || !(escaped || multiLineStrings))
                      state.tokenize = null;
                    return "string";
                  };
                }
            
                function Context(indented, column, type, align, prev) {
                  this.indented = indented;
                  this.column = column;
                  this.type = type;
                  this.align = align;
                  this.prev = prev;
                }
                function pushContext(state, col, type) {
                  var indent = state.indented;
                  if (state.context && state.context.type == "statement")
                    indent = state.context.indented;
                  return state.context = new Context(indent, col, type, null, state.context);
                }
                function popContext(state) {
                  var t = state.context.type;
                  if (t == ")" || t == "]" || t == "}")
                    state.indented = state.context.indented;
                  return state.context = state.context.prev;
                }
            
                //Interface
                return {
                  startState: function(basecolumn) {
                    return {
                      tokenize: null,
                      context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
                      indented: 0,
                      startOfLine: true
                    };
                  },
            
                  token: function(stream, state) {
                    var ctx = state.context;
                    if (stream.sol()) {
                      if (ctx.align == null) ctx.align = false;
                      state.indented = stream.indentation();
                      state.startOfLine = true;
                    }
                    if (stream.eatSpace()) return null;
                    curPunc = null;
                    var style = (state.tokenize || tokenBase)(stream, state);
                    if (style == "comment") return style;
                    if (ctx.align == null) ctx.align = true;
            
                    if ((curPunc == ";" || curPunc == ":" || curPunc == ",")
                        && ctx.type == "statement"){
                      popContext(state);
                    }
                    else if (curPunc == "{") pushContext(state, stream.column(), "}");
                    else if (curPunc == "[") pushContext(state, stream.column(), "]");
                    else if (curPunc == "(") pushContext(state, stream.column(), ")");
                    else if (curPunc == "}") {
                      while (ctx.type == "statement") ctx = popContext(state);
                      if (ctx.type == "}") ctx = popContext(state);
                      while (ctx.type == "statement") ctx = popContext(state);
                    }
                    else if (curPunc == ctx.type) popContext(state);
                    else if (indentStatements && (((ctx.type == "}" || ctx.type == "top")
                        && curPunc != ';') || (ctx.type == "statement"
                        && curPunc == "newstatement")))
                      pushContext(state, stream.column(), "statement");
                    state.startOfLine = false;
                    return style;
                  },
            
                  electricChars: "{}",
                  lineComment: "#",
                  fold: "brace"
                };
              });
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i)
                  obj[words[i]] = true;
                return obj;
              }
            
              CodeMirror.defineMIME("text/x-ttcn-cfg", {
                name: "ttcn-cfg",
                keywords: words("Yes No LogFile FileMask ConsoleMask AppendFile" +
                " TimeStampFormat LogEventTypes SourceInfoFormat" +
                " LogEntityName LogSourceInfo DiskFullAction" +
                " LogFileNumber LogFileSize MatchingHints Detailed" +
                " Compact SubCategories Stack Single None Seconds" +
                " DateTime Time Stop Error Retry Delete TCPPort KillTimer" +
                " NumHCs UnixSocketsEnabled LocalAddress"),
                fileNCtrlMaskOptions: words("TTCN_EXECUTOR TTCN_ERROR TTCN_WARNING" +
                " TTCN_PORTEVENT TTCN_TIMEROP TTCN_VERDICTOP" +
                " TTCN_DEFAULTOP TTCN_TESTCASE TTCN_ACTION" +
                " TTCN_USER TTCN_FUNCTION TTCN_STATISTICS" +
                " TTCN_PARALLEL TTCN_MATCHING TTCN_DEBUG" +
                " EXECUTOR ERROR WARNING PORTEVENT TIMEROP" +
                " VERDICTOP DEFAULTOP TESTCASE ACTION USER" +
                " FUNCTION STATISTICS PARALLEL MATCHING DEBUG" +
                " LOG_ALL LOG_NOTHING ACTION_UNQUALIFIED" +
                " DEBUG_ENCDEC DEBUG_TESTPORT" +
                " DEBUG_UNQUALIFIED DEFAULTOP_ACTIVATE" +
                " DEFAULTOP_DEACTIVATE DEFAULTOP_EXIT" +
                " DEFAULTOP_UNQUALIFIED ERROR_UNQUALIFIED" +
                " EXECUTOR_COMPONENT EXECUTOR_CONFIGDATA" +
                " EXECUTOR_EXTCOMMAND EXECUTOR_LOGOPTIONS" +
                " EXECUTOR_RUNTIME EXECUTOR_UNQUALIFIED" +
                " FUNCTION_RND FUNCTION_UNQUALIFIED" +
                " MATCHING_DONE MATCHING_MCSUCCESS" +
                " MATCHING_MCUNSUCC MATCHING_MMSUCCESS" +
                " MATCHING_MMUNSUCC MATCHING_PCSUCCESS" +
                " MATCHING_PCUNSUCC MATCHING_PMSUCCESS" +
                " MATCHING_PMUNSUCC MATCHING_PROBLEM" +
                " MATCHING_TIMEOUT MATCHING_UNQUALIFIED" +
                " PARALLEL_PORTCONN PARALLEL_PORTMAP" +
                " PARALLEL_PTC PARALLEL_UNQUALIFIED" +
                " PORTEVENT_DUALRECV PORTEVENT_DUALSEND" +
                " PORTEVENT_MCRECV PORTEVENT_MCSEND" +
                " PORTEVENT_MMRECV PORTEVENT_MMSEND" +
                " PORTEVENT_MQUEUE PORTEVENT_PCIN" +
                " PORTEVENT_PCOUT PORTEVENT_PMIN" +
                " PORTEVENT_PMOUT PORTEVENT_PQUEUE" +
                " PORTEVENT_STATE PORTEVENT_UNQUALIFIED" +
                " STATISTICS_UNQUALIFIED STATISTICS_VERDICT" +
                " TESTCASE_FINISH TESTCASE_START" +
                " TESTCASE_UNQUALIFIED TIMEROP_GUARD" +
                " TIMEROP_READ TIMEROP_START TIMEROP_STOP" +
                " TIMEROP_TIMEOUT TIMEROP_UNQUALIFIED" +
                " USER_UNQUALIFIED VERDICTOP_FINAL" +
                " VERDICTOP_GETVERDICT VERDICTOP_SETVERDICT" +
                " VERDICTOP_UNQUALIFIED WARNING_UNQUALIFIED"),
                externalCommands: words("BeginControlPart EndControlPart BeginTestCase" +
                " EndTestCase"),
                multiLineStrings: true
              });
            });
        • turtle
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Turtle mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="turtle.js"></script>
            <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Turtle</a>
              </ul>
            </div>
            
            <article>
            <h2>Turtle mode</h2>
            <form><textarea id="code" name="code">
            @prefix foaf: <http://xmlns.com/foaf/0.1/> .
            @prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> .
            @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
            
            <http://purl.org/net/bsletten> 
                a foaf:Person;
                foaf:interest <http://www.w3.org/2000/01/sw/>;
                foaf:based_near [
                    geo:lat "34.0736111" ;
                    geo:lon "-118.3994444"
               ]
            
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/turtle",
                    matchBrackets: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/turtle</code>.</p>
            
              </article>
            
          • turtle.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("turtle", function(config) {
              var indentUnit = config.indentUnit;
              var curPunc;
            
              function wordRegexp(words) {
                return new RegExp("^(?:" + words.join("|") + ")$", "i");
              }
              var ops = wordRegexp([]);
              var keywords = wordRegexp(["@prefix", "@base", "a"]);
              var operatorChars = /[*+\-<>=&|]/;
            
              function tokenBase(stream, state) {
                var ch = stream.next();
                curPunc = null;
                if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) {
                  stream.match(/^[^\s\u00a0>]*>?/);
                  return "atom";
                }
                else if (ch == "\"" || ch == "'") {
                  state.tokenize = tokenLiteral(ch);
                  return state.tokenize(stream, state);
                }
                else if (/[{}\(\),\.;\[\]]/.test(ch)) {
                  curPunc = ch;
                  return null;
                }
                else if (ch == "#") {
                  stream.skipToEnd();
                  return "comment";
                }
                else if (operatorChars.test(ch)) {
                  stream.eatWhile(operatorChars);
                  return null;
                }
                else if (ch == ":") {
                      return "operator";
                    } else {
                  stream.eatWhile(/[_\w\d]/);
                  if(stream.peek() == ":") {
                    return "variable-3";
                  } else {
                         var word = stream.current();
            
                         if(keywords.test(word)) {
                                    return "meta";
                         }
            
                         if(ch >= "A" && ch <= "Z") {
                                return "comment";
                             } else {
                                    return "keyword";
                             }
                  }
                  var word = stream.current();
                  if (ops.test(word))
                    return null;
                  else if (keywords.test(word))
                    return "meta";
                  else
                    return "variable";
                }
              }
            
              function tokenLiteral(quote) {
                return function(stream, state) {
                  var escaped = false, ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == quote && !escaped) {
                      state.tokenize = tokenBase;
                      break;
                    }
                    escaped = !escaped && ch == "\\";
                  }
                  return "string";
                };
              }
            
              function pushContext(state, type, col) {
                state.context = {prev: state.context, indent: state.indent, col: col, type: type};
              }
              function popContext(state) {
                state.indent = state.context.indent;
                state.context = state.context.prev;
              }
            
              return {
                startState: function() {
                  return {tokenize: tokenBase,
                          context: null,
                          indent: 0,
                          col: 0};
                },
            
                token: function(stream, state) {
                  if (stream.sol()) {
                    if (state.context && state.context.align == null) state.context.align = false;
                    state.indent = stream.indentation();
                  }
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
            
                  if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") {
                    state.context.align = true;
                  }
            
                  if (curPunc == "(") pushContext(state, ")", stream.column());
                  else if (curPunc == "[") pushContext(state, "]", stream.column());
                  else if (curPunc == "{") pushContext(state, "}", stream.column());
                  else if (/[\]\}\)]/.test(curPunc)) {
                    while (state.context && state.context.type == "pattern") popContext(state);
                    if (state.context && curPunc == state.context.type) popContext(state);
                  }
                  else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state);
                  else if (/atom|string|variable/.test(style) && state.context) {
                    if (/[\}\]]/.test(state.context.type))
                      pushContext(state, "pattern", stream.column());
                    else if (state.context.type == "pattern" && !state.context.align) {
                      state.context.align = true;
                      state.context.col = stream.column();
                    }
                  }
            
                  return style;
                },
            
                indent: function(state, textAfter) {
                  var firstChar = textAfter && textAfter.charAt(0);
                  var context = state.context;
                  if (/[\]\}]/.test(firstChar))
                    while (context && context.type == "pattern") context = context.prev;
            
                  var closing = context && firstChar == context.type;
                  if (!context)
                    return 0;
                  else if (context.type == "pattern")
                    return context.col;
                  else if (context.align)
                    return context.col + (closing ? 0 : 1);
                  else
                    return context.indent + (closing ? 0 : indentUnit);
                },
            
                lineComment: "#"
              };
            });
            
            CodeMirror.defineMIME("text/turtle", "turtle");
            
            });
            
        • vb
          • index.html
            <!doctype html>
            
            <title>CodeMirror: VB.NET mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link href="http://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet" type="text/css">
            <script src="../../lib/codemirror.js"></script>
            <script src="vb.js"></script>
            <script type="text/javascript" src="../../addon/runmode/runmode.js"></script>
            <style>
                  .CodeMirror {border: 1px solid #aaa; height:210px; height: auto;}
                  .CodeMirror-scroll { overflow-x: auto; overflow-y: hidden;}
                  .CodeMirror pre { font-family: Inconsolata; font-size: 14px}
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">VB.NET</a>
              </ul>
            </div>
            
            <article>
            <h2>VB.NET mode</h2>
            
            <script type="text/javascript">
            function test(golden, text) {
              var ok = true;
              var i = 0;
              function callback(token, style, lineNo, pos){
            		//console.log(String(token) + " " + String(style) + " " + String(lineNo) + " " + String(pos));
                var result = [String(token), String(style)];
                if (golden[i][0] != result[0] || golden[i][1] != result[1]){
                  return "Error, expected: " + String(golden[i]) + ", got: " + String(result);
                  ok = false;
                }
                i++;
              }
              CodeMirror.runMode(text, "text/x-vb",callback); 
            
              if (ok) return "Tests OK";
            }
            function testTypes() {
              var golden = [['Integer','keyword'],[' ','null'],['Float','keyword']]
              var text =  "Integer Float";
              return test(golden,text);
            }
            function testIf(){
              var golden = [['If','keyword'],[' ','null'],['True','keyword'],[' ','null'],['End','keyword'],[' ','null'],['If','keyword']];
              var text = 'If True End If';
              return test(golden, text);
            }
            function testDecl(){
               var golden = [['Dim','keyword'],[' ','null'],['x','variable'],[' ','null'],['as','keyword'],[' ','null'],['Integer','keyword']];
               var text = 'Dim x as Integer';
               return test(golden, text);
            }
            function testAll(){
              var result = "";
            
              result += testTypes() + "\n";
              result += testIf() + "\n";
              result += testDecl() + "\n";
              return result;
            
            }
            function initText(editor) {
              var content = 'Class rocket\nPrivate quality as Double\nPublic Sub launch() as String\nif quality > 0.8\nlaunch = "Successful"\nElse\nlaunch = "Failed"\nEnd If\nEnd sub\nEnd class\n';
              editor.setValue(content);
              for (var i =0; i< editor.lineCount(); i++) editor.indentLine(i);
            }
            function init() {
                editor = CodeMirror.fromTextArea(document.getElementById("solution"), {
                    lineNumbers: true,
                    mode: "text/x-vb",
                    readOnly: false
                });
                runTest();
            }
            function runTest() {
            	document.getElementById('testresult').innerHTML = testAll();
              initText(editor);
            	
            }
            document.body.onload = init;
            </script>
            
              <div id="edit">
              <textarea style="width:95%;height:200px;padding:5px;" name="solution" id="solution" ></textarea>
              </div>
              <pre id="testresult"></pre>
              <p>MIME type defined: <code>text/x-vb</code>.</p>
            
            </article>
            
          • vb.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("vb", function(conf, parserConf) {
                var ERRORCLASS = 'error';
            
                function wordRegexp(words) {
                    return new RegExp("^((" + words.join(")|(") + "))\\b", "i");
                }
            
                var singleOperators = new RegExp("^[\\+\\-\\*/%&\\\\|\\^~<>!]");
                var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
                var doubleOperators = new RegExp("^((==)|(<>)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
                var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
                var tripleDelimiters = new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
                var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
            
                var openingKeywords = ['class','module', 'sub','enum','select','while','if','function',  'get','set','property', 'try'];
                var middleKeywords = ['else','elseif','case', 'catch'];
                var endKeywords = ['next','loop'];
            
                var operatorKeywords = ['and', 'or', 'not', 'xor', 'in'];
                var wordOperators = wordRegexp(operatorKeywords);
                var commonKeywords = ['as', 'dim', 'break',  'continue','optional', 'then',  'until',
                                      'goto', 'byval','byref','new','handles','property', 'return',
                                      'const','private', 'protected', 'friend', 'public', 'shared', 'static', 'true','false'];
                var commontypes = ['integer','string','double','decimal','boolean','short','char', 'float','single'];
            
                var keywords = wordRegexp(commonKeywords);
                var types = wordRegexp(commontypes);
                var stringPrefixes = '"';
            
                var opening = wordRegexp(openingKeywords);
                var middle = wordRegexp(middleKeywords);
                var closing = wordRegexp(endKeywords);
                var doubleClosing = wordRegexp(['end']);
                var doOpening = wordRegexp(['do']);
            
                var indentInfo = null;
            
                CodeMirror.registerHelper("hintWords", "vb", openingKeywords.concat(middleKeywords).concat(endKeywords)
                                            .concat(operatorKeywords).concat(commonKeywords).concat(commontypes));
            
                function indent(_stream, state) {
                  state.currentIndent++;
                }
            
                function dedent(_stream, state) {
                  state.currentIndent--;
                }
                // tokenizers
                function tokenBase(stream, state) {
                    if (stream.eatSpace()) {
                        return null;
                    }
            
                    var ch = stream.peek();
            
                    // Handle Comments
                    if (ch === "'") {
                        stream.skipToEnd();
                        return 'comment';
                    }
            
            
                    // Handle Number Literals
                    if (stream.match(/^((&H)|(&O))?[0-9\.a-f]/i, false)) {
                        var floatLiteral = false;
                        // Floats
                        if (stream.match(/^\d*\.\d+F?/i)) { floatLiteral = true; }
                        else if (stream.match(/^\d+\.\d*F?/)) { floatLiteral = true; }
                        else if (stream.match(/^\.\d+F?/)) { floatLiteral = true; }
            
                        if (floatLiteral) {
                            // Float literals may be "imaginary"
                            stream.eat(/J/i);
                            return 'number';
                        }
                        // Integers
                        var intLiteral = false;
                        // Hex
                        if (stream.match(/^&H[0-9a-f]+/i)) { intLiteral = true; }
                        // Octal
                        else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; }
                        // Decimal
                        else if (stream.match(/^[1-9]\d*F?/)) {
                            // Decimal literals may be "imaginary"
                            stream.eat(/J/i);
                            // TODO - Can you have imaginary longs?
                            intLiteral = true;
                        }
                        // Zero by itself with no other piece of number.
                        else if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; }
                        if (intLiteral) {
                            // Integer literals may be "long"
                            stream.eat(/L/i);
                            return 'number';
                        }
                    }
            
                    // Handle Strings
                    if (stream.match(stringPrefixes)) {
                        state.tokenize = tokenStringFactory(stream.current());
                        return state.tokenize(stream, state);
                    }
            
                    // Handle operators and Delimiters
                    if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
                        return null;
                    }
                    if (stream.match(doubleOperators)
                        || stream.match(singleOperators)
                        || stream.match(wordOperators)) {
                        return 'operator';
                    }
                    if (stream.match(singleDelimiters)) {
                        return null;
                    }
                    if (stream.match(doOpening)) {
                        indent(stream,state);
                        state.doInCurrentLine = true;
                        return 'keyword';
                    }
                    if (stream.match(opening)) {
                        if (! state.doInCurrentLine)
                          indent(stream,state);
                        else
                          state.doInCurrentLine = false;
                        return 'keyword';
                    }
                    if (stream.match(middle)) {
                        return 'keyword';
                    }
            
                    if (stream.match(doubleClosing)) {
                        dedent(stream,state);
                        dedent(stream,state);
                        return 'keyword';
                    }
                    if (stream.match(closing)) {
                        dedent(stream,state);
                        return 'keyword';
                    }
            
                    if (stream.match(types)) {
                        return 'keyword';
                    }
            
                    if (stream.match(keywords)) {
                        return 'keyword';
                    }
            
                    if (stream.match(identifiers)) {
                        return 'variable';
                    }
            
                    // Handle non-detected items
                    stream.next();
                    return ERRORCLASS;
                }
            
                function tokenStringFactory(delimiter) {
                    var singleline = delimiter.length == 1;
                    var OUTCLASS = 'string';
            
                    return function(stream, state) {
                        while (!stream.eol()) {
                            stream.eatWhile(/[^'"]/);
                            if (stream.match(delimiter)) {
                                state.tokenize = tokenBase;
                                return OUTCLASS;
                            } else {
                                stream.eat(/['"]/);
                            }
                        }
                        if (singleline) {
                            if (parserConf.singleLineStringErrors) {
                                return ERRORCLASS;
                            } else {
                                state.tokenize = tokenBase;
                            }
                        }
                        return OUTCLASS;
                    };
                }
            
            
                function tokenLexer(stream, state) {
                    var style = state.tokenize(stream, state);
                    var current = stream.current();
            
                    // Handle '.' connected identifiers
                    if (current === '.') {
                        style = state.tokenize(stream, state);
                        current = stream.current();
                        if (style === 'variable') {
                            return 'variable';
                        } else {
                            return ERRORCLASS;
                        }
                    }
            
            
                    var delimiter_index = '[({'.indexOf(current);
                    if (delimiter_index !== -1) {
                        indent(stream, state );
                    }
                    if (indentInfo === 'dedent') {
                        if (dedent(stream, state)) {
                            return ERRORCLASS;
                        }
                    }
                    delimiter_index = '])}'.indexOf(current);
                    if (delimiter_index !== -1) {
                        if (dedent(stream, state)) {
                            return ERRORCLASS;
                        }
                    }
            
                    return style;
                }
            
                var external = {
                    electricChars:"dDpPtTfFeE ",
                    startState: function() {
                        return {
                          tokenize: tokenBase,
                          lastToken: null,
                          currentIndent: 0,
                          nextLineIndent: 0,
                          doInCurrentLine: false
            
            
                      };
                    },
            
                    token: function(stream, state) {
                        if (stream.sol()) {
                          state.currentIndent += state.nextLineIndent;
                          state.nextLineIndent = 0;
                          state.doInCurrentLine = 0;
                        }
                        var style = tokenLexer(stream, state);
            
                        state.lastToken = {style:style, content: stream.current()};
            
            
            
                        return style;
                    },
            
                    indent: function(state, textAfter) {
                        var trueText = textAfter.replace(/^\s+|\s+$/g, '') ;
                        if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1);
                        if(state.currentIndent < 0) return 0;
                        return state.currentIndent * conf.indentUnit;
                    }
            
                };
                return external;
            });
            
            CodeMirror.defineMIME("text/x-vb", "vb");
            
            });
            
        • vbscript
          • index.html
            <!doctype html>
            
            <title>CodeMirror: VBScript mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="vbscript.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">VBScript</a>
              </ul>
            </div>
            
            <article>
            <h2>VBScript mode</h2>
            
            
            <div><textarea id="code" name="code">
            ' Pete Guhl
            ' 03-04-2012
            '
            ' Basic VBScript support for codemirror2
            
            Const ForReading = 1, ForWriting = 2, ForAppending = 8
            
            Call Sub020_PostBroadcastToUrbanAirship(strUserName, strPassword, intTransmitID, strResponse)
            
            If Not IsNull(strResponse) AND Len(strResponse) = 0 Then
            	boolTransmitOkYN = False
            Else
            	' WScript.Echo "Oh Happy Day! Oh Happy DAY!"
            	boolTransmitOkYN = True
            End If
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    indentUnit: 4
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/vbscript</code>.</p>
              </article>
            
          • vbscript.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            /*
            For extra ASP classic objects, initialize CodeMirror instance with this option:
                isASP: true
            
            E.G.:
                var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    isASP: true
                  });
            */
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("vbscript", function(conf, parserConf) {
                var ERRORCLASS = 'error';
            
                function wordRegexp(words) {
                    return new RegExp("^((" + words.join(")|(") + "))\\b", "i");
                }
            
                var singleOperators = new RegExp("^[\\+\\-\\*/&\\\\\\^<>=]");
                var doubleOperators = new RegExp("^((<>)|(<=)|(>=))");
                var singleDelimiters = new RegExp('^[\\.,]');
                var brakets = new RegExp('^[\\(\\)]');
                var identifiers = new RegExp("^[A-Za-z][_A-Za-z0-9]*");
            
                var openingKeywords = ['class','sub','select','while','if','function', 'property', 'with', 'for'];
                var middleKeywords = ['else','elseif','case'];
                var endKeywords = ['next','loop','wend'];
            
                var wordOperators = wordRegexp(['and', 'or', 'not', 'xor', 'is', 'mod', 'eqv', 'imp']);
                var commonkeywords = ['dim', 'redim', 'then',  'until', 'randomize',
                                      'byval','byref','new','property', 'exit', 'in',
                                      'const','private', 'public',
                                      'get','set','let', 'stop', 'on error resume next', 'on error goto 0', 'option explicit', 'call', 'me'];
            
                //This list was from: http://msdn.microsoft.com/en-us/library/f8tbc79x(v=vs.84).aspx
                var atomWords = ['true', 'false', 'nothing', 'empty', 'null'];
                //This list was from: http://msdn.microsoft.com/en-us/library/3ca8tfek(v=vs.84).aspx
                var builtinFuncsWords = ['abs', 'array', 'asc', 'atn', 'cbool', 'cbyte', 'ccur', 'cdate', 'cdbl', 'chr', 'cint', 'clng', 'cos', 'csng', 'cstr', 'date', 'dateadd', 'datediff', 'datepart',
                                    'dateserial', 'datevalue', 'day', 'escape', 'eval', 'execute', 'exp', 'filter', 'formatcurrency', 'formatdatetime', 'formatnumber', 'formatpercent', 'getlocale', 'getobject',
                                    'getref', 'hex', 'hour', 'inputbox', 'instr', 'instrrev', 'int', 'fix', 'isarray', 'isdate', 'isempty', 'isnull', 'isnumeric', 'isobject', 'join', 'lbound', 'lcase', 'left',
                                    'len', 'loadpicture', 'log', 'ltrim', 'rtrim', 'trim', 'maths', 'mid', 'minute', 'month', 'monthname', 'msgbox', 'now', 'oct', 'replace', 'rgb', 'right', 'rnd', 'round',
                                    'scriptengine', 'scriptenginebuildversion', 'scriptenginemajorversion', 'scriptengineminorversion', 'second', 'setlocale', 'sgn', 'sin', 'space', 'split', 'sqr', 'strcomp',
                                    'string', 'strreverse', 'tan', 'time', 'timer', 'timeserial', 'timevalue', 'typename', 'ubound', 'ucase', 'unescape', 'vartype', 'weekday', 'weekdayname', 'year'];
            
                //This list was from: http://msdn.microsoft.com/en-us/library/ydz4cfk3(v=vs.84).aspx
                var builtinConsts = ['vbBlack', 'vbRed', 'vbGreen', 'vbYellow', 'vbBlue', 'vbMagenta', 'vbCyan', 'vbWhite', 'vbBinaryCompare', 'vbTextCompare',
                                     'vbSunday', 'vbMonday', 'vbTuesday', 'vbWednesday', 'vbThursday', 'vbFriday', 'vbSaturday', 'vbUseSystemDayOfWeek', 'vbFirstJan1', 'vbFirstFourDays', 'vbFirstFullWeek',
                                     'vbGeneralDate', 'vbLongDate', 'vbShortDate', 'vbLongTime', 'vbShortTime', 'vbObjectError',
                                     'vbOKOnly', 'vbOKCancel', 'vbAbortRetryIgnore', 'vbYesNoCancel', 'vbYesNo', 'vbRetryCancel', 'vbCritical', 'vbQuestion', 'vbExclamation', 'vbInformation', 'vbDefaultButton1', 'vbDefaultButton2',
                                     'vbDefaultButton3', 'vbDefaultButton4', 'vbApplicationModal', 'vbSystemModal', 'vbOK', 'vbCancel', 'vbAbort', 'vbRetry', 'vbIgnore', 'vbYes', 'vbNo',
                                     'vbCr', 'VbCrLf', 'vbFormFeed', 'vbLf', 'vbNewLine', 'vbNullChar', 'vbNullString', 'vbTab', 'vbVerticalTab', 'vbUseDefault', 'vbTrue', 'vbFalse',
                                     'vbEmpty', 'vbNull', 'vbInteger', 'vbLong', 'vbSingle', 'vbDouble', 'vbCurrency', 'vbDate', 'vbString', 'vbObject', 'vbError', 'vbBoolean', 'vbVariant', 'vbDataObject', 'vbDecimal', 'vbByte', 'vbArray'];
                //This list was from: http://msdn.microsoft.com/en-us/library/hkc375ea(v=vs.84).aspx
                var builtinObjsWords = ['WScript', 'err', 'debug', 'RegExp'];
                var knownProperties = ['description', 'firstindex', 'global', 'helpcontext', 'helpfile', 'ignorecase', 'length', 'number', 'pattern', 'source', 'value', 'count'];
                var knownMethods = ['clear', 'execute', 'raise', 'replace', 'test', 'write', 'writeline', 'close', 'open', 'state', 'eof', 'update', 'addnew', 'end', 'createobject', 'quit'];
            
                var aspBuiltinObjsWords = ['server', 'response', 'request', 'session', 'application'];
                var aspKnownProperties = ['buffer', 'cachecontrol', 'charset', 'contenttype', 'expires', 'expiresabsolute', 'isclientconnected', 'pics', 'status', //response
                                          'clientcertificate', 'cookies', 'form', 'querystring', 'servervariables', 'totalbytes', //request
                                          'contents', 'staticobjects', //application
                                          'codepage', 'lcid', 'sessionid', 'timeout', //session
                                          'scripttimeout']; //server
                var aspKnownMethods = ['addheader', 'appendtolog', 'binarywrite', 'end', 'flush', 'redirect', //response
                                       'binaryread', //request
                                       'remove', 'removeall', 'lock', 'unlock', //application
                                       'abandon', //session
                                       'getlasterror', 'htmlencode', 'mappath', 'transfer', 'urlencode']; //server
            
                var knownWords = knownMethods.concat(knownProperties);
            
                builtinObjsWords = builtinObjsWords.concat(builtinConsts);
            
                if (conf.isASP){
                    builtinObjsWords = builtinObjsWords.concat(aspBuiltinObjsWords);
                    knownWords = knownWords.concat(aspKnownMethods, aspKnownProperties);
                };
            
                var keywords = wordRegexp(commonkeywords);
                var atoms = wordRegexp(atomWords);
                var builtinFuncs = wordRegexp(builtinFuncsWords);
                var builtinObjs = wordRegexp(builtinObjsWords);
                var known = wordRegexp(knownWords);
                var stringPrefixes = '"';
            
                var opening = wordRegexp(openingKeywords);
                var middle = wordRegexp(middleKeywords);
                var closing = wordRegexp(endKeywords);
                var doubleClosing = wordRegexp(['end']);
                var doOpening = wordRegexp(['do']);
                var noIndentWords = wordRegexp(['on error resume next', 'exit']);
                var comment = wordRegexp(['rem']);
            
            
                function indent(_stream, state) {
                  state.currentIndent++;
                }
            
                function dedent(_stream, state) {
                  state.currentIndent--;
                }
                // tokenizers
                function tokenBase(stream, state) {
                    if (stream.eatSpace()) {
                        return 'space';
                        //return null;
                    }
            
                    var ch = stream.peek();
            
                    // Handle Comments
                    if (ch === "'") {
                        stream.skipToEnd();
                        return 'comment';
                    }
                    if (stream.match(comment)){
                        stream.skipToEnd();
                        return 'comment';
                    }
            
            
                    // Handle Number Literals
                    if (stream.match(/^((&H)|(&O))?[0-9\.]/i, false) && !stream.match(/^((&H)|(&O))?[0-9\.]+[a-z_]/i, false)) {
                        var floatLiteral = false;
                        // Floats
                        if (stream.match(/^\d*\.\d+/i)) { floatLiteral = true; }
                        else if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; }
                        else if (stream.match(/^\.\d+/)) { floatLiteral = true; }
            
                        if (floatLiteral) {
                            // Float literals may be "imaginary"
                            stream.eat(/J/i);
                            return 'number';
                        }
                        // Integers
                        var intLiteral = false;
                        // Hex
                        if (stream.match(/^&H[0-9a-f]+/i)) { intLiteral = true; }
                        // Octal
                        else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; }
                        // Decimal
                        else if (stream.match(/^[1-9]\d*F?/)) {
                            // Decimal literals may be "imaginary"
                            stream.eat(/J/i);
                            // TODO - Can you have imaginary longs?
                            intLiteral = true;
                        }
                        // Zero by itself with no other piece of number.
                        else if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; }
                        if (intLiteral) {
                            // Integer literals may be "long"
                            stream.eat(/L/i);
                            return 'number';
                        }
                    }
            
                    // Handle Strings
                    if (stream.match(stringPrefixes)) {
                        state.tokenize = tokenStringFactory(stream.current());
                        return state.tokenize(stream, state);
                    }
            
                    // Handle operators and Delimiters
                    if (stream.match(doubleOperators)
                        || stream.match(singleOperators)
                        || stream.match(wordOperators)) {
                        return 'operator';
                    }
                    if (stream.match(singleDelimiters)) {
                        return null;
                    }
            
                    if (stream.match(brakets)) {
                        return "bracket";
                    }
            
                    if (stream.match(noIndentWords)) {
                        state.doInCurrentLine = true;
            
                        return 'keyword';
                    }
            
                    if (stream.match(doOpening)) {
                        indent(stream,state);
                        state.doInCurrentLine = true;
            
                        return 'keyword';
                    }
                    if (stream.match(opening)) {
                        if (! state.doInCurrentLine)
                          indent(stream,state);
                        else
                          state.doInCurrentLine = false;
            
                        return 'keyword';
                    }
                    if (stream.match(middle)) {
                        return 'keyword';
                    }
            
            
                    if (stream.match(doubleClosing)) {
                        dedent(stream,state);
                        dedent(stream,state);
            
                        return 'keyword';
                    }
                    if (stream.match(closing)) {
                        if (! state.doInCurrentLine)
                          dedent(stream,state);
                        else
                          state.doInCurrentLine = false;
            
                        return 'keyword';
                    }
            
                    if (stream.match(keywords)) {
                        return 'keyword';
                    }
            
                    if (stream.match(atoms)) {
                        return 'atom';
                    }
            
                    if (stream.match(known)) {
                        return 'variable-2';
                    }
            
                    if (stream.match(builtinFuncs)) {
                        return 'builtin';
                    }
            
                    if (stream.match(builtinObjs)){
                        return 'variable-2';
                    }
            
                    if (stream.match(identifiers)) {
                        return 'variable';
                    }
            
                    // Handle non-detected items
                    stream.next();
                    return ERRORCLASS;
                }
            
                function tokenStringFactory(delimiter) {
                    var singleline = delimiter.length == 1;
                    var OUTCLASS = 'string';
            
                    return function(stream, state) {
                        while (!stream.eol()) {
                            stream.eatWhile(/[^'"]/);
                            if (stream.match(delimiter)) {
                                state.tokenize = tokenBase;
                                return OUTCLASS;
                            } else {
                                stream.eat(/['"]/);
                            }
                        }
                        if (singleline) {
                            if (parserConf.singleLineStringErrors) {
                                return ERRORCLASS;
                            } else {
                                state.tokenize = tokenBase;
                            }
                        }
                        return OUTCLASS;
                    };
                }
            
            
                function tokenLexer(stream, state) {
                    var style = state.tokenize(stream, state);
                    var current = stream.current();
            
                    // Handle '.' connected identifiers
                    if (current === '.') {
                        style = state.tokenize(stream, state);
            
                        current = stream.current();
                        if (style && (style.substr(0, 8) === 'variable' || style==='builtin' || style==='keyword')){//|| knownWords.indexOf(current.substring(1)) > -1) {
                            if (style === 'builtin' || style === 'keyword') style='variable';
                            if (knownWords.indexOf(current.substr(1)) > -1) style='variable-2';
            
                            return style;
                        } else {
                            return ERRORCLASS;
                        }
                    }
            
                    return style;
                }
            
                var external = {
                    electricChars:"dDpPtTfFeE ",
                    startState: function() {
                        return {
                          tokenize: tokenBase,
                          lastToken: null,
                          currentIndent: 0,
                          nextLineIndent: 0,
                          doInCurrentLine: false,
                          ignoreKeyword: false
            
            
                      };
                    },
            
                    token: function(stream, state) {
                        if (stream.sol()) {
                          state.currentIndent += state.nextLineIndent;
                          state.nextLineIndent = 0;
                          state.doInCurrentLine = 0;
                        }
                        var style = tokenLexer(stream, state);
            
                        state.lastToken = {style:style, content: stream.current()};
            
                        if (style==='space') style=null;
            
                        return style;
                    },
            
                    indent: function(state, textAfter) {
                        var trueText = textAfter.replace(/^\s+|\s+$/g, '') ;
                        if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1);
                        if(state.currentIndent < 0) return 0;
                        return state.currentIndent * conf.indentUnit;
                    }
            
                };
                return external;
            });
            
            CodeMirror.defineMIME("text/vbscript", "vbscript");
            
            });
            
        • velocity
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Velocity mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/night.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="velocity.js"></script>
            <style>.CodeMirror {border: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Velocity</a>
              </ul>
            </div>
            
            <article>
            <h2>Velocity mode</h2>
            <form><textarea id="code" name="code">
            ## Velocity Code Demo
            #*
               based on PL/SQL mode by Peter Raganitsch, adapted to Velocity by Steve O'Hara ( http://www.pivotal-solutions.co.uk )
               August 2011
            *#
            
            #*
               This is a multiline comment.
               This is the second line
            *#
            
            #[[ hello steve
               This has invalid syntax that would normally need "poor man's escaping" like:
            
               #define()
            
               ${blah
            ]]#
            
            #include( "disclaimer.txt" "opinion.txt" )
            #include( $foo $bar )
            
            #parse( "lecorbusier.vm" )
            #parse( $foo )
            
            #evaluate( 'string with VTL #if(true)will be displayed#end' )
            
            #define( $hello ) Hello $who #end #set( $who = "World!") $hello ## displays Hello World!
            
            #foreach( $customer in $customerList )
            
                $foreach.count $customer.Name
            
                #if( $foo == ${bar})
                    it's true!
                    #break
                #{else}
                    it's not!
                    #stop
                #end
            
                #if ($foreach.parent.hasNext)
                    $velocityCount
                #end
            #end
            
            $someObject.getValues("this is a string split
                    across lines")
            
            $someObject("This plus $something in the middle").method(7567).property
            
            #macro( tablerows $color $somelist )
                #foreach( $something in $somelist )
                    <tr><td bgcolor=$color>$something</td></tr>
                    <tr><td bgcolor=$color>$bodyContent</td></tr>
                #end
            #end
            
            #tablerows("red" ["dadsdf","dsa"])
            #@tablerows("red" ["dadsdf","dsa"]) some body content #end
            
               Variable reference: #set( $monkey = $bill )
               String literal: #set( $monkey.Friend = 'monica' )
               Property reference: #set( $monkey.Blame = $whitehouse.Leak )
               Method reference: #set( $monkey.Plan = $spindoctor.weave($web) )
               Number literal: #set( $monkey.Number = 123 )
               Range operator: #set( $monkey.Numbers = [1..3] )
               Object list: #set( $monkey.Say = ["Not", $my, "fault"] )
               Object map: #set( $monkey.Map = {"banana" : "good", "roast beef" : "bad"})
            
            The RHS can also be a simple arithmetic expression, such as:
            Addition: #set( $value = $foo + 1 )
               Subtraction: #set( $value = $bar - 1 )
               Multiplication: #set( $value = $foo * $bar )
               Division: #set( $value = $foo / $bar )
               Remainder: #set( $value = $foo % $bar )
            
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    theme: "night",
                    lineNumbers: true,
                    indentUnit: 4,
                    mode: "text/velocity"
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/velocity</code>.</p>
            
              </article>
            
          • velocity.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("velocity", function() {
                function parseWords(str) {
                    var obj = {}, words = str.split(" ");
                    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                    return obj;
                }
            
                var keywords = parseWords("#end #else #break #stop #[[ #]] " +
                                          "#{end} #{else} #{break} #{stop}");
                var functions = parseWords("#if #elseif #foreach #set #include #parse #macro #define #evaluate " +
                                           "#{if} #{elseif} #{foreach} #{set} #{include} #{parse} #{macro} #{define} #{evaluate}");
                var specials = parseWords("$foreach.count $foreach.hasNext $foreach.first $foreach.last $foreach.topmost $foreach.parent.count $foreach.parent.hasNext $foreach.parent.first $foreach.parent.last $foreach.parent $velocityCount $!bodyContent $bodyContent");
                var isOperatorChar = /[+\-*&%=<>!?:\/|]/;
            
                function chain(stream, state, f) {
                    state.tokenize = f;
                    return f(stream, state);
                }
                function tokenBase(stream, state) {
                    var beforeParams = state.beforeParams;
                    state.beforeParams = false;
                    var ch = stream.next();
                    // start of unparsed string?
                    if ((ch == "'") && state.inParams) {
                        state.lastTokenWasBuiltin = false;
                        return chain(stream, state, tokenString(ch));
                    }
                    // start of parsed string?
                    else if ((ch == '"')) {
                        state.lastTokenWasBuiltin = false;
                        if (state.inString) {
                            state.inString = false;
                            return "string";
                        }
                        else if (state.inParams)
                            return chain(stream, state, tokenString(ch));
                    }
                    // is it one of the special signs []{}().,;? Seperator?
                    else if (/[\[\]{}\(\),;\.]/.test(ch)) {
                        if (ch == "(" && beforeParams)
                            state.inParams = true;
                        else if (ch == ")") {
                            state.inParams = false;
                            state.lastTokenWasBuiltin = true;
                        }
                        return null;
                    }
                    // start of a number value?
                    else if (/\d/.test(ch)) {
                        state.lastTokenWasBuiltin = false;
                        stream.eatWhile(/[\w\.]/);
                        return "number";
                    }
                    // multi line comment?
                    else if (ch == "#" && stream.eat("*")) {
                        state.lastTokenWasBuiltin = false;
                        return chain(stream, state, tokenComment);
                    }
                    // unparsed content?
                    else if (ch == "#" && stream.match(/ *\[ *\[/)) {
                        state.lastTokenWasBuiltin = false;
                        return chain(stream, state, tokenUnparsed);
                    }
                    // single line comment?
                    else if (ch == "#" && stream.eat("#")) {
                        state.lastTokenWasBuiltin = false;
                        stream.skipToEnd();
                        return "comment";
                    }
                    // variable?
                    else if (ch == "$") {
                        stream.eatWhile(/[\w\d\$_\.{}]/);
                        // is it one of the specials?
                        if (specials && specials.propertyIsEnumerable(stream.current())) {
                            return "keyword";
                        }
                        else {
                            state.lastTokenWasBuiltin = true;
                            state.beforeParams = true;
                            return "builtin";
                        }
                    }
                    // is it a operator?
                    else if (isOperatorChar.test(ch)) {
                        state.lastTokenWasBuiltin = false;
                        stream.eatWhile(isOperatorChar);
                        return "operator";
                    }
                    else {
                        // get the whole word
                        stream.eatWhile(/[\w\$_{}@]/);
                        var word = stream.current();
                        // is it one of the listed keywords?
                        if (keywords && keywords.propertyIsEnumerable(word))
                            return "keyword";
                        // is it one of the listed functions?
                        if (functions && functions.propertyIsEnumerable(word) ||
                                (stream.current().match(/^#@?[a-z0-9_]+ *$/i) && stream.peek()=="(") &&
                                 !(functions && functions.propertyIsEnumerable(word.toLowerCase()))) {
                            state.beforeParams = true;
                            state.lastTokenWasBuiltin = false;
                            return "keyword";
                        }
                        if (state.inString) {
                            state.lastTokenWasBuiltin = false;
                            return "string";
                        }
                        if (stream.pos > word.length && stream.string.charAt(stream.pos-word.length-1)=="." && state.lastTokenWasBuiltin)
                            return "builtin";
                        // default: just a "word"
                        state.lastTokenWasBuiltin = false;
                        return null;
                    }
                }
            
                function tokenString(quote) {
                    return function(stream, state) {
                        var escaped = false, next, end = false;
                        while ((next = stream.next()) != null) {
                            if ((next == quote) && !escaped) {
                                end = true;
                                break;
                            }
                            if (quote=='"' && stream.peek() == '$' && !escaped) {
                                state.inString = true;
                                end = true;
                                break;
                            }
                            escaped = !escaped && next == "\\";
                        }
                        if (end) state.tokenize = tokenBase;
                        return "string";
                    };
                }
            
                function tokenComment(stream, state) {
                    var maybeEnd = false, ch;
                    while (ch = stream.next()) {
                        if (ch == "#" && maybeEnd) {
                            state.tokenize = tokenBase;
                            break;
                        }
                        maybeEnd = (ch == "*");
                    }
                    return "comment";
                }
            
                function tokenUnparsed(stream, state) {
                    var maybeEnd = 0, ch;
                    while (ch = stream.next()) {
                        if (ch == "#" && maybeEnd == 2) {
                            state.tokenize = tokenBase;
                            break;
                        }
                        if (ch == "]")
                            maybeEnd++;
                        else if (ch != " ")
                            maybeEnd = 0;
                    }
                    return "meta";
                }
                // Interface
            
                return {
                    startState: function() {
                        return {
                            tokenize: tokenBase,
                            beforeParams: false,
                            inParams: false,
                            inString: false,
                            lastTokenWasBuiltin: false
                        };
                    },
            
                    token: function(stream, state) {
                        if (stream.eatSpace()) return null;
                        return state.tokenize(stream, state);
                    },
                    blockCommentStart: "#*",
                    blockCommentEnd: "*#",
                    lineComment: "##",
                    fold: "velocity"
                };
            });
            
            CodeMirror.defineMIME("text/velocity", "velocity");
            
            });
            
        • verilog
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Verilog/SystemVerilog mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="../../addon/edit/matchbrackets.js"></script>
            <script src="verilog.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Verilog/SystemVerilog</a>
              </ul>
            </div>
            
            <article>
            <h2>SystemVerilog mode</h2>
            
            <div><textarea id="code" name="code">
            // Literals
            1'b0
            1'bx
            1'bz
            16'hDC78
            'hdeadbeef
            'b0011xxzz
            1234
            32'd5678
            3.4e6
            -128.7
            
            // Macro definition
            `define BUS_WIDTH = 8;
            
            // Module definition
            module block(
              input                   clk,
              input                   rst_n,
              input  [`BUS_WIDTH-1:0] data_in,
              output [`BUS_WIDTH-1:0] data_out
            );
              
              always @(posedge clk or negedge rst_n) begin
            
                if (~rst_n) begin
                  data_out <= 8'b0;
                end else begin
                  data_out <= data_in;
                end
                
                if (~rst_n)
                  data_out <= 8'b0;
                else
                  data_out <= data_in;
                
                if (~rst_n)
                  begin
                    data_out <= 8'b0;
                  end
                else
                  begin
                    data_out <= data_in;
                  end
            
              end
              
            endmodule
            
            // Class definition
            class test;
            
              /**
               * Sum two integers
               */
              function int sum(int a, int b);
                int result = a + b;
                string msg = $sformatf("%d + %d = %d", a, b, result);
                $display(msg);
                return result;
              endfunction
              
              task delay(int num_cycles);
                repeat(num_cycles) #1;
              endtask
              
            endclass
            
            </textarea></div>
            
            <script>
              var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                lineNumbers: true,
                matchBrackets: true,
                mode: {
                  name: "verilog",
                  noIndentKeywords: ["package"]
                }
              });
            </script>
            
            <p>
            Syntax highlighting and indentation for the Verilog and SystemVerilog languages (IEEE 1800).
            <h2>Configuration options:</h2>
              <ul>
                <li><strong>noIndentKeywords</strong> - List of keywords which should not cause identation to increase. E.g. ["package", "module"]. Default: None</li>
              </ul>
            </p>
            
            <p><strong>MIME types defined:</strong> <code>text/x-verilog</code> and <code>text/x-systemverilog</code>.</p>
            </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 4}, "verilog");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT("binary_literals",
                 "[number 1'b0]",
                 "[number 1'b1]",
                 "[number 1'bx]",
                 "[number 1'bz]",
                 "[number 1'bX]",
                 "[number 1'bZ]",
                 "[number 1'B0]",
                 "[number 1'B1]",
                 "[number 1'Bx]",
                 "[number 1'Bz]",
                 "[number 1'BX]",
                 "[number 1'BZ]",
                 "[number 1'b0]",
                 "[number 1'b1]",
                 "[number 2'b01]",
                 "[number 2'bxz]",
                 "[number 2'b11]",
                 "[number 2'b10]",
                 "[number 2'b1Z]",
                 "[number 12'b0101_0101_0101]",
                 "[number 1'b 0]",
                 "[number 'b0101]"
              );
            
              MT("octal_literals",
                 "[number 3'o7]",
                 "[number 3'O7]",
                 "[number 3'so7]",
                 "[number 3'SO7]"
              );
            
              MT("decimal_literals",
                 "[number 0]",
                 "[number 1]",
                 "[number 7]",
                 "[number 123_456]",
                 "[number 'd33]",
                 "[number 8'd255]",
                 "[number 8'D255]",
                 "[number 8'sd255]",
                 "[number 8'SD255]",
                 "[number 32'd123]",
                 "[number 32 'd123]",
                 "[number 32 'd 123]"
              );
            
              MT("hex_literals",
                 "[number 4'h0]",
                 "[number 4'ha]",
                 "[number 4'hF]",
                 "[number 4'hx]",
                 "[number 4'hz]",
                 "[number 4'hX]",
                 "[number 4'hZ]",
                 "[number 32'hdc78]",
                 "[number 32'hDC78]",
                 "[number 32 'hDC78]",
                 "[number 32'h DC78]",
                 "[number 32 'h DC78]",
                 "[number 32'h44x7]",
                 "[number 32'hFFF?]"
              );
            
              MT("real_number_literals",
                 "[number 1.2]",
                 "[number 0.1]",
                 "[number 2394.26331]",
                 "[number 1.2E12]",
                 "[number 1.2e12]",
                 "[number 1.30e-2]",
                 "[number 0.1e-0]",
                 "[number 23E10]",
                 "[number 29E-2]",
                 "[number 236.123_763_e-12]"
              );
            
              MT("operators",
                 "[meta ^]"
              );
            
              MT("keywords",
                 "[keyword logic]",
                 "[keyword logic] [variable foo]",
                 "[keyword reg] [variable abc]"
              );
            
              MT("variables",
                 "[variable _leading_underscore]",
                 "[variable _if]",
                 "[number 12] [variable foo]",
                 "[variable foo] [number 14]"
              );
            
              MT("tick_defines",
                 "[def `FOO]",
                 "[def `foo]",
                 "[def `FOO_bar]"
              );
            
              MT("system_calls",
                 "[meta $display]",
                 "[meta $vpi_printf]"
              );
            
              MT("line_comment", "[comment // Hello world]");
            
              // Alignment tests
              MT("align_port_map_style1",
                 /**
                  * mod mod(.a(a),
                  *         .b(b)
                  *        );
                  */
                 "[variable mod] [variable mod][bracket (].[variable a][bracket (][variable a][bracket )],",
                 "        .[variable b][bracket (][variable b][bracket )]",
                 "       [bracket )];",
                 ""
              );
            
              MT("align_port_map_style2",
                 /**
                  * mod mod(
                  *     .a(a),
                  *     .b(b)
                  * );
                  */
                 "[variable mod] [variable mod][bracket (]",
                 "    .[variable a][bracket (][variable a][bracket )],",
                 "    .[variable b][bracket (][variable b][bracket )]",
                 "[bracket )];",
                 ""
              );
            
              // Indentation tests
              MT("indent_single_statement_if",
                  "[keyword if] [bracket (][variable foo][bracket )]",
                  "    [keyword break];",
                  ""
              );
            
              MT("no_indent_after_single_line_if",
                  "[keyword if] [bracket (][variable foo][bracket )] [keyword break];",
                  ""
              );
            
              MT("indent_after_if_begin_same_line",
                  "[keyword if] [bracket (][variable foo][bracket )] [keyword begin]",
                  "    [keyword break];",
                  "    [keyword break];",
                  "[keyword end]",
                  ""
              );
            
              MT("indent_after_if_begin_next_line",
                  "[keyword if] [bracket (][variable foo][bracket )]",
                  "    [keyword begin]",
                  "        [keyword break];",
                  "        [keyword break];",
                  "    [keyword end]",
                  ""
              );
            
              MT("indent_single_statement_if_else",
                  "[keyword if] [bracket (][variable foo][bracket )]",
                  "    [keyword break];",
                  "[keyword else]",
                  "    [keyword break];",
                  ""
              );
            
              MT("indent_if_else_begin_same_line",
                  "[keyword if] [bracket (][variable foo][bracket )] [keyword begin]",
                  "    [keyword break];",
                  "    [keyword break];",
                  "[keyword end] [keyword else] [keyword begin]",
                  "    [keyword break];",
                  "    [keyword break];",
                  "[keyword end]",
                  ""
              );
            
              MT("indent_if_else_begin_next_line",
                  "[keyword if] [bracket (][variable foo][bracket )]",
                  "    [keyword begin]",
                  "        [keyword break];",
                  "        [keyword break];",
                  "    [keyword end]",
                  "[keyword else]",
                  "    [keyword begin]",
                  "        [keyword break];",
                  "        [keyword break];",
                  "    [keyword end]",
                  ""
              );
            
              MT("indent_if_nested_without_begin",
                  "[keyword if] [bracket (][variable foo][bracket )]",
                  "    [keyword if] [bracket (][variable foo][bracket )]",
                  "        [keyword if] [bracket (][variable foo][bracket )]",
                  "            [keyword break];",
                  ""
              );
            
              MT("indent_case",
                  "[keyword case] [bracket (][variable state][bracket )]",
                  "    [variable FOO]:",
                  "        [keyword break];",
                  "    [variable BAR]:",
                  "        [keyword break];",
                  "[keyword endcase]",
                  ""
              );
            
              MT("unindent_after_end_with_preceding_text",
                  "[keyword begin]",
                  "    [keyword break]; [keyword end]",
                  ""
              );
            
              MT("export_function_one_line_does_not_indent",
                 "[keyword export] [string \"DPI-C\"] [keyword function] [variable helloFromSV];",
                 ""
              );
            
              MT("export_task_one_line_does_not_indent",
                 "[keyword export] [string \"DPI-C\"] [keyword task] [variable helloFromSV];",
                 ""
              );
            
              MT("export_function_two_lines_indents_properly",
                "[keyword export]",
                "    [string \"DPI-C\"] [keyword function] [variable helloFromSV];",
                ""
              );
            
              MT("export_task_two_lines_indents_properly",
                "[keyword export]",
                "    [string \"DPI-C\"] [keyword task] [variable helloFromSV];",
                ""
              );
            
              MT("import_function_one_line_does_not_indent",
                "[keyword import] [string \"DPI-C\"] [keyword function] [variable helloFromC];",
                ""
              );
            
              MT("import_task_one_line_does_not_indent",
                "[keyword import] [string \"DPI-C\"] [keyword task] [variable helloFromC];",
                ""
              );
            
              MT("import_package_single_line_does_not_indent",
                "[keyword import] [variable p]::[variable x];",
                "[keyword import] [variable p]::[variable y];",
                ""
              );
            
              MT("covergoup_with_function_indents_properly",
                "[keyword covergroup] [variable cg] [keyword with] [keyword function] [variable sample][bracket (][keyword bit] [variable b][bracket )];",
                "    [variable c] : [keyword coverpoint] [variable c];",
                "[keyword endgroup]: [variable cg]",
                ""
              );
            
            })();
            
          • verilog.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("verilog", function(config, parserConfig) {
            
              var indentUnit = config.indentUnit,
                  statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
                  dontAlignCalls = parserConfig.dontAlignCalls,
                  noIndentKeywords = parserConfig.noIndentKeywords || [],
                  multiLineStrings = parserConfig.multiLineStrings,
                  hooks = parserConfig.hooks || {};
            
              function words(str) {
                var obj = {}, words = str.split(" ");
                for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
                return obj;
              }
            
              /**
               * Keywords from IEEE 1800-2012
               */
              var keywords = words(
                "accept_on alias always always_comb always_ff always_latch and assert assign assume automatic before begin bind " +
                "bins binsof bit break buf bufif0 bufif1 byte case casex casez cell chandle checker class clocking cmos config " +
                "const constraint context continue cover covergroup coverpoint cross deassign default defparam design disable " +
                "dist do edge else end endcase endchecker endclass endclocking endconfig endfunction endgenerate endgroup " +
                "endinterface endmodule endpackage endprimitive endprogram endproperty endspecify endsequence endtable endtask " +
                "enum event eventually expect export extends extern final first_match for force foreach forever fork forkjoin " +
                "function generate genvar global highz0 highz1 if iff ifnone ignore_bins illegal_bins implements implies import " +
                "incdir include initial inout input inside instance int integer interconnect interface intersect join join_any " +
                "join_none large let liblist library local localparam logic longint macromodule matches medium modport module " +
                "nand negedge nettype new nexttime nmos nor noshowcancelled not notif0 notif1 null or output package packed " +
                "parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup " +
                "pulsestyle_ondetect pulsestyle_onevent pure rand randc randcase randsequence rcmos real realtime ref reg " +
                "reject_on release repeat restrict return rnmos rpmos rtran rtranif0 rtranif1 s_always s_eventually s_nexttime " +
                "s_until s_until_with scalared sequence shortint shortreal showcancelled signed small soft solve specify " +
                "specparam static string strong strong0 strong1 struct super supply0 supply1 sync_accept_on sync_reject_on " +
                "table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior " +
                "trireg type typedef union unique unique0 unsigned until until_with untyped use uwire var vectored virtual void " +
                "wait wait_order wand weak weak0 weak1 while wildcard wire with within wor xnor xor");
            
              /** Operators from IEEE 1800-2012
                 unary_operator ::=
                   + | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
                 binary_operator ::=
                   + | - | * | / | % | == | != | === | !== | ==? | !=? | && | || | **
                   | < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<<
                   | -> | <->
                 inc_or_dec_operator ::= ++ | --
                 unary_module_path_operator ::=
                   ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
                 binary_module_path_operator ::=
                   == | != | && | || | & | | | ^ | ^~ | ~^
              */
              var isOperatorChar = /[\+\-\*\/!~&|^%=?:]/;
              var isBracketChar = /[\[\]{}()]/;
            
              var unsignedNumber = /\d[0-9_]*/;
              var decimalLiteral = /\d*\s*'s?d\s*\d[0-9_]*/i;
              var binaryLiteral = /\d*\s*'s?b\s*[xz01][xz01_]*/i;
              var octLiteral = /\d*\s*'s?o\s*[xz0-7][xz0-7_]*/i;
              var hexLiteral = /\d*\s*'s?h\s*[0-9a-fxz?][0-9a-fxz?_]*/i;
              var realLiteral = /(\d[\d_]*(\.\d[\d_]*)?E-?[\d_]+)|(\d[\d_]*\.\d[\d_]*)/i;
            
              var closingBracketOrWord = /^((\w+)|[)}\]])/;
              var closingBracket = /[)}\]]/;
            
              var curPunc;
              var curKeyword;
            
              // Block openings which are closed by a matching keyword in the form of ("end" + keyword)
              // E.g. "task" => "endtask"
              var blockKeywords = words(
                "case checker class clocking config function generate interface module package" +
                "primitive program property specify sequence table task"
              );
            
              // Opening/closing pairs
              var openClose = {};
              for (var keyword in blockKeywords) {
                openClose[keyword] = "end" + keyword;
              }
              openClose["begin"] = "end";
              openClose["casex"] = "endcase";
              openClose["casez"] = "endcase";
              openClose["do"   ] = "while";
              openClose["fork" ] = "join;join_any;join_none";
              openClose["covergroup"] = "endgroup";
            
              for (var i in noIndentKeywords) {
                var keyword = noIndentKeywords[i];
                if (openClose[keyword]) {
                  openClose[keyword] = undefined;
                }
              }
            
              // Keywords which open statements that are ended with a semi-colon
              var statementKeywords = words("always always_comb always_ff always_latch assert assign assume else export for foreach forever if import initial repeat while");
            
              function tokenBase(stream, state) {
                var ch = stream.peek(), style;
                if (hooks[ch] && (style = hooks[ch](stream, state)) != false) return style;
                if (hooks.tokenBase && (style = hooks.tokenBase(stream, state)) != false)
                  return style;
            
                if (/[,;:\.]/.test(ch)) {
                  curPunc = stream.next();
                  return null;
                }
                if (isBracketChar.test(ch)) {
                  curPunc = stream.next();
                  return "bracket";
                }
                // Macros (tick-defines)
                if (ch == '`') {
                  stream.next();
                  if (stream.eatWhile(/[\w\$_]/)) {
                    return "def";
                  } else {
                    return null;
                  }
                }
                // System calls
                if (ch == '$') {
                  stream.next();
                  if (stream.eatWhile(/[\w\$_]/)) {
                    return "meta";
                  } else {
                    return null;
                  }
                }
                // Time literals
                if (ch == '#') {
                  stream.next();
                  stream.eatWhile(/[\d_.]/);
                  return "def";
                }
                // Strings
                if (ch == '"') {
                  stream.next();
                  state.tokenize = tokenString(ch);
                  return state.tokenize(stream, state);
                }
                // Comments
                if (ch == "/") {
                  stream.next();
                  if (stream.eat("*")) {
                    state.tokenize = tokenComment;
                    return tokenComment(stream, state);
                  }
                  if (stream.eat("/")) {
                    stream.skipToEnd();
                    return "comment";
                  }
                  stream.backUp(1);
                }
            
                // Numeric literals
                if (stream.match(realLiteral) ||
                    stream.match(decimalLiteral) ||
                    stream.match(binaryLiteral) ||
                    stream.match(octLiteral) ||
                    stream.match(hexLiteral) ||
                    stream.match(unsignedNumber) ||
                    stream.match(realLiteral)) {
                  return "number";
                }
            
                // Operators
                if (stream.eatWhile(isOperatorChar)) {
                  return "meta";
                }
            
                // Keywords / plain variables
                if (stream.eatWhile(/[\w\$_]/)) {
                  var cur = stream.current();
                  if (keywords[cur]) {
                    if (openClose[cur]) {
                      curPunc = "newblock";
                    }
                    if (statementKeywords[cur]) {
                      curPunc = "newstatement";
                    }
                    curKeyword = cur;
                    return "keyword";
                  }
                  return "variable";
                }
            
                stream.next();
                return null;
              }
            
              function tokenString(quote) {
                return function(stream, state) {
                  var escaped = false, next, end = false;
                  while ((next = stream.next()) != null) {
                    if (next == quote && !escaped) {end = true; break;}
                    escaped = !escaped && next == "\\";
                  }
                  if (end || !(escaped || multiLineStrings))
                    state.tokenize = tokenBase;
                  return "string";
                };
              }
            
              function tokenComment(stream, state) {
                var maybeEnd = false, ch;
                while (ch = stream.next()) {
                  if (ch == "/" && maybeEnd) {
                    state.tokenize = tokenBase;
                    break;
                  }
                  maybeEnd = (ch == "*");
                }
                return "comment";
              }
            
              function Context(indented, column, type, align, prev) {
                this.indented = indented;
                this.column = column;
                this.type = type;
                this.align = align;
                this.prev = prev;
              }
              function pushContext(state, col, type) {
                var indent = state.indented;
                var c = new Context(indent, col, type, null, state.context);
                return state.context = c;
              }
              function popContext(state) {
                var t = state.context.type;
                if (t == ")" || t == "]" || t == "}") {
                  state.indented = state.context.indented;
                }
                return state.context = state.context.prev;
              }
            
              function isClosing(text, contextClosing) {
                if (text == contextClosing) {
                  return true;
                } else {
                  // contextClosing may be mulitple keywords separated by ;
                  var closingKeywords = contextClosing.split(";");
                  for (var i in closingKeywords) {
                    if (text == closingKeywords[i]) {
                      return true;
                    }
                  }
                  return false;
                }
              }
            
              function buildElectricInputRegEx() {
                // Reindentation should occur on any bracket char: {}()[]
                // or on a match of any of the block closing keywords, at
                // the end of a line
                var allClosings = [];
                for (var i in openClose) {
                  if (openClose[i]) {
                    var closings = openClose[i].split(";");
                    for (var j in closings) {
                      allClosings.push(closings[j]);
                    }
                  }
                }
                var re = new RegExp("[{}()\\[\\]]|(" + allClosings.join("|") + ")$");
                return re;
              }
            
              // Interface
              return {
            
                // Regex to force current line to reindent
                electricInput: buildElectricInputRegEx(),
            
                startState: function(basecolumn) {
                  var state = {
                    tokenize: null,
                    context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
                    indented: 0,
                    startOfLine: true
                  };
                  if (hooks.startState) hooks.startState(state);
                  return state;
                },
            
                token: function(stream, state) {
                  var ctx = state.context;
                  if (stream.sol()) {
                    if (ctx.align == null) ctx.align = false;
                    state.indented = stream.indentation();
                    state.startOfLine = true;
                  }
                  if (hooks.token) hooks.token(stream, state);
                  if (stream.eatSpace()) return null;
                  curPunc = null;
                  curKeyword = null;
                  var style = (state.tokenize || tokenBase)(stream, state);
                  if (style == "comment" || style == "meta" || style == "variable") return style;
                  if (ctx.align == null) ctx.align = true;
            
                  if (curPunc == ctx.type) {
                    popContext(state);
                  } else if ((curPunc == ";" && ctx.type == "statement") ||
                           (ctx.type && isClosing(curKeyword, ctx.type))) {
                    ctx = popContext(state);
                    while (ctx && ctx.type == "statement") ctx = popContext(state);
                  } else if (curPunc == "{") {
                    pushContext(state, stream.column(), "}");
                  } else if (curPunc == "[") {
                    pushContext(state, stream.column(), "]");
                  } else if (curPunc == "(") {
                    pushContext(state, stream.column(), ")");
                  } else if (ctx && ctx.type == "endcase" && curPunc == ":") {
                    pushContext(state, stream.column(), "statement");
                  } else if (curPunc == "newstatement") {
                    pushContext(state, stream.column(), "statement");
                  } else if (curPunc == "newblock") {
                    if (curKeyword == "function" && ctx && (ctx.type == "statement" || ctx.type == "endgroup")) {
                      // The 'function' keyword can appear in some other contexts where it actually does not
                      // indicate a function (import/export DPI and covergroup definitions).
                      // Do nothing in this case
                    } else if (curKeyword == "task" && ctx && ctx.type == "statement") {
                      // Same thing for task
                    } else {
                      var close = openClose[curKeyword];
                      pushContext(state, stream.column(), close);
                    }
                  }
            
                  state.startOfLine = false;
                  return style;
                },
            
                indent: function(state, textAfter) {
                  if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
                  if (hooks.indent) {
                    var fromHook = hooks.indent(state);
                    if (fromHook >= 0) return fromHook;
                  }
                  var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
                  if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
                  var closing = false;
                  var possibleClosing = textAfter.match(closingBracketOrWord);
                  if (possibleClosing)
                    closing = isClosing(possibleClosing[0], ctx.type);
                  if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
                  else if (closingBracket.test(ctx.type) && ctx.align && !dontAlignCalls) return ctx.column + (closing ? 0 : 1);
                  else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
                  else return ctx.indented + (closing ? 0 : indentUnit);
                },
            
                blockCommentStart: "/*",
                blockCommentEnd: "*/",
                lineComment: "//"
              };
            });
            
              CodeMirror.defineMIME("text/x-verilog", {
                name: "verilog"
              });
            
              CodeMirror.defineMIME("text/x-systemverilog", {
                name: "verilog"
              });
            
              // TLVVerilog mode
            
              var tlvchScopePrefixes = {
                ">": "property", "->": "property", "-": "hr", "|": "link", "?$": "qualifier", "?*": "qualifier",
                "@-": "variable-3", "@": "variable-3", "?": "qualifier"
              };
            
              function tlvGenIndent(stream, state) {
                var tlvindentUnit = 2;
                var rtnIndent = -1, indentUnitRq = 0, curIndent = stream.indentation();
                switch (state.tlvCurCtlFlowChar) {
                case "\\":
                  curIndent = 0;
                  break;
                case "|":
                  if (state.tlvPrevPrevCtlFlowChar == "@") {
                    indentUnitRq = -2; //-2 new pipe rq after cur pipe
                    break;
                  }
                  if (tlvchScopePrefixes[state.tlvPrevCtlFlowChar])
                    indentUnitRq = 1; // +1 new scope
                  break;
                case "M":  // m4
                  if (state.tlvPrevPrevCtlFlowChar == "@") {
                    indentUnitRq = -2; //-2 new inst rq after  pipe
                    break;
                  }
                  if (tlvchScopePrefixes[state.tlvPrevCtlFlowChar])
                    indentUnitRq = 1; // +1 new scope
                  break;
                case "@":
                  if (state.tlvPrevCtlFlowChar == "S")
                    indentUnitRq = -1; // new pipe stage after stmts
                  if (state.tlvPrevCtlFlowChar == "|")
                    indentUnitRq = 1; // 1st pipe stage
                  break;
                case "S":
                  if (state.tlvPrevCtlFlowChar == "@")
                    indentUnitRq = 1; // flow in pipe stage
                  if (tlvchScopePrefixes[state.tlvPrevCtlFlowChar])
                    indentUnitRq = 1; // +1 new scope
                  break;
                }
                var statementIndentUnit = tlvindentUnit;
                rtnIndent = curIndent + (indentUnitRq*statementIndentUnit);
                return rtnIndent >= 0 ? rtnIndent : curIndent;
              }
            
              CodeMirror.defineMIME("text/x-tlv", {
                name: "verilog",
                hooks: {
                  "\\": function(stream, state) {
                    var vxIndent = 0, style = false;
                    var curPunc  = stream.string;
                    if ((stream.sol()) && ((/\\SV/.test(stream.string)) || (/\\TLV/.test(stream.string)))) {
                      curPunc = (/\\TLV_version/.test(stream.string))
                        ? "\\TLV_version" : stream.string;
                      stream.skipToEnd();
                      if (curPunc == "\\SV" && state.vxCodeActive) {state.vxCodeActive = false;};
                      if ((/\\TLV/.test(curPunc) && !state.vxCodeActive)
                        || (curPunc=="\\TLV_version" && state.vxCodeActive)) {state.vxCodeActive = true;};
                      style = "keyword";
                      state.tlvCurCtlFlowChar  = state.tlvPrevPrevCtlFlowChar
                        = state.tlvPrevCtlFlowChar = "";
                      if (state.vxCodeActive == true) {
                        state.tlvCurCtlFlowChar  = "\\";
                        vxIndent = tlvGenIndent(stream, state);
                      }
                      state.vxIndentRq = vxIndent;
                    }
                    return style;
                  },
                  tokenBase: function(stream, state) {
                    var vxIndent = 0, style = false;
                    var tlvisOperatorChar = /[\[\]=:]/;
                    var tlvkpScopePrefixs = {
                      "**":"variable-2", "*":"variable-2", "$$":"variable", "$":"variable",
                      "^^":"attribute", "^":"attribute"};
                    var ch = stream.peek();
                    var vxCurCtlFlowCharValueAtStart = state.tlvCurCtlFlowChar;
                    if (state.vxCodeActive == true) {
                      if (/[\[\]{}\(\);\:]/.test(ch)) {
                        // bypass nesting and 1 char punc
                        style = "meta";
                        stream.next();
                      } else if (ch == "/") {
                        stream.next();
                        if (stream.eat("/")) {
                          stream.skipToEnd();
                          style = "comment";
                          state.tlvCurCtlFlowChar = "S";
                        } else {
                          stream.backUp(1);
                        }
                      } else if (ch == "@") {
                        // pipeline stage
                        style = tlvchScopePrefixes[ch];
                        state.tlvCurCtlFlowChar = "@";
                        stream.next();
                        stream.eatWhile(/[\w\$_]/);
                      } else if (stream.match(/\b[mM]4+/, true)) { // match: function(pattern, consume, caseInsensitive)
                        // m4 pre proc
                        stream.skipTo("(");
                        style = "def";
                        state.tlvCurCtlFlowChar = "M";
                      } else if (ch == "!" && stream.sol()) {
                        // v stmt in tlv region
                        // state.tlvCurCtlFlowChar  = "S";
                        style = "comment";
                        stream.next();
                      } else if (tlvisOperatorChar.test(ch)) {
                        // operators
                        stream.eatWhile(tlvisOperatorChar);
                        style = "operator";
                      } else if (ch == "#") {
                        // phy hier
                        state.tlvCurCtlFlowChar  = (state.tlvCurCtlFlowChar == "")
                          ? ch : state.tlvCurCtlFlowChar;
                        stream.next();
                        stream.eatWhile(/[+-]\d/);
                        style = "tag";
                      } else if (tlvkpScopePrefixs.propertyIsEnumerable(ch)) {
                        // special TLV operators
                        style = tlvkpScopePrefixs[ch];
                        state.tlvCurCtlFlowChar = state.tlvCurCtlFlowChar == "" ? "S" : state.tlvCurCtlFlowChar;  // stmt
                        stream.next();
                        stream.match(/[a-zA-Z_0-9]+/);
                      } else if (style = tlvchScopePrefixes[ch] || false) {
                        // special TLV operators
                        state.tlvCurCtlFlowChar = state.tlvCurCtlFlowChar == "" ? ch : state.tlvCurCtlFlowChar;
                        stream.next();
                        stream.match(/[a-zA-Z_0-9]+/);
                      }
                      if (state.tlvCurCtlFlowChar != vxCurCtlFlowCharValueAtStart) { // flow change
                        vxIndent = tlvGenIndent(stream, state);
                        state.vxIndentRq = vxIndent;
                      }
                    }
                    return style;
                  },
                  token: function(stream, state) {
                    if (state.vxCodeActive == true && stream.sol() && state.tlvCurCtlFlowChar != "") {
                      state.tlvPrevPrevCtlFlowChar = state.tlvPrevCtlFlowChar;
                      state.tlvPrevCtlFlowChar = state.tlvCurCtlFlowChar;
                      state.tlvCurCtlFlowChar = "";
                    }
                  },
                  indent: function(state) {
                    return (state.vxCodeActive == true) ? state.vxIndentRq : -1;
                  },
                  startState: function(state) {
                    state.tlvCurCtlFlowChar = "";
                    state.tlvPrevCtlFlowChar = "";
                    state.tlvPrevPrevCtlFlowChar = "";
                    state.vxCodeActive = true;
                    state.vxIndentRq = 0;
                  }
                }
              });
            });
            
        • xml
          • index.html
            <!doctype html>
            
            <title>CodeMirror: XML mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="xml.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">XML</a>
              </ul>
            </div>
            
            <article>
            <h2>XML mode</h2>
            <form><textarea id="code" name="code">
            &lt;html style="color: green"&gt;
              &lt;!-- this is a comment --&gt;
              &lt;head&gt;
                &lt;title&gt;HTML Example&lt;/title&gt;
              &lt;/head&gt;
              &lt;body&gt;
                The indentation tries to be &lt;em&gt;somewhat &amp;quot;do what
                I mean&amp;quot;&lt;/em&gt;... but might not match your style.
              &lt;/body&gt;
            &lt;/html&gt;
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    mode: "text/html",
                    lineNumbers: true
                  });
                </script>
                <p>The XML mode supports two configuration parameters:</p>
                <dl>
                  <dt><code>htmlMode (boolean)</code></dt>
                  <dd>This switches the mode to parse HTML instead of XML. This
                  means attributes do not have to be quoted, and some elements
                  (such as <code>br</code>) do not require a closing tag.</dd>
                  <dt><code>alignCDATA (boolean)</code></dt>
                  <dd>Setting this to true will force the opening tag of CDATA
                  blocks to not be indented.</dd>
                </dl>
            
                <p><strong>MIME types defined:</strong> <code>application/xml</code>, <code>text/html</code>.</p>
              </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function() {
              var mode = CodeMirror.getMode({indentUnit: 2}, "xml"), mname = "xml";
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), mname); }
            
              MT("matching",
                 "[tag&bracket <][tag top][tag&bracket >]",
                 "  text",
                 "  [tag&bracket <][tag inner][tag&bracket />]",
                 "[tag&bracket </][tag top][tag&bracket >]");
            
              MT("nonmatching",
                 "[tag&bracket <][tag top][tag&bracket >]",
                 "  [tag&bracket <][tag inner][tag&bracket />]",
                 "  [tag&bracket </][tag&error tip][tag&bracket&error >]");
            
              MT("doctype",
                 "[meta <!doctype foobar>]",
                 "[tag&bracket <][tag top][tag&bracket />]");
            
              MT("cdata",
                 "[tag&bracket <][tag top][tag&bracket >]",
                 "  [atom <![CDATA[foo]",
                 "[atom barbazguh]]]]>]",
                 "[tag&bracket </][tag top][tag&bracket >]");
            
              // HTML tests
              mode = CodeMirror.getMode({indentUnit: 2}, "text/html");
            
              MT("selfclose",
                 "[tag&bracket <][tag html][tag&bracket >]",
                 "  [tag&bracket <][tag link] [attribute rel]=[string stylesheet] [attribute href]=[string \"/foobar\"][tag&bracket >]",
                 "[tag&bracket </][tag html][tag&bracket >]");
            
              MT("list",
                 "[tag&bracket <][tag ol][tag&bracket >]",
                 "  [tag&bracket <][tag li][tag&bracket >]one",
                 "  [tag&bracket <][tag li][tag&bracket >]two",
                 "[tag&bracket </][tag ol][tag&bracket >]");
            
              MT("valueless",
                 "[tag&bracket <][tag input] [attribute type]=[string checkbox] [attribute checked][tag&bracket />]");
            
              MT("pThenArticle",
                 "[tag&bracket <][tag p][tag&bracket >]",
                 "  foo",
                 "[tag&bracket <][tag article][tag&bracket >]bar");
            
            })();
            
          • xml.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("xml", function(config, parserConfig) {
              var indentUnit = config.indentUnit;
              var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
              var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;
              if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;
            
              var Kludges = parserConfig.htmlMode ? {
                autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
                                  'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
                                  'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
                                  'track': true, 'wbr': true, 'menuitem': true},
                implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
                                   'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
                                   'th': true, 'tr': true},
                contextGrabbers: {
                  'dd': {'dd': true, 'dt': true},
                  'dt': {'dd': true, 'dt': true},
                  'li': {'li': true},
                  'option': {'option': true, 'optgroup': true},
                  'optgroup': {'optgroup': true},
                  'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
                        'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
                        'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
                        'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
                        'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
                  'rp': {'rp': true, 'rt': true},
                  'rt': {'rp': true, 'rt': true},
                  'tbody': {'tbody': true, 'tfoot': true},
                  'td': {'td': true, 'th': true},
                  'tfoot': {'tbody': true},
                  'th': {'td': true, 'th': true},
                  'thead': {'tbody': true, 'tfoot': true},
                  'tr': {'tr': true}
                },
                doNotIndent: {"pre": true},
                allowUnquoted: true,
                allowMissing: true,
                caseFold: true
              } : {
                autoSelfClosers: {},
                implicitlyClosed: {},
                contextGrabbers: {},
                doNotIndent: {},
                allowUnquoted: false,
                allowMissing: false,
                caseFold: false
              };
              var alignCDATA = parserConfig.alignCDATA;
            
              // Return variables for tokenizers
              var type, setStyle;
            
              function inText(stream, state) {
                function chain(parser) {
                  state.tokenize = parser;
                  return parser(stream, state);
                }
            
                var ch = stream.next();
                if (ch == "<") {
                  if (stream.eat("!")) {
                    if (stream.eat("[")) {
                      if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
                      else return null;
                    } else if (stream.match("--")) {
                      return chain(inBlock("comment", "-->"));
                    } else if (stream.match("DOCTYPE", true, true)) {
                      stream.eatWhile(/[\w\._\-]/);
                      return chain(doctype(1));
                    } else {
                      return null;
                    }
                  } else if (stream.eat("?")) {
                    stream.eatWhile(/[\w\._\-]/);
                    state.tokenize = inBlock("meta", "?>");
                    return "meta";
                  } else {
                    type = stream.eat("/") ? "closeTag" : "openTag";
                    state.tokenize = inTag;
                    return "tag bracket";
                  }
                } else if (ch == "&") {
                  var ok;
                  if (stream.eat("#")) {
                    if (stream.eat("x")) {
                      ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
                    } else {
                      ok = stream.eatWhile(/[\d]/) && stream.eat(";");
                    }
                  } else {
                    ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
                  }
                  return ok ? "atom" : "error";
                } else {
                  stream.eatWhile(/[^&<]/);
                  return null;
                }
              }
            
              function inTag(stream, state) {
                var ch = stream.next();
                if (ch == ">" || (ch == "/" && stream.eat(">"))) {
                  state.tokenize = inText;
                  type = ch == ">" ? "endTag" : "selfcloseTag";
                  return "tag bracket";
                } else if (ch == "=") {
                  type = "equals";
                  return null;
                } else if (ch == "<") {
                  state.tokenize = inText;
                  state.state = baseState;
                  state.tagName = state.tagStart = null;
                  var next = state.tokenize(stream, state);
                  return next ? next + " tag error" : "tag error";
                } else if (/[\'\"]/.test(ch)) {
                  state.tokenize = inAttribute(ch);
                  state.stringStartCol = stream.column();
                  return state.tokenize(stream, state);
                } else {
                  stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
                  return "word";
                }
              }
            
              function inAttribute(quote) {
                var closure = function(stream, state) {
                  while (!stream.eol()) {
                    if (stream.next() == quote) {
                      state.tokenize = inTag;
                      break;
                    }
                  }
                  return "string";
                };
                closure.isInAttribute = true;
                return closure;
              }
            
              function inBlock(style, terminator) {
                return function(stream, state) {
                  while (!stream.eol()) {
                    if (stream.match(terminator)) {
                      state.tokenize = inText;
                      break;
                    }
                    stream.next();
                  }
                  return style;
                };
              }
              function doctype(depth) {
                return function(stream, state) {
                  var ch;
                  while ((ch = stream.next()) != null) {
                    if (ch == "<") {
                      state.tokenize = doctype(depth + 1);
                      return state.tokenize(stream, state);
                    } else if (ch == ">") {
                      if (depth == 1) {
                        state.tokenize = inText;
                        break;
                      } else {
                        state.tokenize = doctype(depth - 1);
                        return state.tokenize(stream, state);
                      }
                    }
                  }
                  return "meta";
                };
              }
            
              function Context(state, tagName, startOfLine) {
                this.prev = state.context;
                this.tagName = tagName;
                this.indent = state.indented;
                this.startOfLine = startOfLine;
                if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
                  this.noIndent = true;
              }
              function popContext(state) {
                if (state.context) state.context = state.context.prev;
              }
              function maybePopContext(state, nextTagName) {
                var parentTagName;
                while (true) {
                  if (!state.context) {
                    return;
                  }
                  parentTagName = state.context.tagName;
                  if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
                      !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
                    return;
                  }
                  popContext(state);
                }
              }
            
              function baseState(type, stream, state) {
                if (type == "openTag") {
                  state.tagStart = stream.column();
                  return tagNameState;
                } else if (type == "closeTag") {
                  return closeTagNameState;
                } else {
                  return baseState;
                }
              }
              function tagNameState(type, stream, state) {
                if (type == "word") {
                  state.tagName = stream.current();
                  setStyle = "tag";
                  return attrState;
                } else {
                  setStyle = "error";
                  return tagNameState;
                }
              }
              function closeTagNameState(type, stream, state) {
                if (type == "word") {
                  var tagName = stream.current();
                  if (state.context && state.context.tagName != tagName &&
                      Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
                    popContext(state);
                  if (state.context && state.context.tagName == tagName) {
                    setStyle = "tag";
                    return closeState;
                  } else {
                    setStyle = "tag error";
                    return closeStateErr;
                  }
                } else {
                  setStyle = "error";
                  return closeStateErr;
                }
              }
            
              function closeState(type, _stream, state) {
                if (type != "endTag") {
                  setStyle = "error";
                  return closeState;
                }
                popContext(state);
                return baseState;
              }
              function closeStateErr(type, stream, state) {
                setStyle = "error";
                return closeState(type, stream, state);
              }
            
              function attrState(type, _stream, state) {
                if (type == "word") {
                  setStyle = "attribute";
                  return attrEqState;
                } else if (type == "endTag" || type == "selfcloseTag") {
                  var tagName = state.tagName, tagStart = state.tagStart;
                  state.tagName = state.tagStart = null;
                  if (type == "selfcloseTag" ||
                      Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
                    maybePopContext(state, tagName);
                  } else {
                    maybePopContext(state, tagName);
                    state.context = new Context(state, tagName, tagStart == state.indented);
                  }
                  return baseState;
                }
                setStyle = "error";
                return attrState;
              }
              function attrEqState(type, stream, state) {
                if (type == "equals") return attrValueState;
                if (!Kludges.allowMissing) setStyle = "error";
                return attrState(type, stream, state);
              }
              function attrValueState(type, stream, state) {
                if (type == "string") return attrContinuedState;
                if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
                setStyle = "error";
                return attrState(type, stream, state);
              }
              function attrContinuedState(type, stream, state) {
                if (type == "string") return attrContinuedState;
                return attrState(type, stream, state);
              }
            
              return {
                startState: function() {
                  return {tokenize: inText,
                          state: baseState,
                          indented: 0,
                          tagName: null, tagStart: null,
                          context: null};
                },
            
                token: function(stream, state) {
                  if (!state.tagName && stream.sol())
                    state.indented = stream.indentation();
            
                  if (stream.eatSpace()) return null;
                  type = null;
                  var style = state.tokenize(stream, state);
                  if ((style || type) && style != "comment") {
                    setStyle = null;
                    state.state = state.state(type || style, stream, state);
                    if (setStyle)
                      style = setStyle == "error" ? style + " error" : setStyle;
                  }
                  return style;
                },
            
                indent: function(state, textAfter, fullLine) {
                  var context = state.context;
                  // Indent multi-line strings (e.g. css).
                  if (state.tokenize.isInAttribute) {
                    if (state.tagStart == state.indented)
                      return state.stringStartCol + 1;
                    else
                      return state.indented + indentUnit;
                  }
                  if (context && context.noIndent) return CodeMirror.Pass;
                  if (state.tokenize != inTag && state.tokenize != inText)
                    return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
                  // Indent the starts of attribute names.
                  if (state.tagName) {
                    if (multilineTagIndentPastTag)
                      return state.tagStart + state.tagName.length + 2;
                    else
                      return state.tagStart + indentUnit * multilineTagIndentFactor;
                  }
                  if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
                  var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
                  if (tagAfter && tagAfter[1]) { // Closing tag spotted
                    while (context) {
                      if (context.tagName == tagAfter[2]) {
                        context = context.prev;
                        break;
                      } else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {
                        context = context.prev;
                      } else {
                        break;
                      }
                    }
                  } else if (tagAfter) { // Opening tag spotted
                    while (context) {
                      var grabbers = Kludges.contextGrabbers[context.tagName];
                      if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
                        context = context.prev;
                      else
                        break;
                    }
                  }
                  while (context && !context.startOfLine)
                    context = context.prev;
                  if (context) return context.indent + indentUnit;
                  else return 0;
                },
            
                electricInput: /<\/[\s\w:]+>$/,
                blockCommentStart: "<!--",
                blockCommentEnd: "-->",
            
                configuration: parserConfig.htmlMode ? "html" : "xml",
                helperType: parserConfig.htmlMode ? "html" : "xml"
              };
            });
            
            CodeMirror.defineMIME("text/xml", "xml");
            CodeMirror.defineMIME("application/xml", "xml");
            if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
              CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
            
            });
            
        • xquery
          • index.html
            <!doctype html>
            
            <title>CodeMirror: XQuery mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <link rel="stylesheet" href="../../theme/xq-dark.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="xquery.js"></script>
            <style type="text/css">
            	.CodeMirror {
            	  border-top: 1px solid black; border-bottom: 1px solid black;
            	  height:400px;
            	}
                </style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">XQuery</a>
              </ul>
            </div>
            
            <article>
            <h2>XQuery mode</h2>
             
             
            <div class="cm-s-default"> 
            	<textarea id="code" name="code"> 
            xquery version &quot;1.0-ml&quot;;
            (: this is
             : a 
               "comment" :)
            let $let := &lt;x attr=&quot;value&quot;&gt;&quot;test&quot;&lt;func&gt;function() $var {function()} {$var}&lt;/func&gt;&lt;/x&gt;
            let $joe:=1
            return element element {
            	attribute attribute { 1 },
            	element test { &#39;a&#39; }, 
            	attribute foo { &quot;bar&quot; },
            	fn:doc()[ foo/@bar eq $let ],
            	//x }    
             
            (: a more 'evil' test :)
            (: Modified Blakeley example (: with nested comment :) ... :)
            declare private function local:declare() {()};
            declare private function local:private() {()};
            declare private function local:function() {()};
            declare private function local:local() {()};
            let $let := &lt;let&gt;let $let := &quot;let&quot;&lt;/let&gt;
            return element element {
            	attribute attribute { try { xdmp:version() } catch($e) { xdmp:log($e) } },
            	attribute fn:doc { &quot;bar&quot; castable as xs:string },
            	element text { text { &quot;text&quot; } },
            	fn:doc()[ child::eq/(@bar | attribute::attribute) eq $let ],
            	//fn:doc
            }
            
            
            
            xquery version &quot;1.0-ml&quot;;
            
            (: Copyright 2006-2010 Mark Logic Corporation. :)
            
            (:
             : Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
             : you may not use this file except in compliance with the License.
             : You may obtain a copy of the License at
             :
             :     http://www.apache.org/licenses/LICENSE-2.0
             :
             : Unless required by applicable law or agreed to in writing, software
             : distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             : See the License for the specific language governing permissions and
             : limitations under the License.
             :)
            
            module namespace json = &quot;http://marklogic.com/json&quot;;
            declare default function namespace &quot;http://www.w3.org/2005/xpath-functions&quot;;
            
            (: Need to backslash escape any double quotes, backslashes, and newlines :)
            declare function json:escape($s as xs:string) as xs:string {
              let $s := replace($s, &quot;\\&quot;, &quot;\\\\&quot;)
              let $s := replace($s, &quot;&quot;&quot;&quot;, &quot;\\&quot;&quot;&quot;)
              let $s := replace($s, codepoints-to-string((13, 10)), &quot;\\n&quot;)
              let $s := replace($s, codepoints-to-string(13), &quot;\\n&quot;)
              let $s := replace($s, codepoints-to-string(10), &quot;\\n&quot;)
              return $s
            };
            
            declare function json:atomize($x as element()) as xs:string {
              if (count($x/node()) = 0) then 'null'
              else if ($x/@type = &quot;number&quot;) then
                let $castable := $x castable as xs:float or
                                 $x castable as xs:double or
                                 $x castable as xs:decimal
                return
                if ($castable) then xs:string($x)
                else error(concat(&quot;Not a number: &quot;, xdmp:describe($x)))
              else if ($x/@type = &quot;boolean&quot;) then
                let $castable := $x castable as xs:boolean
                return
                if ($castable) then xs:string(xs:boolean($x))
                else error(concat(&quot;Not a boolean: &quot;, xdmp:describe($x)))
              else concat('&quot;', json:escape($x), '&quot;')
            };
            
            (: Print the thing that comes after the colon :)
            declare function json:print-value($x as element()) as xs:string {
              if (count($x/*) = 0) then
                json:atomize($x)
              else if ($x/@quote = &quot;true&quot;) then
                concat('&quot;', json:escape(xdmp:quote($x/node())), '&quot;')
              else
                string-join(('{',
                  string-join(for $i in $x/* return json:print-name-value($i), &quot;,&quot;),
                '}'), &quot;&quot;)
            };
            
            (: Print the name and value both :)
            declare function json:print-name-value($x as element()) as xs:string? {
              let $name := name($x)
              let $first-in-array :=
                count($x/preceding-sibling::*[name(.) = $name]) = 0 and
                (count($x/following-sibling::*[name(.) = $name]) &gt; 0 or $x/@array = &quot;true&quot;)
              let $later-in-array := count($x/preceding-sibling::*[name(.) = $name]) &gt; 0
              return
            
              if ($later-in-array) then
                ()  (: I was handled previously :)
              else if ($first-in-array) then
                string-join(('&quot;', json:escape($name), '&quot;:[',
                  string-join((for $i in ($x, $x/following-sibling::*[name(.) = $name]) return json:print-value($i)), &quot;,&quot;),
                ']'), &quot;&quot;)
               else
                 string-join(('&quot;', json:escape($name), '&quot;:', json:print-value($x)), &quot;&quot;)
            };
            
            (:~
              Transforms an XML element into a JSON string representation.  See http://json.org.
              &lt;p/&gt;
              Sample usage:
              &lt;pre&gt;
                xquery version &quot;1.0-ml&quot;;
                import module namespace json=&quot;http://marklogic.com/json&quot; at &quot;json.xqy&quot;;
                json:serialize(&amp;lt;foo&amp;gt;&amp;lt;bar&amp;gt;kid&amp;lt;/bar&amp;gt;&amp;lt;/foo&amp;gt;)
              &lt;/pre&gt;
              Sample transformations:
              &lt;pre&gt;
              &amp;lt;e/&amp;gt; becomes {&quot;e&quot;:null}
              &amp;lt;e&amp;gt;text&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;text&quot;}
              &amp;lt;e&amp;gt;quote &quot; escaping&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;quote \&quot; escaping&quot;}
              &amp;lt;e&amp;gt;backslash \ escaping&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;backslash \\ escaping&quot;}
              &amp;lt;e&amp;gt;&amp;lt;a&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;b&amp;gt;text2&amp;lt;/b&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:&quot;text1&quot;,&quot;b&quot;:&quot;text2&quot;}}
              &amp;lt;e&amp;gt;&amp;lt;a&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;a&amp;gt;text2&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:[&quot;text1&quot;,&quot;text2&quot;]}}
              &amp;lt;e&amp;gt;&amp;lt;a array=&quot;true&quot;&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:[&quot;text1&quot;]}}
              &amp;lt;e&amp;gt;&amp;lt;a type=&quot;boolean&quot;&amp;gt;false&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:false}}
              &amp;lt;e&amp;gt;&amp;lt;a type=&quot;number&quot;&amp;gt;123.5&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:123.5}}
              &amp;lt;e quote=&quot;true&quot;&amp;gt;&amp;lt;div attrib=&quot;value&quot;/&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;&amp;lt;div attrib=\&quot;value\&quot;/&amp;gt;&quot;}
              &lt;/pre&gt;
              &lt;p/&gt;
              Namespace URIs are ignored.  Namespace prefixes are included in the JSON name.
              &lt;p/&gt;
              Attributes are ignored, except for the special attribute @array=&quot;true&quot; that
              indicates the JSON serialization should write the node, even if single, as an
              array, and the attribute @type that can be set to &quot;boolean&quot; or &quot;number&quot; to
              dictate the value should be written as that type (unquoted).  There's also
              an @quote attribute that when set to true writes the inner content as text
              rather than as structured JSON, useful for sending some XHTML over the
              wire.
              &lt;p/&gt;
              Text nodes within mixed content are ignored.
            
              @param $x Element node to convert
              @return String holding JSON serialized representation of $x
            
              @author Jason Hunter
              @version 1.0.1
              
              Ported to xquery 1.0-ml; double escaped backslashes in json:escape
            :)
            declare function json:serialize($x as element())  as xs:string {
              string-join(('{', json:print-name-value($x), '}'), &quot;&quot;)
            };
              </textarea> 
            </div> 
             
                <script> 
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true,
                    matchBrackets: true,
                    theme: "xq-dark"
                  });
                </script> 
             
                <p><strong>MIME types defined:</strong> <code>application/xquery</code>.</p> 
             
                <p>Development of the CodeMirror XQuery mode was sponsored by 
                  <a href="http://marklogic.com">MarkLogic</a> and developed by 
                  <a href="https://twitter.com/mbrevoort">Mike Brevoort</a>.
                </p>
             
              </article>
            
          • test.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            // Don't take these too seriously -- the expected results appear to be
            // based on the results of actual runs without any serious manual
            // verification. If a change you made causes them to fail, the test is
            // as likely to wrong as the code.
            
            (function() {
              var mode = CodeMirror.getMode({tabSize: 4}, "xquery");
              function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
            
              MT("eviltest",
                 "[keyword xquery] [keyword version] [variable &quot;1][keyword .][atom 0][keyword -][variable ml&quot;][def&variable ;]      [comment (: this is       : a          \"comment\" :)]",
                 "      [keyword let] [variable $let] [keyword :=] [variable &lt;x] [variable attr][keyword =][variable &quot;value&quot;&gt;&quot;test&quot;&lt;func&gt][def&variable ;function]() [variable $var] {[keyword function]()} {[variable $var]}[variable &lt;][keyword /][variable func&gt;&lt;][keyword /][variable x&gt;]",
                 "      [keyword let] [variable $joe][keyword :=][atom 1]",
                 "      [keyword return] [keyword element] [variable element] {",
                 "          [keyword attribute] [variable attribute] { [atom 1] },",
                 "          [keyword element] [variable test] { [variable &#39;a&#39;] },           [keyword attribute] [variable foo] { [variable &quot;bar&quot;] },",
                 "          [def&variable fn:doc]()[[ [variable foo][keyword /][variable @bar] [keyword eq] [variable $let] ]],",
                 "          [keyword //][variable x] }                 [comment (: a more 'evil' test :)]",
                 "      [comment (: Modified Blakeley example (: with nested comment :) ... :)]",
                 "      [keyword declare] [keyword private] [keyword function] [def&variable local:declare]() {()}[variable ;]",
                 "      [keyword declare] [keyword private] [keyword function] [def&variable local:private]() {()}[variable ;]",
                 "      [keyword declare] [keyword private] [keyword function] [def&variable local:function]() {()}[variable ;]",
                 "      [keyword declare] [keyword private] [keyword function] [def&variable local:local]() {()}[variable ;]",
                 "      [keyword let] [variable $let] [keyword :=] [variable &lt;let&gt;let] [variable $let] [keyword :=] [variable &quot;let&quot;&lt;][keyword /let][variable &gt;]",
                 "      [keyword return] [keyword element] [variable element] {",
                 "          [keyword attribute] [variable attribute] { [keyword try] { [def&variable xdmp:version]() } [keyword catch]([variable $e]) { [def&variable xdmp:log]([variable $e]) } },",
                 "          [keyword attribute] [variable fn:doc] { [variable &quot;bar&quot;] [variable castable] [keyword as] [atom xs:string] },",
                 "          [keyword element] [variable text] { [keyword text] { [variable &quot;text&quot;] } },",
                 "          [def&variable fn:doc]()[[ [qualifier child::][variable eq][keyword /]([variable @bar] [keyword |] [qualifier attribute::][variable attribute]) [keyword eq] [variable $let] ]],",
                 "          [keyword //][variable fn:doc]",
                 "      }");
            
              MT("testEmptySequenceKeyword",
                 "[string \"foo\"] [keyword instance] [keyword of] [keyword empty-sequence]()");
            
              MT("testMultiAttr",
                 "[tag <p ][attribute a1]=[string \"foo\"] [attribute a2]=[string \"bar\"][tag >][variable hello] [variable world][tag </p>]");
            
              MT("test namespaced variable",
                 "[keyword declare] [keyword namespace] [variable e] [keyword =] [string \"http://example.com/ANamespace\"][variable ;declare] [keyword variable] [variable $e:exampleComThisVarIsNotRecognized] [keyword as] [keyword element]([keyword *]) [variable external;]");
            
              MT("test EQName variable",
                 "[keyword declare] [keyword variable] [variable $\"http://www.example.com/ns/my\":var] [keyword :=] [atom 12][variable ;]",
                 "[tag <out>]{[variable $\"http://www.example.com/ns/my\":var]}[tag </out>]");
            
              MT("test EQName function",
                 "[keyword declare] [keyword function] [def&variable \"http://www.example.com/ns/my\":fn] ([variable $a] [keyword as] [atom xs:integer]) [keyword as] [atom xs:integer] {",
                 "   [variable $a] [keyword +] [atom 2]",
                 "}[variable ;]",
                 "[tag <out>]{[def&variable \"http://www.example.com/ns/my\":fn]([atom 12])}[tag </out>]");
            
              MT("test EQName function with single quotes",
                 "[keyword declare] [keyword function] [def&variable 'http://www.example.com/ns/my':fn] ([variable $a] [keyword as] [atom xs:integer]) [keyword as] [atom xs:integer] {",
                 "   [variable $a] [keyword +] [atom 2]",
                 "}[variable ;]",
                 "[tag <out>]{[def&variable 'http://www.example.com/ns/my':fn]([atom 12])}[tag </out>]");
            
              MT("testProcessingInstructions",
                 "[def&variable data]([comment&meta <?target content?>]) [keyword instance] [keyword of] [atom xs:string]");
            
              MT("testQuoteEscapeDouble",
                 "[keyword let] [variable $rootfolder] [keyword :=] [string \"c:\\builds\\winnt\\HEAD\\qa\\scripts\\\"]",
                 "[keyword let] [variable $keysfolder] [keyword :=] [def&variable concat]([variable $rootfolder], [string \"keys\\\"])");
            })();
            
          • xquery.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("xquery", function() {
            
              // The keywords object is set to the result of this self executing
              // function. Each keyword is a property of the keywords object whose
              // value is {type: atype, style: astyle}
              var keywords = function(){
                // conveinence functions used to build keywords object
                function kw(type) {return {type: type, style: "keyword"};}
                var A = kw("keyword a")
                  , B = kw("keyword b")
                  , C = kw("keyword c")
                  , operator = kw("operator")
                  , atom = {type: "atom", style: "atom"}
                  , punctuation = {type: "punctuation", style: null}
                  , qualifier = {type: "axis_specifier", style: "qualifier"};
            
                // kwObj is what is return from this function at the end
                var kwObj = {
                  'if': A, 'switch': A, 'while': A, 'for': A,
                  'else': B, 'then': B, 'try': B, 'finally': B, 'catch': B,
                  'element': C, 'attribute': C, 'let': C, 'implements': C, 'import': C, 'module': C, 'namespace': C,
                  'return': C, 'super': C, 'this': C, 'throws': C, 'where': C, 'private': C,
                  ',': punctuation,
                  'null': atom, 'fn:false()': atom, 'fn:true()': atom
                };
            
                // a list of 'basic' keywords. For each add a property to kwObj with the value of
                // {type: basic[i], style: "keyword"} e.g. 'after' --> {type: "after", style: "keyword"}
                var basic = ['after','ancestor','ancestor-or-self','and','as','ascending','assert','attribute','before',
                'by','case','cast','child','comment','declare','default','define','descendant','descendant-or-self',
                'descending','document','document-node','element','else','eq','every','except','external','following',
                'following-sibling','follows','for','function','if','import','in','instance','intersect','item',
                'let','module','namespace','node','node','of','only','or','order','parent','precedes','preceding',
                'preceding-sibling','processing-instruction','ref','return','returns','satisfies','schema','schema-element',
                'self','some','sortby','stable','text','then','to','treat','typeswitch','union','variable','version','where',
                'xquery', 'empty-sequence'];
                for(var i=0, l=basic.length; i < l; i++) { kwObj[basic[i]] = kw(basic[i]);};
            
                // a list of types. For each add a property to kwObj with the value of
                // {type: "atom", style: "atom"}
                var types = ['xs:string', 'xs:float', 'xs:decimal', 'xs:double', 'xs:integer', 'xs:boolean', 'xs:date', 'xs:dateTime',
                'xs:time', 'xs:duration', 'xs:dayTimeDuration', 'xs:time', 'xs:yearMonthDuration', 'numeric', 'xs:hexBinary',
                'xs:base64Binary', 'xs:anyURI', 'xs:QName', 'xs:byte','xs:boolean','xs:anyURI','xf:yearMonthDuration'];
                for(var i=0, l=types.length; i < l; i++) { kwObj[types[i]] = atom;};
            
                // each operator will add a property to kwObj with value of {type: "operator", style: "keyword"}
                var operators = ['eq', 'ne', 'lt', 'le', 'gt', 'ge', ':=', '=', '>', '>=', '<', '<=', '.', '|', '?', 'and', 'or', 'div', 'idiv', 'mod', '*', '/', '+', '-'];
                for(var i=0, l=operators.length; i < l; i++) { kwObj[operators[i]] = operator;};
            
                // each axis_specifiers will add a property to kwObj with value of {type: "axis_specifier", style: "qualifier"}
                var axis_specifiers = ["self::", "attribute::", "child::", "descendant::", "descendant-or-self::", "parent::",
                "ancestor::", "ancestor-or-self::", "following::", "preceding::", "following-sibling::", "preceding-sibling::"];
                for(var i=0, l=axis_specifiers.length; i < l; i++) { kwObj[axis_specifiers[i]] = qualifier; };
            
                return kwObj;
              }();
            
              function chain(stream, state, f) {
                state.tokenize = f;
                return f(stream, state);
              }
            
              // the primary mode tokenizer
              function tokenBase(stream, state) {
                var ch = stream.next(),
                    mightBeFunction = false,
                    isEQName = isEQNameAhead(stream);
            
                // an XML tag (if not in some sub, chained tokenizer)
                if (ch == "<") {
                  if(stream.match("!--", true))
                    return chain(stream, state, tokenXMLComment);
            
                  if(stream.match("![CDATA", false)) {
                    state.tokenize = tokenCDATA;
                    return "tag";
                  }
            
                  if(stream.match("?", false)) {
                    return chain(stream, state, tokenPreProcessing);
                  }
            
                  var isclose = stream.eat("/");
                  stream.eatSpace();
                  var tagName = "", c;
                  while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
            
                  return chain(stream, state, tokenTag(tagName, isclose));
                }
                // start code block
                else if(ch == "{") {
                  pushStateStack(state,{ type: "codeblock"});
                  return null;
                }
                // end code block
                else if(ch == "}") {
                  popStateStack(state);
                  return null;
                }
                // if we're in an XML block
                else if(isInXmlBlock(state)) {
                  if(ch == ">")
                    return "tag";
                  else if(ch == "/" && stream.eat(">")) {
                    popStateStack(state);
                    return "tag";
                  }
                  else
                    return "variable";
                }
                // if a number
                else if (/\d/.test(ch)) {
                  stream.match(/^\d*(?:\.\d*)?(?:E[+\-]?\d+)?/);
                  return "atom";
                }
                // comment start
                else if (ch === "(" && stream.eat(":")) {
                  pushStateStack(state, { type: "comment"});
                  return chain(stream, state, tokenComment);
                }
                // quoted string
                else if (  !isEQName && (ch === '"' || ch === "'"))
                  return chain(stream, state, tokenString(ch));
                // variable
                else if(ch === "$") {
                  return chain(stream, state, tokenVariable);
                }
                // assignment
                else if(ch ===":" && stream.eat("=")) {
                  return "keyword";
                }
                // open paren
                else if(ch === "(") {
                  pushStateStack(state, { type: "paren"});
                  return null;
                }
                // close paren
                else if(ch === ")") {
                  popStateStack(state);
                  return null;
                }
                // open paren
                else if(ch === "[") {
                  pushStateStack(state, { type: "bracket"});
                  return null;
                }
                // close paren
                else if(ch === "]") {
                  popStateStack(state);
                  return null;
                }
                else {
                  var known = keywords.propertyIsEnumerable(ch) && keywords[ch];
            
                  // if there's a EQName ahead, consume the rest of the string portion, it's likely a function
                  if(isEQName && ch === '\"') while(stream.next() !== '"'){}
                  if(isEQName && ch === '\'') while(stream.next() !== '\''){}
            
                  // gobble up a word if the character is not known
                  if(!known) stream.eatWhile(/[\w\$_-]/);
            
                  // gobble a colon in the case that is a lib func type call fn:doc
                  var foundColon = stream.eat(":");
            
                  // if there's not a second colon, gobble another word. Otherwise, it's probably an axis specifier
                  // which should get matched as a keyword
                  if(!stream.eat(":") && foundColon) {
                    stream.eatWhile(/[\w\$_-]/);
                  }
                  // if the next non whitespace character is an open paren, this is probably a function (if not a keyword of other sort)
                  if(stream.match(/^[ \t]*\(/, false)) {
                    mightBeFunction = true;
                  }
                  // is the word a keyword?
                  var word = stream.current();
                  known = keywords.propertyIsEnumerable(word) && keywords[word];
            
                  // if we think it's a function call but not yet known,
                  // set style to variable for now for lack of something better
                  if(mightBeFunction && !known) known = {type: "function_call", style: "variable def"};
            
                  // if the previous word was element, attribute, axis specifier, this word should be the name of that
                  if(isInXmlConstructor(state)) {
                    popStateStack(state);
                    return "variable";
                  }
                  // as previously checked, if the word is element,attribute, axis specifier, call it an "xmlconstructor" and
                  // push the stack so we know to look for it on the next word
                  if(word == "element" || word == "attribute" || known.type == "axis_specifier") pushStateStack(state, {type: "xmlconstructor"});
            
                  // if the word is known, return the details of that else just call this a generic 'word'
                  return known ? known.style : "variable";
                }
              }
            
              // handle comments, including nested
              function tokenComment(stream, state) {
                var maybeEnd = false, maybeNested = false, nestedCount = 0, ch;
                while (ch = stream.next()) {
                  if (ch == ")" && maybeEnd) {
                    if(nestedCount > 0)
                      nestedCount--;
                    else {
                      popStateStack(state);
                      break;
                    }
                  }
                  else if(ch == ":" && maybeNested) {
                    nestedCount++;
                  }
                  maybeEnd = (ch == ":");
                  maybeNested = (ch == "(");
                }
            
                return "comment";
              }
            
              // tokenizer for string literals
              // optionally pass a tokenizer function to set state.tokenize back to when finished
              function tokenString(quote, f) {
                return function(stream, state) {
                  var ch;
            
                  if(isInString(state) && stream.current() == quote) {
                    popStateStack(state);
                    if(f) state.tokenize = f;
                    return "string";
                  }
            
                  pushStateStack(state, { type: "string", name: quote, tokenize: tokenString(quote, f) });
            
                  // if we're in a string and in an XML block, allow an embedded code block
                  if(stream.match("{", false) && isInXmlAttributeBlock(state)) {
                    state.tokenize = tokenBase;
                    return "string";
                  }
            
            
                  while (ch = stream.next()) {
                    if (ch ==  quote) {
                      popStateStack(state);
                      if(f) state.tokenize = f;
                      break;
                    }
                    else {
                      // if we're in a string and in an XML block, allow an embedded code block in an attribute
                      if(stream.match("{", false) && isInXmlAttributeBlock(state)) {
                        state.tokenize = tokenBase;
                        return "string";
                      }
            
                    }
                  }
            
                  return "string";
                };
              }
            
              // tokenizer for variables
              function tokenVariable(stream, state) {
                var isVariableChar = /[\w\$_-]/;
            
                // a variable may start with a quoted EQName so if the next character is quote, consume to the next quote
                if(stream.eat("\"")) {
                  while(stream.next() !== '\"'){};
                  stream.eat(":");
                } else {
                  stream.eatWhile(isVariableChar);
                  if(!stream.match(":=", false)) stream.eat(":");
                }
                stream.eatWhile(isVariableChar);
                state.tokenize = tokenBase;
                return "variable";
              }
            
              // tokenizer for XML tags
              function tokenTag(name, isclose) {
                return function(stream, state) {
                  stream.eatSpace();
                  if(isclose && stream.eat(">")) {
                    popStateStack(state);
                    state.tokenize = tokenBase;
                    return "tag";
                  }
                  // self closing tag without attributes?
                  if(!stream.eat("/"))
                    pushStateStack(state, { type: "tag", name: name, tokenize: tokenBase});
                  if(!stream.eat(">")) {
                    state.tokenize = tokenAttribute;
                    return "tag";
                  }
                  else {
                    state.tokenize = tokenBase;
                  }
                  return "tag";
                };
              }
            
              // tokenizer for XML attributes
              function tokenAttribute(stream, state) {
                var ch = stream.next();
            
                if(ch == "/" && stream.eat(">")) {
                  if(isInXmlAttributeBlock(state)) popStateStack(state);
                  if(isInXmlBlock(state)) popStateStack(state);
                  return "tag";
                }
                if(ch == ">") {
                  if(isInXmlAttributeBlock(state)) popStateStack(state);
                  return "tag";
                }
                if(ch == "=")
                  return null;
                // quoted string
                if (ch == '"' || ch == "'")
                  return chain(stream, state, tokenString(ch, tokenAttribute));
            
                if(!isInXmlAttributeBlock(state))
                  pushStateStack(state, { type: "attribute", tokenize: tokenAttribute});
            
                stream.eat(/[a-zA-Z_:]/);
                stream.eatWhile(/[-a-zA-Z0-9_:.]/);
                stream.eatSpace();
            
                // the case where the attribute has not value and the tag was closed
                if(stream.match(">", false) || stream.match("/", false)) {
                  popStateStack(state);
                  state.tokenize = tokenBase;
                }
            
                return "attribute";
              }
            
              // handle comments, including nested
              function tokenXMLComment(stream, state) {
                var ch;
                while (ch = stream.next()) {
                  if (ch == "-" && stream.match("->", true)) {
                    state.tokenize = tokenBase;
                    return "comment";
                  }
                }
              }
            
            
              // handle CDATA
              function tokenCDATA(stream, state) {
                var ch;
                while (ch = stream.next()) {
                  if (ch == "]" && stream.match("]", true)) {
                    state.tokenize = tokenBase;
                    return "comment";
                  }
                }
              }
            
              // handle preprocessing instructions
              function tokenPreProcessing(stream, state) {
                var ch;
                while (ch = stream.next()) {
                  if (ch == "?" && stream.match(">", true)) {
                    state.tokenize = tokenBase;
                    return "comment meta";
                  }
                }
              }
            
            
              // functions to test the current context of the state
              function isInXmlBlock(state) { return isIn(state, "tag"); }
              function isInXmlAttributeBlock(state) { return isIn(state, "attribute"); }
              function isInXmlConstructor(state) { return isIn(state, "xmlconstructor"); }
              function isInString(state) { return isIn(state, "string"); }
            
              function isEQNameAhead(stream) {
                // assume we've already eaten a quote (")
                if(stream.current() === '"')
                  return stream.match(/^[^\"]+\"\:/, false);
                else if(stream.current() === '\'')
                  return stream.match(/^[^\"]+\'\:/, false);
                else
                  return false;
              }
            
              function isIn(state, type) {
                return (state.stack.length && state.stack[state.stack.length - 1].type == type);
              }
            
              function pushStateStack(state, newState) {
                state.stack.push(newState);
              }
            
              function popStateStack(state) {
                state.stack.pop();
                var reinstateTokenize = state.stack.length && state.stack[state.stack.length-1].tokenize;
                state.tokenize = reinstateTokenize || tokenBase;
              }
            
              // the interface for the mode API
              return {
                startState: function() {
                  return {
                    tokenize: tokenBase,
                    cc: [],
                    stack: []
                  };
                },
            
                token: function(stream, state) {
                  if (stream.eatSpace()) return null;
                  var style = state.tokenize(stream, state);
                  return style;
                },
            
                blockCommentStart: "(:",
                blockCommentEnd: ":)"
            
              };
            
            });
            
            CodeMirror.defineMIME("application/xquery", "xquery");
            
            });
            
        • yaml
          • index.html
            <!doctype html>
            
            <title>CodeMirror: YAML mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="yaml.js"></script>
            <style>.CodeMirror { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; }</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">YAML</a>
              </ul>
            </div>
            
            <article>
            <h2>YAML mode</h2>
            <form><textarea id="code" name="code">
            --- # Favorite movies
            - Casablanca
            - North by Northwest
            - The Man Who Wasn't There
            --- # Shopping list
            [milk, pumpkin pie, eggs, juice]
            --- # Indented Blocks, common in YAML data files, use indentation and new lines to separate the key: value pairs
              name: John Smith
              age: 33
            --- # Inline Blocks, common in YAML data streams, use commas to separate the key: value pairs between braces
            {name: John Smith, age: 33}
            ---
            receipt:     Oz-Ware Purchase Invoice
            date:        2007-08-06
            customer:
                given:   Dorothy
                family:  Gale
            
            items:
                - part_no:   A4786
                  descrip:   Water Bucket (Filled)
                  price:     1.47
                  quantity:  4
            
                - part_no:   E1628
                  descrip:   High Heeled "Ruby" Slippers
                  size:       8
                  price:     100.27
                  quantity:  1
            
            bill-to:  &id001
                street: |
                        123 Tornado Alley
                        Suite 16
                city:   East Centerville
                state:  KS
            
            ship-to:  *id001
            
            specialDelivery:  >
                Follow the Yellow Brick
                Road to the Emerald City.
                Pay no attention to the
                man behind the curtain.
            ...
            </textarea></form>
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-yaml</code>.</p>
            
              </article>
            
          • yaml.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
                mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
                define(["../../lib/codemirror"], mod);
              else // Plain browser env
                mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode("yaml", function() {
            
              var cons = ['true', 'false', 'on', 'off', 'yes', 'no'];
              var keywordRegex = new RegExp("\\b(("+cons.join(")|(")+"))$", 'i');
            
              return {
                token: function(stream, state) {
                  var ch = stream.peek();
                  var esc = state.escaped;
                  state.escaped = false;
                  /* comments */
                  if (ch == "#" && (stream.pos == 0 || /\s/.test(stream.string.charAt(stream.pos - 1)))) {
                    stream.skipToEnd();
                    return "comment";
                  }
            
                  if (stream.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/))
                    return "string";
            
                  if (state.literal && stream.indentation() > state.keyCol) {
                    stream.skipToEnd(); return "string";
                  } else if (state.literal) { state.literal = false; }
                  if (stream.sol()) {
                    state.keyCol = 0;
                    state.pair = false;
                    state.pairStart = false;
                    /* document start */
                    if(stream.match(/---/)) { return "def"; }
                    /* document end */
                    if (stream.match(/\.\.\./)) { return "def"; }
                    /* array list item */
                    if (stream.match(/\s*-\s+/)) { return 'meta'; }
                  }
                  /* inline pairs/lists */
                  if (stream.match(/^(\{|\}|\[|\])/)) {
                    if (ch == '{')
                      state.inlinePairs++;
                    else if (ch == '}')
                      state.inlinePairs--;
                    else if (ch == '[')
                      state.inlineList++;
                    else
                      state.inlineList--;
                    return 'meta';
                  }
            
                  /* list seperator */
                  if (state.inlineList > 0 && !esc && ch == ',') {
                    stream.next();
                    return 'meta';
                  }
                  /* pairs seperator */
                  if (state.inlinePairs > 0 && !esc && ch == ',') {
                    state.keyCol = 0;
                    state.pair = false;
                    state.pairStart = false;
                    stream.next();
                    return 'meta';
                  }
            
                  /* start of value of a pair */
                  if (state.pairStart) {
                    /* block literals */
                    if (stream.match(/^\s*(\||\>)\s*/)) { state.literal = true; return 'meta'; };
                    /* references */
                    if (stream.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i)) { return 'variable-2'; }
                    /* numbers */
                    if (state.inlinePairs == 0 && stream.match(/^\s*-?[0-9\.\,]+\s?$/)) { return 'number'; }
                    if (state.inlinePairs > 0 && stream.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/)) { return 'number'; }
                    /* keywords */
                    if (stream.match(keywordRegex)) { return 'keyword'; }
                  }
            
                  /* pairs (associative arrays) -> key */
                  if (!state.pair && stream.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)) {
                    state.pair = true;
                    state.keyCol = stream.indentation();
                    return "atom";
                  }
                  if (state.pair && stream.match(/^:\s*/)) { state.pairStart = true; return 'meta'; }
            
                  /* nothing found, continue */
                  state.pairStart = false;
                  state.escaped = (ch == '\\');
                  stream.next();
                  return null;
                },
                startState: function() {
                  return {
                    pair: false,
                    pairStart: false,
                    keyCol: 0,
                    inlinePairs: 0,
                    inlineList: 0,
                    literal: false,
                    escaped: false
                  };
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-yaml", "yaml");
            
            });
            
        • z80
          • index.html
            <!doctype html>
            
            <title>CodeMirror: Z80 assembly mode</title>
            <meta charset="utf-8"/>
            <link rel=stylesheet href="../../doc/docs.css">
            
            <link rel="stylesheet" href="../../lib/codemirror.css">
            <script src="../../lib/codemirror.js"></script>
            <script src="z80.js"></script>
            <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
            <div id=nav>
              <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
            
              <ul>
                <li><a href="../../index.html">Home</a>
                <li><a href="../../doc/manual.html">Manual</a>
                <li><a href="https://github.com/codemirror/codemirror">Code</a>
              </ul>
              <ul>
                <li><a href="../index.html">Language modes</a>
                <li><a class=active href="#">Z80 assembly</a>
              </ul>
            </div>
            
            <article>
            <h2>Z80 assembly mode</h2>
            
            
            <div><textarea id="code" name="code">
            #include    "ti83plus.inc"
            #define     progStart   $9D95
                .org progStart-2
                .db $BB,$6D
            
                bcall(_ClrLCDFull)
                ld hl,0
                ld (CurCol),hl
                ld hl,Message
                bcall(_PutS) ; Displays the string
                bcall(_NewLine)
                ret
            Message:
                .db "Hello world!",0
            </textarea></div>
            
                <script>
                  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
                    lineNumbers: true
                  });
                </script>
            
                <p><strong>MIME types defined:</strong> <code>text/x-z80</code>, <code>text/x-ez80</code>.</p>
              </article>
            
          • z80.js
            // CodeMirror, copyright (c) by Marijn Haverbeke and others
            // Distributed under an MIT license: http://codemirror.net/LICENSE
            
            (function(mod) {
              if (typeof exports == "object" && typeof module == "object") // CommonJS
              mod(require("../../lib/codemirror"));
              else if (typeof define == "function" && define.amd) // AMD
              define(["../../lib/codemirror"], mod);
              else // Plain browser env
              mod(CodeMirror);
            })(function(CodeMirror) {
            "use strict";
            
            CodeMirror.defineMode('z80', function(_config, parserConfig) {
              var ez80 = parserConfig.ez80;
              var keywords1, keywords2;
              if (ez80) {
                keywords1 = /^(exx?|(ld|cp)([di]r?)?|[lp]ea|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|[de]i|halt|im|in([di]mr?|ir?|irx|2r?)|ot(dmr?|[id]rx|imr?)|out(0?|[di]r?|[di]2r?)|tst(io)?|slp)(\.([sl]?i)?[sl])?\b/i;
                keywords2 = /^(((call|j[pr]|rst|ret[in]?)(\.([sl]?i)?[sl])?)|(rs|st)mix)\b/i;
              } else {
                keywords1 = /^(exx?|(ld|cp|in)([di]r?)?|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|rst|[de]i|halt|im|ot[di]r|out[di]?)\b/i;
                keywords2 = /^(call|j[pr]|ret[in]?|b_?(call|jump))\b/i;
              }
            
              var variables1 = /^(af?|bc?|c|de?|e|hl?|l|i[xy]?|r|sp)\b/i;
              var variables2 = /^(n?[zc]|p[oe]?|m)\b/i;
              var errors = /^([hl][xy]|i[xy][hl]|slia|sll)\b/i;
              var numbers = /^([\da-f]+h|[0-7]+o|[01]+b|\d+d?)\b/i;
            
              return {
                startState: function() {
                  return {
                    context: 0
                  };
                },
                token: function(stream, state) {
                  if (!stream.column())
                    state.context = 0;
            
                  if (stream.eatSpace())
                    return null;
            
                  var w;
            
                  if (stream.eatWhile(/\w/)) {
                    if (ez80 && stream.eat('.')) {
                      stream.eatWhile(/\w/);
                    }
                    w = stream.current();
            
                    if (stream.indentation()) {
                      if ((state.context == 1 || state.context == 4) && variables1.test(w)) {
                        state.context = 4;
                        return 'var2';
                      }
            
                      if (state.context == 2 && variables2.test(w)) {
                        state.context = 4;
                        return 'var3';
                      }
            
                      if (keywords1.test(w)) {
                        state.context = 1;
                        return 'keyword';
                      } else if (keywords2.test(w)) {
                        state.context = 2;
                        return 'keyword';
                      } else if (state.context == 4 && numbers.test(w)) {
                        return 'number';
                      }
            
                      if (errors.test(w))
                        return 'error';
                    } else if (stream.match(numbers)) {
                      return 'number';
                    } else {
                      return null;
                    }
                  } else if (stream.eat(';')) {
                    stream.skipToEnd();
                    return 'comment';
                  } else if (stream.eat('"')) {
                    while (w = stream.next()) {
                      if (w == '"')
                        break;
            
                      if (w == '\\')
                        stream.next();
                    }
                    return 'string';
                  } else if (stream.eat('\'')) {
                    if (stream.match(/\\?.'/))
                      return 'number';
                  } else if (stream.eat('.') || stream.sol() && stream.eat('#')) {
                    state.context = 5;
            
                    if (stream.eatWhile(/\w/))
                      return 'def';
                  } else if (stream.eat('$')) {
                    if (stream.eatWhile(/[\da-f]/i))
                      return 'number';
                  } else if (stream.eat('%')) {
                    if (stream.eatWhile(/[01]/))
                      return 'number';
                  } else {
                    stream.next();
                  }
                  return null;
                }
              };
            });
            
            CodeMirror.defineMIME("text/x-z80", "z80");
            CodeMirror.defineMIME("text/x-ez80", { name: "z80", ez80: true });
            
            });
            
        • index.html
          <!doctype html>
          
          <title>CodeMirror: Language Modes</title>
          <meta charset="utf-8"/>
          <link rel=stylesheet href="../doc/docs.css">
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Language modes</a>
            </ul>
          </div>
          
          <article>
          
            <h2>Language modes</h2>
          
            <p>This is a list of every mode in the distribution. Each mode lives
          in a subdirectory of the <code>mode/</code> directory, and typically
          defines a single JavaScript file that implements the mode. Loading
          such file will make the language available to CodeMirror, through
          the <a href="../doc/manual.html#option_mode"><code>mode</code></a>
          option.</p>
          
            <div style="-webkit-columns: 100px 2; -moz-columns: 100px 2; columns: 100px 2;">
              <ul style="margin-top: 0">
                <li><a href="apl/index.html">APL</a></li>
                <li><a href="asn.1/index.html">ASN.1</a></li>
                <li><a href="asterisk/index.html">Asterisk dialplan</a></li>
                <li><a href="clike/index.html">C, C++, C#</a></li>
                <li><a href="clojure/index.html">Clojure</a></li>
                <li><a href="cmake/index.html">CMake</a></li>
                <li><a href="cobol/index.html">COBOL</a></li>
                <li><a href="coffeescript/index.html">CoffeeScript</a></li>
                <li><a href="commonlisp/index.html">Common Lisp</a></li>
                <li><a href="css/index.html">CSS</a></li>
                <li><a href="cypher/index.html">Cypher</a></li>
                <li><a href="python/index.html">Cython</a></li>
                <li><a href="d/index.html">D</a></li>
                <li><a href="dart/index.html">Dart</a></li>
                <li><a href="django/index.html">Django</a> (templating language)</li>
                <li><a href="dockerfile/index.html">Dockerfile</a></li>
                <li><a href="diff/index.html">diff</a></li>
                <li><a href="dtd/index.html">DTD</a></li>
                <li><a href="dylan/index.html">Dylan</a></li>
                <li><a href="ebnf/index.html">EBNF</a></li>
                <li><a href="ecl/index.html">ECL</a></li>
                <li><a href="eiffel/index.html">Eiffel</a></li>
                <li><a href="erlang/index.html">Erlang</a></li>
                <li><a href="forth/index.html">Forth</a></li>
                <li><a href="fortran/index.html">Fortran</a></li>
                <li><a href="mllike/index.html">F#</a></li>
                <li><a href="gas/index.html">Gas</a> (AT&amp;T-style assembly)</li>
                <li><a href="gherkin/index.html">Gherkin</a></li>
                <li><a href="go/index.html">Go</a></li>
                <li><a href="groovy/index.html">Groovy</a></li>
                <li><a href="haml/index.html">HAML</a></li>
                <li><a href="handlebars/index.html">Handlebars</a></li>
                <li><a href="haskell/index.html">Haskell</a></li>
                <li><a href="haxe/index.html">Haxe</a></li>
                <li><a href="htmlembedded/index.html">HTML embedded</a> (JSP, ASP.NET)</li>
                <li><a href="htmlmixed/index.html">HTML mixed-mode</a></li>
                <li><a href="http/index.html">HTTP</a></li>
                <li><a href="idl/index.html">IDL</a></li>
                <li><a href="clike/index.html">Java</a></li>
                <li><a href="jade/index.html">Jade</a></li>
                <li><a href="javascript/index.html">JavaScript</a></li>
                <li><a href="jinja2/index.html">Jinja2</a></li>
                <li><a href="julia/index.html">Julia</a></li>
                <li><a href="kotlin/index.html">Kotlin</a></li>
                <li><a href="css/less.html">LESS</a></li>
                <li><a href="livescript/index.html">LiveScript</a></li>
                <li><a href="lua/index.html">Lua</a></li>
                <li><a href="markdown/index.html">Markdown</a> (<a href="gfm/index.html">GitHub-flavour</a>)</li>
                <li><a href="mathematica/index.html">Mathematica</a></li>
                <li><a href="mirc/index.html">mIRC</a></li>
                <li><a href="modelica/index.html">Modelica</a></li>
                <li><a href="mumps/index.html">MUMPS</a></li>
                <li><a href="nginx/index.html">Nginx</a></li>
                <li><a href="ntriples/index.html">NTriples</a></li>
                <li><a href="clike/index.html">Objective C</a></li>
                <li><a href="mllike/index.html">OCaml</a></li>
                <li><a href="octave/index.html">Octave</a> (MATLAB)</li>
                <li><a href="pascal/index.html">Pascal</a></li>
                <li><a href="pegjs/index.html">PEG.js</a></li>
                <li><a href="perl/index.html">Perl</a></li>
                <li><a href="asciiarmor/index.html">PGP (ASCII armor)</a></li>
                <li><a href="php/index.html">PHP</a></li>
                <li><a href="pig/index.html">Pig Latin</a></li>
                <li><a href="properties/index.html">Properties files</a></li>
                <li><a href="puppet/index.html">Puppet</a></li>
                <li><a href="python/index.html">Python</a></li>
                <li><a href="q/index.html">Q</a></li>
                <li><a href="r/index.html">R</a></li>
                <li><a href="rpm/index.html">RPM</a></li>
                <li><a href="rst/index.html">reStructuredText</a></li>
                <li><a href="ruby/index.html">Ruby</a></li>
                <li><a href="rust/index.html">Rust</a></li>
                <li><a href="sass/index.html">Sass</a></li>
                <li><a href="spreadsheet/index.html">Spreadsheet</a></li>
                <li><a href="clike/scala.html">Scala</a></li>
                <li><a href="scheme/index.html">Scheme</a></li>
                <li><a href="css/scss.html">SCSS</a></li>
                <li><a href="shell/index.html">Shell</a></li>
                <li><a href="sieve/index.html">Sieve</a></li>
                <li><a href="slim/index.html">Slim</a></li>
                <li><a href="smalltalk/index.html">Smalltalk</a></li>
                <li><a href="smarty/index.html">Smarty</a></li>
                <li><a href="solr/index.html">Solr</a></li>
                <li><a href="soy/index.html">Soy</a></li>
                <li><a href="stylus/index.html">Stylus</a></li>
                <li><a href="sql/index.html">SQL</a> (several dialects)</li>
                <li><a href="sparql/index.html">SPARQL</a></li>
                <li><a href="stex/index.html">sTeX, LaTeX</a></li>
                <li><a href="tcl/index.html">Tcl</a></li>
                <li><a href="textile/index.html">Textile</a></li>
                <li><a href="tiddlywiki/index.html">Tiddlywiki</a></li>
                <li><a href="tiki/index.html">Tiki wiki</a></li>
                <li><a href="toml/index.html">TOML</a></li>
                <li><a href="tornado/index.html">Tornado</a> (templating language)</li>
                <li><a href="troff/index.html">troff</a> (for manpages)</li>
                <li><a href="ttcn/index.html">TTCN</a></li>
                <li><a href="ttcn-cfg/index.html">TTCN Configuration</a></li>
                <li><a href="turtle/index.html">Turtle</a></li>
                <li><a href="vb/index.html">VB.NET</a></li>
                <li><a href="vbscript/index.html">VBScript</a></li>
                <li><a href="velocity/index.html">Velocity</a></li>
                <li><a href="verilog/index.html">Verilog/SystemVerilog</a></li>
                <li><a href="xml/index.html">XML/HTML</a></li>
                <li><a href="xquery/index.html">XQuery</a></li>
                <li><a href="yaml/index.html">YAML</a></li>
                <li><a href="z80/index.html">Z80</a></li>
              </ul>
            </div>
          
          </article>
          
        • meta.js
          // CodeMirror, copyright (c) by Marijn Haverbeke and others
          // Distributed under an MIT license: http://codemirror.net/LICENSE
          
          (function(mod) {
            if (typeof exports == "object" && typeof module == "object") // CommonJS
              mod(require("../lib/codemirror"));
            else if (typeof define == "function" && define.amd) // AMD
              define(["../lib/codemirror"], mod);
            else // Plain browser env
              mod(CodeMirror);
          })(function(CodeMirror) {
            "use strict";
          
            CodeMirror.modeInfo = [
              {name: "APL", mime: "text/apl", mode: "apl", ext: ["dyalog", "apl"]},
              {name: "PGP", mimes: ["application/pgp", "application/pgp-keys", "application/pgp-signature"], mode: "asciiarmor", ext: ["pgp"]},
              {name: "Asterisk", mime: "text/x-asterisk", mode: "asterisk", file: /^extensions\.conf$/i},
              {name: "C", mime: "text/x-csrc", mode: "clike", ext: ["c", "h"]},
              {name: "C++", mime: "text/x-c++src", mode: "clike", ext: ["cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx"], alias: ["cpp"]},
              {name: "Cobol", mime: "text/x-cobol", mode: "cobol", ext: ["cob", "cpy"]},
              {name: "C#", mime: "text/x-csharp", mode: "clike", ext: ["cs"], alias: ["csharp"]},
              {name: "Clojure", mime: "text/x-clojure", mode: "clojure", ext: ["clj"]},
              {name: "CMake", mime: "text/x-cmake", mode: "cmake", ext: ["cmake", "cmake.in"], file: /^CMakeLists.txt$/},
              {name: "CoffeeScript", mime: "text/x-coffeescript", mode: "coffeescript", ext: ["coffee"], alias: ["coffee", "coffee-script"]},
              {name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp", ext: ["cl", "lisp", "el"], alias: ["lisp"]},
              {name: "Cypher", mime: "application/x-cypher-query", mode: "cypher", ext: ["cyp", "cypher"]},
              {name: "Cython", mime: "text/x-cython", mode: "python", ext: ["pyx", "pxd", "pxi"]},
              {name: "CSS", mime: "text/css", mode: "css", ext: ["css"]},
              {name: "CQL", mime: "text/x-cassandra", mode: "sql", ext: ["cql"]},
              {name: "D", mime: "text/x-d", mode: "d", ext: ["d"]},
              {name: "Dart", mimes: ["application/dart", "text/x-dart"], mode: "dart", ext: ["dart"]},
              {name: "diff", mime: "text/x-diff", mode: "diff", ext: ["diff", "patch"]},
              {name: "Django", mime: "text/x-django", mode: "django"},
              {name: "Dockerfile", mime: "text/x-dockerfile", mode: "dockerfile", file: /^Dockerfile$/},
              {name: "DTD", mime: "application/xml-dtd", mode: "dtd", ext: ["dtd"]},
              {name: "Dylan", mime: "text/x-dylan", mode: "dylan", ext: ["dylan", "dyl", "intr"]},
              {name: "EBNF", mime: "text/x-ebnf", mode: "ebnf"},
              {name: "ECL", mime: "text/x-ecl", mode: "ecl", ext: ["ecl"]},
              {name: "Eiffel", mime: "text/x-eiffel", mode: "eiffel", ext: ["e"]},
              {name: "Embedded Javascript", mime: "application/x-ejs", mode: "htmlembedded", ext: ["ejs"]},
              {name: "Embedded Ruby", mime: "application/x-erb", mode: "htmlembedded", ext: ["erb"]},
              {name: "Erlang", mime: "text/x-erlang", mode: "erlang", ext: ["erl"]},
              {name: "Forth", mime: "text/x-forth", mode: "forth", ext: ["forth", "fth", "4th"]},
              {name: "Fortran", mime: "text/x-fortran", mode: "fortran", ext: ["f", "for", "f77", "f90"]},
              {name: "F#", mime: "text/x-fsharp", mode: "mllike", ext: ["fs"], alias: ["fsharp"]},
              {name: "Gas", mime: "text/x-gas", mode: "gas", ext: ["s"]},
              {name: "Gherkin", mime: "text/x-feature", mode: "gherkin", ext: ["feature"]},
              {name: "GitHub Flavored Markdown", mime: "text/x-gfm", mode: "gfm", file: /^(readme|contributing|history).md$/i},
              {name: "Go", mime: "text/x-go", mode: "go", ext: ["go"]},
              {name: "Groovy", mime: "text/x-groovy", mode: "groovy", ext: ["groovy"]},
              {name: "HAML", mime: "text/x-haml", mode: "haml", ext: ["haml"]},
              {name: "Haskell", mime: "text/x-haskell", mode: "haskell", ext: ["hs"]},
              {name: "Haxe", mime: "text/x-haxe", mode: "haxe", ext: ["hx"]},
              {name: "HXML", mime: "text/x-hxml", mode: "haxe", ext: ["hxml"]},
              {name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded", ext: ["aspx"], alias: ["asp", "aspx"]},
              {name: "HTML", mime: "text/html", mode: "htmlmixed", ext: ["html", "htm"], alias: ["xhtml"]},
              {name: "HTTP", mime: "message/http", mode: "http"},
              {name: "IDL", mime: "text/x-idl", mode: "idl", ext: ["pro"]},
              {name: "Jade", mime: "text/x-jade", mode: "jade", ext: ["jade"]},
              {name: "Java", mime: "text/x-java", mode: "clike", ext: ["java"]},
              {name: "Java Server Pages", mime: "application/x-jsp", mode: "htmlembedded", ext: ["jsp"], alias: ["jsp"]},
              {name: "JavaScript", mimes: ["text/javascript", "text/ecmascript", "application/javascript", "application/x-javascript", "application/ecmascript"],
               mode: "javascript", ext: ["js"], alias: ["ecmascript", "js", "node"]},
              {name: "JSON", mimes: ["application/json", "application/x-json"], mode: "javascript", ext: ["json", "map"], alias: ["json5"]},
              {name: "JSON-LD", mime: "application/ld+json", mode: "javascript", ext: ["jsonld"], alias: ["jsonld"]},
              {name: "Jinja2", mime: "null", mode: "jinja2"},
              {name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"]},
              {name: "Kotlin", mime: "text/x-kotlin", mode: "kotlin", ext: ["kt"]},
              {name: "LESS", mime: "text/x-less", mode: "css", ext: ["less"]},
              {name: "LiveScript", mime: "text/x-livescript", mode: "livescript", ext: ["ls"], alias: ["ls"]},
              {name: "Lua", mime: "text/x-lua", mode: "lua", ext: ["lua"]},
              {name: "Markdown", mime: "text/x-markdown", mode: "markdown", ext: ["markdown", "md", "mkd"]},
              {name: "mIRC", mime: "text/mirc", mode: "mirc"},
              {name: "MariaDB SQL", mime: "text/x-mariadb", mode: "sql"},
              {name: "Mathematica", mime: "text/x-mathematica", mode: "mathematica", ext: ["m", "nb"]},
              {name: "Modelica", mime: "text/x-modelica", mode: "modelica", ext: ["mo"]},
              {name: "MUMPS", mime: "text/x-mumps", mode: "mumps"},
              {name: "MS SQL", mime: "text/x-mssql", mode: "sql"},
              {name: "MySQL", mime: "text/x-mysql", mode: "sql"},
              {name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx", file: /nginx.*\.conf$/i},
              {name: "NTriples", mime: "text/n-triples", mode: "ntriples", ext: ["nt"]},
              {name: "Objective C", mime: "text/x-objectivec", mode: "clike", ext: ["m", "mm"]},
              {name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]},
              {name: "Octave", mime: "text/x-octave", mode: "octave", ext: ["m"]},
              {name: "Pascal", mime: "text/x-pascal", mode: "pascal", ext: ["p", "pas"]},
              {name: "PEG.js", mime: "null", mode: "pegjs", ext: ["jsonld"]},
              {name: "Perl", mime: "text/x-perl", mode: "perl", ext: ["pl", "pm"]},
              {name: "PHP", mime: "application/x-httpd-php", mode: "php", ext: ["php", "php3", "php4", "php5", "phtml"]},
              {name: "Pig", mime: "text/x-pig", mode: "pig", ext: ["pig"]},
              {name: "Plain Text", mime: "text/plain", mode: "null", ext: ["txt", "text", "conf", "def", "list", "log"]},
              {name: "PLSQL", mime: "text/x-plsql", mode: "sql", ext: ["pls"]},
              {name: "Properties files", mime: "text/x-properties", mode: "properties", ext: ["properties", "ini", "in"], alias: ["ini", "properties"]},
              {name: "Python", mime: "text/x-python", mode: "python", ext: ["py", "pyw"]},
              {name: "Puppet", mime: "text/x-puppet", mode: "puppet", ext: ["pp"]},
              {name: "Q", mime: "text/x-q", mode: "q", ext: ["q"]},
              {name: "R", mime: "text/x-rsrc", mode: "r", ext: ["r"], alias: ["rscript"]},
              {name: "reStructuredText", mime: "text/x-rst", mode: "rst", ext: ["rst"], alias: ["rst"]},
              {name: "RPM Changes", mime: "text/x-rpm-changes", mode: "rpm"},
              {name: "RPM Spec", mime: "text/x-rpm-spec", mode: "rpm", ext: ["spec"]},
              {name: "Ruby", mime: "text/x-ruby", mode: "ruby", ext: ["rb"], alias: ["jruby", "macruby", "rake", "rb", "rbx"]},
              {name: "Rust", mime: "text/x-rustsrc", mode: "rust", ext: ["rs"]},
              {name: "Sass", mime: "text/x-sass", mode: "sass", ext: ["sass"]},
              {name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]},
              {name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]},
              {name: "SCSS", mime: "text/x-scss", mode: "css", ext: ["scss"]},
              {name: "Shell", mime: "text/x-sh", mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"]},
              {name: "Sieve", mime: "application/sieve", mode: "sieve", ext: ["siv", "sieve"]},
              {name: "Slim", mimes: ["text/x-slim", "application/x-slim"], mode: "slim", ext: ["slim"]},
              {name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk", ext: ["st"]},
              {name: "Smarty", mime: "text/x-smarty", mode: "smarty", ext: ["tpl"]},
              {name: "Solr", mime: "text/x-solr", mode: "solr"},
              {name: "Soy", mime: "text/x-soy", mode: "soy", ext: ["soy"], alias: ["closure template"]},
              {name: "SPARQL", mime: "application/sparql-query", mode: "sparql", ext: ["rq", "sparql"], alias: ["sparul"]},
              {name: "Spreadsheet", mime: "text/x-spreadsheet", mode: "spreadsheet", alias: ["excel", "formula"]},
              {name: "SQL", mime: "text/x-sql", mode: "sql", ext: ["sql"]},
              {name: "MariaDB", mime: "text/x-mariadb", mode: "sql"},
              {name: "sTeX", mime: "text/x-stex", mode: "stex"},
              {name: "LaTeX", mime: "text/x-latex", mode: "stex", ext: ["text", "ltx"], alias: ["tex"]},
              {name: "SystemVerilog", mime: "text/x-systemverilog", mode: "verilog", ext: ["v"]},
              {name: "Tcl", mime: "text/x-tcl", mode: "tcl", ext: ["tcl"]},
              {name: "Textile", mime: "text/x-textile", mode: "textile", ext: ["textile"]},
              {name: "TiddlyWiki ", mime: "text/x-tiddlywiki", mode: "tiddlywiki"},
              {name: "Tiki wiki", mime: "text/tiki", mode: "tiki"},
              {name: "TOML", mime: "text/x-toml", mode: "toml", ext: ["toml"]},
              {name: "Tornado", mime: "text/x-tornado", mode: "tornado"},
              {name: "troff", mime: "troff", mode: "troff", ext: ["1", "2", "3", "4", "5", "6", "7", "8", "9"]},
              {name: "Turtle", mime: "text/turtle", mode: "turtle", ext: ["ttl"]},
              {name: "TypeScript", mime: "application/typescript", mode: "javascript", ext: ["ts"], alias: ["ts"]},
              {name: "VB.NET", mime: "text/x-vb", mode: "vb", ext: ["vb"]},
              {name: "VBScript", mime: "text/vbscript", mode: "vbscript", ext: ["vbs"]},
              {name: "Velocity", mime: "text/velocity", mode: "velocity", ext: ["vtl"]},
              {name: "Verilog", mime: "text/x-verilog", mode: "verilog", ext: ["v"]},
              {name: "XML", mimes: ["application/xml", "text/xml"], mode: "xml", ext: ["xml", "xsl", "xsd"], alias: ["rss", "wsdl", "xsd"]},
              {name: "XQuery", mime: "application/xquery", mode: "xquery", ext: ["xy", "xquery"]},
              {name: "YAML", mime: "text/x-yaml", mode: "yaml", ext: ["yaml", "yml"], alias: ["yml"]},
              {name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]}
            ];
            // Ensure all modes have a mime property for backwards compatibility
            for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
              var info = CodeMirror.modeInfo[i];
              if (info.mimes) info.mime = info.mimes[0];
            }
          
            CodeMirror.findModeByMIME = function(mime) {
              mime = mime.toLowerCase();
              for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
                var info = CodeMirror.modeInfo[i];
                if (info.mime == mime) return info;
                if (info.mimes) for (var j = 0; j < info.mimes.length; j++)
                  if (info.mimes[j] == mime) return info;
              }
            };
          
            CodeMirror.findModeByExtension = function(ext) {
              for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
                var info = CodeMirror.modeInfo[i];
                if (info.ext) for (var j = 0; j < info.ext.length; j++)
                  if (info.ext[j] == ext) return info;
              }
            };
          
            CodeMirror.findModeByFileName = function(filename) {
              for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
                var info = CodeMirror.modeInfo[i];
                if (info.file && info.file.test(filename)) return info;
              }
              var dot = filename.lastIndexOf(".");
              var ext = dot > -1 && filename.substring(dot + 1, filename.length);
              if (ext) return CodeMirror.findModeByExtension(ext);
            };
          
            CodeMirror.findModeByName = function(name) {
              name = name.toLowerCase();
              for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
                var info = CodeMirror.modeInfo[i];
                if (info.name.toLowerCase() == name) return info;
                if (info.alias) for (var j = 0; j < info.alias.length; j++)
                  if (info.alias[j].toLowerCase() == name) return info;
              }
            };
          });
          
      • test
        • comment_test.js
          namespace = "comment_";
          
          (function() {
            function test(name, mode, run, before, after) {
              return testCM(name, function(cm) {
                run(cm);
                eq(cm.getValue(), after);
              }, {value: before, mode: mode});
            }
          
            var simpleProg = "function foo() {\n  return bar;\n}";
            var inlineBlock = "foo(/* bar */ true);";
            var inlineBlocks = "foo(/* bar */ true, /* baz */ false);";
            var multiLineInlineBlock = ["above();", "foo(/* bar */ true);", "below();"];
          
            test("block", "javascript", function(cm) {
              cm.blockComment(Pos(0, 3), Pos(3, 0), {blockCommentLead: " *"});
            }, simpleProg + "\n", "/* function foo() {\n *   return bar;\n * }\n */");
          
            test("blockToggle", "javascript", function(cm) {
              cm.blockComment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"});
              cm.uncomment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"});
            }, simpleProg, simpleProg);
          
            test("blockToggle2", "javascript", function(cm) {
              cm.setCursor({line: 0, ch: 7 /* inside the block comment */});
              cm.execCommand("toggleComment");
            }, inlineBlock, "foo(bar true);");
          
            // This test should work but currently fails.
            // test("blockToggle3", "javascript", function(cm) {
            //   cm.setCursor({line: 0, ch: 7 /* inside the first block comment */});
            //   cm.execCommand("toggleComment");
            // }, inlineBlocks, "foo(bar true, /* baz */ false);");
          
            test("line", "javascript", function(cm) {
              cm.lineComment(Pos(1, 1), Pos(1, 1));
            }, simpleProg, "function foo() {\n//   return bar;\n}");
          
            test("lineToggle", "javascript", function(cm) {
              cm.lineComment(Pos(0, 0), Pos(2, 1));
              cm.uncomment(Pos(0, 0), Pos(2, 1));
            }, simpleProg, simpleProg);
          
            test("fallbackToBlock", "css", function(cm) {
              cm.lineComment(Pos(0, 0), Pos(2, 1));
            }, "html {\n  border: none;\n}", "/* html {\n  border: none;\n} */");
          
            test("fallbackToLine", "ruby", function(cm) {
              cm.blockComment(Pos(0, 0), Pos(1));
            }, "def blah()\n  return hah\n", "# def blah()\n#   return hah\n");
          
            test("ignoreExternalBlockComments", "javascript", function(cm) {
              cm.execCommand("toggleComment");
            }, inlineBlocks, "// " + inlineBlocks);
          
            test("ignoreExternalBlockComments2", "javascript", function(cm) {
              cm.setCursor({line: 0, ch: null /* eol */});
              cm.execCommand("toggleComment");
            }, inlineBlocks, "// " + inlineBlocks);
          
            test("ignoreExternalBlockCommentsMultiLineAbove", "javascript", function(cm) {
              cm.setSelection({line: 0, ch: 0}, {line: 1, ch: 1});
              cm.execCommand("toggleComment");
            }, multiLineInlineBlock.join("\n"), ["// " + multiLineInlineBlock[0],
                                                 "// " + multiLineInlineBlock[1],
                                                 multiLineInlineBlock[2]].join("\n"));
          
            test("ignoreExternalBlockCommentsMultiLineBelow", "javascript", function(cm) {
              cm.setSelection({line: 1, ch: 13 /* after end of block comment */}, {line: 2, ch: 1});
              cm.execCommand("toggleComment");
            }, multiLineInlineBlock.join("\n"), [multiLineInlineBlock[0],
                                                 "// " + multiLineInlineBlock[1],
                                                 "// " + multiLineInlineBlock[2]].join("\n"));
          
            test("commentRange", "javascript", function(cm) {
              cm.blockComment(Pos(1, 2), Pos(1, 13), {fullLines: false});
            }, simpleProg, "function foo() {\n  /*return bar;*/\n}");
          
            test("indented", "javascript", function(cm) {
              cm.lineComment(Pos(1, 0), Pos(2), {indent: true});
            }, simpleProg, "function foo() {\n  // return bar;\n  // }");
          
            test("singleEmptyLine", "javascript", function(cm) {
              cm.setCursor(1);
              cm.execCommand("toggleComment");
            }, "a;\n\nb;", "a;\n// \nb;");
          
            test("dontMessWithStrings", "javascript", function(cm) {
              cm.execCommand("toggleComment");
            }, "console.log(\"/*string*/\");", "// console.log(\"/*string*/\");");
          
            test("dontMessWithStrings2", "javascript", function(cm) {
              cm.execCommand("toggleComment");
            }, "console.log(\"// string\");", "// console.log(\"// string\");");
          
            test("dontMessWithStrings3", "javascript", function(cm) {
              cm.execCommand("toggleComment");
            }, "// console.log(\"// string\");", "console.log(\"// string\");");
          })();
          
        • doc_test.js
          (function() {
            // A minilanguage for instantiating linked CodeMirror instances and Docs
            function instantiateSpec(spec, place, opts) {
              var names = {}, pos = 0, l = spec.length, editors = [];
              while (spec) {
                var m = spec.match(/^(\w+)(\*?)(?:='([^\']*)'|<(~?)(\w+)(?:\/(\d+)-(\d+))?)\s*/);
                var name = m[1], isDoc = m[2], cur;
                if (m[3]) {
                  cur = isDoc ? CodeMirror.Doc(m[3]) : CodeMirror(place, clone(opts, {value: m[3]}));
                } else {
                  var other = m[5];
                  if (!names.hasOwnProperty(other)) {
                    names[other] = editors.length;
                    editors.push(CodeMirror(place, opts));
                  }
                  var doc = editors[names[other]].linkedDoc({
                    sharedHist: !m[4],
                    from: m[6] ? Number(m[6]) : null,
                    to: m[7] ? Number(m[7]) : null
                  });
                  cur = isDoc ? doc : CodeMirror(place, clone(opts, {value: doc}));
                }
                names[name] = editors.length;
                editors.push(cur);
                spec = spec.slice(m[0].length);
              }
              return editors;
            }
          
            function clone(obj, props) {
              if (!obj) return;
              clone.prototype = obj;
              var inst = new clone();
              if (props) for (var n in props) if (props.hasOwnProperty(n))
                inst[n] = props[n];
              return inst;
            }
          
            function eqAll(val) {
              var end = arguments.length, msg = null;
              if (typeof arguments[end-1] == "string")
                msg = arguments[--end];
              if (i == end) throw new Error("No editors provided to eqAll");
              for (var i = 1; i < end; ++i)
                eq(arguments[i].getValue(), val, msg)
            }
          
            function testDoc(name, spec, run, opts, expectFail) {
              if (!opts) opts = {};
          
              return test("doc_" + name, function() {
                var place = document.getElementById("testground");
                var editors = instantiateSpec(spec, place, opts);
                var successful = false;
          
                try {
                  run.apply(null, editors);
                  successful = true;
                } finally {
                  if (!successful || verbose) {
                    place.style.visibility = "visible";
                  } else {
                    for (var i = 0; i < editors.length; ++i)
                      if (editors[i] instanceof CodeMirror)
                        place.removeChild(editors[i].getWrapperElement());
                  }
                }
              }, expectFail);
            }
          
            var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
          
            function testBasic(a, b) {
              eqAll("x", a, b);
              a.setValue("hey");
              eqAll("hey", a, b);
              b.setValue("wow");
              eqAll("wow", a, b);
              a.replaceRange("u\nv\nw", Pos(0, 3));
              b.replaceRange("i", Pos(0, 4));
              b.replaceRange("j", Pos(2, 1));
              eqAll("wowui\nv\nwj", a, b);
            }
          
            testDoc("basic", "A='x' B<A", testBasic);
            testDoc("basicSeparate", "A='x' B<~A", testBasic);
          
            testDoc("sharedHist", "A='ab\ncd\nef' B<A", function(a, b) {
              a.replaceRange("x", Pos(0));
              b.replaceRange("y", Pos(1));
              a.replaceRange("z", Pos(2));
              eqAll("abx\ncdy\nefz", a, b);
              a.undo();
              a.undo();
              eqAll("abx\ncd\nef", a, b);
              a.redo();
              eqAll("abx\ncdy\nef", a, b);
              b.redo();
              eqAll("abx\ncdy\nefz", a, b);
              a.undo(); b.undo(); a.undo(); a.undo();
              eqAll("ab\ncd\nef", a, b);
            }, null, ie_lt8);
          
            testDoc("undoIntact", "A='ab\ncd\nef' B<~A", function(a, b) {
              a.replaceRange("x", Pos(0));
              b.replaceRange("y", Pos(1));
              a.replaceRange("z", Pos(2));
              a.replaceRange("q", Pos(0));
              eqAll("abxq\ncdy\nefz", a, b);
              a.undo();
              a.undo();
              eqAll("abx\ncdy\nef", a, b);
              b.undo();
              eqAll("abx\ncd\nef", a, b);
              a.redo();
              eqAll("abx\ncd\nefz", a, b);
              a.redo();
              eqAll("abxq\ncd\nefz", a, b);
              a.undo(); a.undo(); a.undo(); a.undo();
              eqAll("ab\ncd\nef", a, b);
              b.redo();
              eqAll("ab\ncdy\nef", a, b);
            });
          
            testDoc("undoConflict", "A='ab\ncd\nef' B<~A", function(a, b) {
              a.replaceRange("x", Pos(0));
              a.replaceRange("z", Pos(2));
              // This should clear the first undo event in a, but not the second
              b.replaceRange("y", Pos(0));
              a.undo(); a.undo();
              eqAll("abxy\ncd\nef", a, b);
              a.replaceRange("u", Pos(2));
              a.replaceRange("v", Pos(0));
              // This should clear both events in a
              b.replaceRange("w", Pos(0));
              a.undo(); a.undo();
              eqAll("abxyvw\ncd\nefu", a, b);
            });
          
            testDoc("doubleRebase", "A='ab\ncd\nef\ng' B<~A C<B", function(a, b, c) {
              c.replaceRange("u", Pos(3));
              a.replaceRange("", Pos(0, 0), Pos(1, 0));
              c.undo();
              eqAll("cd\nef\ng", a, b, c);
            });
          
            testDoc("undoUpdate", "A='ab\ncd\nef' B<~A", function(a, b) {
              a.replaceRange("x", Pos(2));
              b.replaceRange("u\nv\nw\n", Pos(0, 0));
              a.undo();
              eqAll("u\nv\nw\nab\ncd\nef", a, b);
              a.redo();
              eqAll("u\nv\nw\nab\ncd\nefx", a, b);
              a.undo();
              eqAll("u\nv\nw\nab\ncd\nef", a, b);
              b.undo();
              a.redo();
              eqAll("ab\ncd\nefx", a, b);
              a.undo();
              eqAll("ab\ncd\nef", a, b);
            });
          
            testDoc("undoKeepRanges", "A='abcdefg' B<A", function(a, b) {
              var m = a.markText(Pos(0, 1), Pos(0, 3), {className: "foo"});
              b.replaceRange("x", Pos(0, 0));
              eqPos(m.find().from, Pos(0, 2));
              b.replaceRange("yzzy", Pos(0, 1), Pos(0));
              eq(m.find(), null);
              b.undo();
              eqPos(m.find().from, Pos(0, 2));
              b.undo();
              eqPos(m.find().from, Pos(0, 1));
            });
          
            testDoc("longChain", "A='uv' B<A C<B D<C", function(a, b, c, d) {
              a.replaceSelection("X");
              eqAll("Xuv", a, b, c, d);
              d.replaceRange("Y", Pos(0));
              eqAll("XuvY", a, b, c, d);
            });
          
            testDoc("broadCast", "B<A C<A D<A E<A", function(a, b, c, d, e) {
              b.setValue("uu");
              eqAll("uu", a, b, c, d, e);
              a.replaceRange("v", Pos(0, 1));
              eqAll("uvu", a, b, c, d, e);
            });
          
            // A and B share a history, C and D share a separate one
            testDoc("islands", "A='x\ny\nz' B<A C<~A D<C", function(a, b, c, d) {
              a.replaceRange("u", Pos(0));
              d.replaceRange("v", Pos(2));
              b.undo();
              eqAll("x\ny\nzv", a, b, c, d);
              c.undo();
              eqAll("x\ny\nz", a, b, c, d);
              a.redo();
              eqAll("xu\ny\nz", a, b, c, d);
              d.redo();
              eqAll("xu\ny\nzv", a, b, c, d);
            });
          
            testDoc("unlink", "B<A C<A D<B", function(a, b, c, d) {
              a.setValue("hi");
              b.unlinkDoc(a);
              d.setValue("aye");
              eqAll("hi", a, c);
              eqAll("aye", b, d);
              a.setValue("oo");
              eqAll("oo", a, c);
              eqAll("aye", b, d);
            });
          
            testDoc("bareDoc", "A*='foo' B*<A C<B", function(a, b, c) {
              is(a instanceof CodeMirror.Doc);
              is(b instanceof CodeMirror.Doc);
              is(c instanceof CodeMirror);
              eqAll("foo", a, b, c);
              a.replaceRange("hey", Pos(0, 0), Pos(0));
              c.replaceRange("!", Pos(0));
              eqAll("hey!", a, b, c);
              b.unlinkDoc(a);
              b.setValue("x");
              eqAll("x", b, c);
              eqAll("hey!", a);
            });
          
            testDoc("swapDoc", "A='a' B*='b' C<A", function(a, b, c) {
              var d = a.swapDoc(b);
              d.setValue("x");
              eqAll("x", c, d);
              eqAll("b", a, b);
            });
          
            testDoc("docKeepsScroll", "A='x' B*='y'", function(a, b) {
              addDoc(a, 200, 200);
              a.scrollIntoView(Pos(199, 200));
              var c = a.swapDoc(b);
              a.swapDoc(c);
              var pos = a.getScrollInfo();
              is(pos.left > 0, "not at left");
              is(pos.top > 0, "not at top");
            });
          
            testDoc("copyDoc", "A='u'", function(a) {
              var copy = a.getDoc().copy(true);
              a.setValue("foo");
              copy.setValue("bar");
              var old = a.swapDoc(copy);
              eq(a.getValue(), "bar");
              a.undo();
              eq(a.getValue(), "u");
              a.swapDoc(old);
              eq(a.getValue(), "foo");
              eq(old.historySize().undo, 1);
              eq(old.copy(false).historySize().undo, 0);
            });
          
            testDoc("docKeepsMode", "A='1+1'", function(a) {
              var other = CodeMirror.Doc("hi", "text/x-markdown");
              a.setOption("mode", "text/javascript");
              var old = a.swapDoc(other);
              eq(a.getOption("mode"), "text/x-markdown");
              eq(a.getMode().name, "markdown");
              a.swapDoc(old);
              eq(a.getOption("mode"), "text/javascript");
              eq(a.getMode().name, "javascript");
            });
          
            testDoc("subview", "A='1\n2\n3\n4\n5' B<~A/1-3", function(a, b) {
              eq(b.getValue(), "2\n3");
              eq(b.firstLine(), 1);
              b.setCursor(Pos(4));
              eqPos(b.getCursor(), Pos(2, 1));
              a.replaceRange("-1\n0\n", Pos(0, 0));
              eq(b.firstLine(), 3);
              eqPos(b.getCursor(), Pos(4, 1));
              a.undo();
              eqPos(b.getCursor(), Pos(2, 1));
              b.replaceRange("oyoy\n", Pos(2, 0));
              eq(a.getValue(), "1\n2\noyoy\n3\n4\n5");
              b.undo();
              eq(a.getValue(), "1\n2\n3\n4\n5");
            });
          
            testDoc("subviewEditOnBoundary", "A='11\n22\n33\n44\n55' B<~A/1-4", function(a, b) {
              a.replaceRange("x\nyy\nz", Pos(0, 1), Pos(2, 1));
              eq(b.firstLine(), 2);
              eq(b.lineCount(), 2);
              eq(b.getValue(), "z3\n44");
              a.replaceRange("q\nrr\ns", Pos(3, 1), Pos(4, 1));
              eq(b.firstLine(), 2);
              eq(b.getValue(), "z3\n4q");
              eq(a.getValue(), "1x\nyy\nz3\n4q\nrr\ns5");
              a.execCommand("selectAll");
              a.replaceSelection("!");
              eqAll("!", a, b);
            });
          
          
            testDoc("sharedMarker", "A='ab\ncd\nef\ngh' B<A C<~A/1-2", function(a, b, c) {
              var mark = b.markText(Pos(0, 1), Pos(3, 1),
                                    {className: "cm-searching", shared: true});
              var found = a.findMarksAt(Pos(0, 2));
              eq(found.length, 1);
              eq(found[0], mark);
              eq(c.findMarksAt(Pos(1, 1)).length, 1);
              eqPos(mark.find().from, Pos(0, 1));
              eqPos(mark.find().to, Pos(3, 1));
              b.replaceRange("x\ny\n", Pos(0, 0));
              eqPos(mark.find().from, Pos(2, 1));
              eqPos(mark.find().to, Pos(5, 1));
              var cleared = 0;
              CodeMirror.on(mark, "clear", function() {++cleared;});
              b.operation(function(){mark.clear();});
              eq(a.findMarksAt(Pos(3, 1)).length, 0);
              eq(b.findMarksAt(Pos(3, 1)).length, 0);
              eq(c.findMarksAt(Pos(3, 1)).length, 0);
              eq(mark.find(), null);
              eq(cleared, 1);
            });
          
            testDoc("sharedMarkerCopy", "A='abcde'", function(a) {
              var shared = a.markText(Pos(0, 1), Pos(0, 3), {shared: true});
              var b = a.linkedDoc();
              var found = b.findMarksAt(Pos(0, 2));
              eq(found.length, 1);
              eq(found[0], shared);
              shared.clear();
              eq(b.findMarksAt(Pos(0, 2)), 0);
            });
          
            testDoc("sharedMarkerDetach", "A='abcde' B<A C<B", function(a, b, c) {
              var shared = a.markText(Pos(0, 1), Pos(0, 3), {shared: true});
              a.unlinkDoc(b);
              var inB = b.findMarksAt(Pos(0, 2));
              eq(inB.length, 1);
              is(inB[0] != shared);
              var inC = c.findMarksAt(Pos(0, 2));
              eq(inC.length, 1);
              is(inC[0] != shared);
              inC[0].clear();
              is(shared.find());
            });
          
            testDoc("sharedBookmark", "A='ab\ncd\nef\ngh' B<A C<~A/1-2", function(a, b, c) {
              var mark = b.setBookmark(Pos(1, 1), {shared: true});
              var found = a.findMarksAt(Pos(1, 1));
              eq(found.length, 1);
              eq(found[0], mark);
              eq(c.findMarksAt(Pos(1, 1)).length, 1);
              eqPos(mark.find(), Pos(1, 1));
              b.replaceRange("x\ny\n", Pos(0, 0));
              eqPos(mark.find(), Pos(3, 1));
              var cleared = 0;
              CodeMirror.on(mark, "clear", function() {++cleared;});
              b.operation(function() {mark.clear();});
              eq(a.findMarks(Pos(0, 0), Pos(5)).length, 0);
              eq(b.findMarks(Pos(0, 0), Pos(5)).length, 0);
              eq(c.findMarks(Pos(0, 0), Pos(5)).length, 0);
              eq(mark.find(), null);
              eq(cleared, 1);
            });
          
            testDoc("undoInSubview", "A='line 0\nline 1\nline 2\nline 3\nline 4' B<A/1-4", function(a, b) {
              b.replaceRange("x", Pos(2, 0));
              a.undo();
              eq(a.getValue(), "line 0\nline 1\nline 2\nline 3\nline 4");
              eq(b.getValue(), "line 1\nline 2\nline 3");
            });
          })();
          
        • driver.js
          var tests = [], filters = [], allNames = [];
          
          function Failure(why) {this.message = why;}
          Failure.prototype.toString = function() { return this.message; };
          
          function indexOf(collection, elt) {
            if (collection.indexOf) return collection.indexOf(elt);
            for (var i = 0, e = collection.length; i < e; ++i)
              if (collection[i] == elt) return i;
            return -1;
          }
          
          function test(name, run, expectedFail) {
            // Force unique names
            var originalName = name;
            var i = 2; // Second function would be NAME_2
            while (indexOf(allNames, name) !== -1){
              name = originalName + "_" + i;
              i++;
            }
            allNames.push(name);
            // Add test
            tests.push({name: name, func: run, expectedFail: expectedFail});
            return name;
          }
          var namespace = "";
          function testCM(name, run, opts, expectedFail) {
            return test(namespace + name, function() {
              var place = document.getElementById("testground"), cm = window.cm = CodeMirror(place, opts);
              var successful = false;
              try {
                run(cm);
                successful = true;
              } finally {
                if (!successful || verbose) {
                  place.style.visibility = "visible";
                } else {
                  place.removeChild(cm.getWrapperElement());
                }
              }
            }, expectedFail);
          }
          
          function runTests(callback) {
            var totalTime = 0;
            function step(i) {
              for (;;) {
                if (i === tests.length) {
                  running = false;
                  return callback("done");
                }
                var test = tests[i], skip = false;
                if (filters.length) {
                  skip = true;
                  for (var j = 0; j < filters.length; j++)
                    if (test.name.match(filters[j])) skip = false;
                }
                if (skip) {
                  callback("skipped", test.name, message);
                  i++;
                } else {
                  break;
                }
              }
              var expFail = test.expectedFail, startTime = +new Date, threw = false;
              try {
                var message = test.func();
              } catch(e) {
                threw = true;
                if (expFail) callback("expected", test.name);
                else if (e instanceof Failure) callback("fail", test.name, e.message);
                else {
                  var pos = /(?:\bat |@).*?([^\/:]+):(\d+)/.exec(e.stack);
                  if (pos) console["log"](e.stack);
                  callback("error", test.name, e.toString() + (pos ? " (" + pos[1] + ":" + pos[2] + ")" : ""));
                }
              }
              if (!threw) {
                if (expFail) callback("fail", test.name, message || "expected failure, but succeeded");
                else callback("ok", test.name, message);
              }
              if (!quit) { // Run next test
                var delay = 0;
                totalTime += (+new Date) - startTime;
                if (totalTime > 500){
                  totalTime = 0;
                  delay = 50;
                }
                setTimeout(function(){step(i + 1);}, delay);
              } else { // Quit tests
                running = false;
                return null;
              }
            }
            step(0);
          }
          
          function label(str, msg) {
            if (msg) return str + " (" + msg + ")";
            return str;
          }
          function eq(a, b, msg) {
            if (a != b) throw new Failure(label(a + " != " + b, msg));
          }
          function near(a, b, margin, msg) {
            if (Math.abs(a - b) > margin)
              throw new Failure(label(a + " is not close to " + b + " (" + margin + ")", msg));
          }
          function eqPos(a, b, msg) {
            function str(p) { return "{line:" + p.line + ",ch:" + p.ch + "}"; }
            if (a == b) return;
            if (a == null) throw new Failure(label("comparing null to " + str(b), msg));
            if (b == null) throw new Failure(label("comparing " + str(a) + " to null", msg));
            if (a.line != b.line || a.ch != b.ch) throw new Failure(label(str(a) + " != " + str(b), msg));
          }
          function is(a, msg) {
            if (!a) throw new Failure(label("assertion failed", msg));
          }
          
          function countTests() {
            if (!filters.length) return tests.length;
            var sum = 0;
            for (var i = 0; i < tests.length; ++i) {
              var name = tests[i].name;
              for (var j = 0; j < filters.length; j++) {
                if (name.match(filters[j])) {
                  ++sum;
                  break;
                }
              }
            }
            return sum;
          }
          
          function parseTestFilter(s) {
            if (/_\*$/.test(s)) return new RegExp("^" + s.slice(0, s.length - 2), "i");
            else return new RegExp(s, "i");
          }
          
        • emacs_test.js
          (function() {
            "use strict";
          
            var Pos = CodeMirror.Pos;
            namespace = "emacs_";
          
            var eventCache = {};
            function fakeEvent(keyName) {
              var event = eventCache[key];
              if (event) return event;
          
              var ctrl, shift, alt;
              var key = keyName.replace(/\w+-/g, function(type) {
                if (type == "Ctrl-") ctrl = true;
                else if (type == "Alt-") alt = true;
                else if (type == "Shift-") shift = true;
                return "";
              });
              var code;
              for (var c in CodeMirror.keyNames)
                if (CodeMirror.keyNames[c] == key) { code = c; break; }
              if (c == null) throw new Error("Unknown key: " + key);
          
              return eventCache[keyName] = {
                type: "keydown", keyCode: code, ctrlKey: ctrl, shiftKey: shift, altKey: alt,
                preventDefault: function(){}, stopPropagation: function(){}
              };
            }
          
            function sim(name, start /*, actions... */) {
              var keys = Array.prototype.slice.call(arguments, 2);
              testCM(name, function(cm) {
                for (var i = 0; i < keys.length; ++i) {
                  var cur = keys[i];
                  if (cur instanceof Pos) cm.setCursor(cur);
                  else if (cur.call) cur(cm);
                  else cm.triggerOnKeyDown(fakeEvent(cur));
                }
              }, {keyMap: "emacs", value: start, mode: "javascript"});
            }
          
            function at(line, ch) { return function(cm) { eqPos(cm.getCursor(), Pos(line, ch)); }; }
            function txt(str) { return function(cm) { eq(cm.getValue(), str); }; }
          
            sim("motionHSimple", "abc", "Ctrl-F", "Ctrl-F", "Ctrl-B", at(0, 1));
            sim("motionHMulti", "abcde",
                "Ctrl-4", "Ctrl-F", at(0, 4), "Ctrl--", "Ctrl-2", "Ctrl-F", at(0, 2),
                "Ctrl-5", "Ctrl-B", at(0, 0));
          
            sim("motionHWord", "abc. def ghi",
                "Alt-F", at(0, 3), "Alt-F", at(0, 8),
                "Ctrl-B", "Alt-B", at(0, 5), "Alt-B", at(0, 0));
            sim("motionHWordMulti", "abc. def ghi ",
                "Ctrl-3", "Alt-F", at(0, 12), "Ctrl-2", "Alt-B", at(0, 5),
                "Ctrl--", "Alt-B", at(0, 8));
          
            sim("motionVSimple", "a\nb\nc\n", "Ctrl-N", "Ctrl-N", "Ctrl-P", at(1, 0));
            sim("motionVMulti", "a\nb\nc\nd\ne\n",
                "Ctrl-2", "Ctrl-N", at(2, 0), "Ctrl-F", "Ctrl--", "Ctrl-N", at(1, 1),
                "Ctrl--", "Ctrl-3", "Ctrl-P", at(4, 1));
          
            sim("killYank", "abc\ndef\nghi",
                "Ctrl-F", "Ctrl-Space", "Ctrl-N", "Ctrl-N", "Ctrl-W", "Ctrl-E", "Ctrl-Y",
                txt("ahibc\ndef\ng"));
            sim("killRing", "abcdef",
                "Ctrl-Space", "Ctrl-F", "Ctrl-W", "Ctrl-Space", "Ctrl-F", "Ctrl-W",
                "Ctrl-Y", "Alt-Y",
                txt("acdef"));
            sim("copyYank", "abcd",
                "Ctrl-Space", "Ctrl-E", "Alt-W", "Ctrl-Y",
                txt("abcdabcd"));
          
            sim("killLineSimple", "foo\nbar", "Ctrl-F", "Ctrl-K", txt("f\nbar"));
            sim("killLineEmptyLine", "foo\n  \nbar", "Ctrl-N", "Ctrl-K", txt("foo\nbar"));
            sim("killLineMulti", "foo\nbar\nbaz",
                "Ctrl-F", "Ctrl-F", "Ctrl-K", "Ctrl-K", "Ctrl-K", "Ctrl-A", "Ctrl-Y",
                txt("o\nbarfo\nbaz"));
          
            sim("moveByParagraph", "abc\ndef\n\n\nhij\nklm\n\n",
                "Ctrl-F", "Ctrl-Down", at(2, 0), "Ctrl-Down", at(6, 0),
                "Ctrl-N", "Ctrl-Up", at(3, 0), "Ctrl-Up", at(0, 0),
                Pos(1, 2), "Ctrl-Down", at(2, 0), Pos(4, 2), "Ctrl-Up", at(3, 0));
            sim("moveByParagraphMulti", "abc\n\ndef\n\nhij\n\nklm",
                "Ctrl-U", "2", "Ctrl-Down", at(3, 0),
                "Shift-Alt-.", "Ctrl-3", "Ctrl-Up", at(1, 0));
          
            sim("moveBySentence", "sentence one! sentence\ntwo\n\nparagraph two",
                "Alt-E", at(0, 13), "Alt-E", at(1, 3), "Ctrl-F", "Alt-A", at(0, 13));
          
            sim("moveByExpr", "function foo(a, b) {}",
                "Ctrl-Alt-F", at(0, 8), "Ctrl-Alt-F", at(0, 12), "Ctrl-Alt-F", at(0, 18),
                "Ctrl-Alt-B", at(0, 12), "Ctrl-Alt-B", at(0, 9));
            sim("moveByExprMulti", "foo bar baz bug",
                "Ctrl-2", "Ctrl-Alt-F", at(0, 7),
                "Ctrl--", "Ctrl-Alt-F", at(0, 4),
                "Ctrl--", "Ctrl-2", "Ctrl-Alt-B", at(0, 11));
            sim("delExpr", "var x = [\n  a,\n  b\n  c\n];",
                Pos(0, 8), "Ctrl-Alt-K", txt("var x = ;"), "Ctrl-/",
                Pos(4, 1), "Ctrl-Alt-Backspace", txt("var x = ;"));
            sim("delExprMulti", "foo bar baz",
                "Ctrl-2", "Ctrl-Alt-K", txt(" baz"),
                "Ctrl-/", "Ctrl-E", "Ctrl-2", "Ctrl-Alt-Backspace", txt("foo "));
          
            sim("justOneSpace", "hi      bye  ",
                Pos(0, 4), "Alt-Space", txt("hi bye  "),
                Pos(0, 4), "Alt-Space", txt("hi b ye  "),
                "Ctrl-A", "Alt-Space", "Ctrl-E", "Alt-Space", txt(" hi b ye "));
          
            sim("openLine", "foo bar", "Alt-F", "Ctrl-O", txt("foo\n bar"))
          
            sim("transposeChar", "abcd\ne",
                "Ctrl-F", "Ctrl-T", "Ctrl-T", txt("bcad\ne"), at(0, 3),
                "Ctrl-F", "Ctrl-T", "Ctrl-T", "Ctrl-T", txt("bcda\ne"), at(0, 4),
                "Ctrl-F", "Ctrl-T", txt("bcde\na"), at(1, 0));
          
            sim("manipWordCase", "foo BAR bAZ",
                "Alt-C", "Alt-L", "Alt-U", txt("Foo bar BAZ"),
                "Ctrl-A", "Alt-U", "Alt-L", "Alt-C", txt("FOO bar Baz"));
            sim("manipWordCaseMulti", "foo Bar bAz",
                "Ctrl-2", "Alt-U", txt("FOO BAR bAz"),
                "Ctrl-A", "Ctrl-3", "Alt-C", txt("Foo Bar Baz"));
          
            sim("upExpr", "foo {\n  bar[];\n  baz(blah);\n}",
                Pos(2, 7), "Ctrl-Alt-U", at(2, 5), "Ctrl-Alt-U", at(0, 4));
            sim("transposeExpr", "do foo[bar] dah",
                Pos(0, 6), "Ctrl-Alt-T", txt("do [bar]foo dah"));
          
            sim("clearMark", "abcde", Pos(0, 2), "Ctrl-Space", "Ctrl-F", "Ctrl-F",
                "Ctrl-G", "Ctrl-W", txt("abcde"));
          
            sim("delRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Delete", txt("cde"));
            sim("backspaceRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Backspace", txt("cde"));
          
            testCM("save", function(cm) {
              var saved = false;
              CodeMirror.commands.save = function(cm) { saved = cm.getValue(); };
              cm.triggerOnKeyDown(fakeEvent("Ctrl-X"));
              cm.triggerOnKeyDown(fakeEvent("Ctrl-S"));
              is(saved, "hi");
            }, {value: "hi", keyMap: "emacs"});
          })();
          
        • index.html
          <!doctype html>
          
          <meta charset="utf-8"/>
          <title>CodeMirror: Test Suite</title>
          <link rel=stylesheet href="../doc/docs.css">
          
          <link rel="stylesheet" href="../lib/codemirror.css">
          <link rel="stylesheet" href="mode_test.css">
          <script src="../doc/activebookmark.js"></script>
          <script src="../lib/codemirror.js"></script>
          <script src="../addon/mode/overlay.js"></script>
          <script src="../addon/mode/multiplex.js"></script>
          <script src="../addon/search/searchcursor.js"></script>
          <script src="../addon/dialog/dialog.js"></script>
          <script src="../addon/edit/matchbrackets.js"></script>
          <script src="../addon/hint/sql-hint.js"></script>
          <script src="../addon/comment/comment.js"></script>
          <script src="../mode/css/css.js"></script>
          <script src="../mode/clike/clike.js"></script>
          <!-- clike must be after css or vim and sublime tests will fail -->
          <script src="../mode/gfm/gfm.js"></script>
          <script src="../mode/haml/haml.js"></script>
          <script src="../mode/htmlmixed/htmlmixed.js"></script>
          <script src="../mode/javascript/javascript.js"></script>
          <script src="../mode/markdown/markdown.js"></script>
          <script src="../mode/php/php.js"></script>
          <script src="../mode/ruby/ruby.js"></script>
          <script src="../mode/shell/shell.js"></script>
          <script src="../mode/slim/slim.js"></script>
          <script src="../mode/sql/sql.js"></script>
          <script src="../mode/stex/stex.js"></script>
          <script src="../mode/textile/textile.js"></script>
          <script src="../mode/verilog/verilog.js"></script>
          <script src="../mode/xml/xml.js"></script>
          <script src="../mode/xquery/xquery.js"></script>
          <script src="../keymap/emacs.js"></script>
          <script src="../keymap/sublime.js"></script>
          <script src="../keymap/vim.js"></script>
          
          <style type="text/css">
            .ok {color: #090;}
            .fail {color: #e00;}
            .error {color: #c90;}
            .done {font-weight: bold;}
            #progress {
            background: #45d;
            color: white;
            text-shadow: 0 0 1px #45d, 0 0 2px #45d, 0 0 3px #45d;
            font-weight: bold;
            white-space: pre;
            }
            #testground {
            visibility: hidden;
            }
            #testground.offscreen {
            visibility: visible;
            position: absolute;
            left: -10000px;
            top: -10000px;
            }
            .CodeMirror { border: 1px solid black; }
          </style>
          
          <div id=nav>
            <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
          
            <ul>
              <li><a href="../index.html">Home</a>
              <li><a href="../doc/manual.html">Manual</a>
              <li><a href="https://github.com/codemirror/codemirror">Code</a>
            </ul>
            <ul>
              <li><a class=active href="#">Test suite</a>
            </ul>
          </div>
          
          <article>
            <h2>Test Suite</h2>
          
              <p>A limited set of programmatic sanity tests for CodeMirror.</p>
          
              <div style="border: 1px solid black; padding: 1px; max-width: 700px;">
                <div style="width: 0px;" id=progress><div style="padding: 3px;">Ran <span id="progress_ran">0</span><span id="progress_total"> of 0</span> tests</div></div>
              </div>
              <p id=status>Please enable JavaScript...</p>
              <div id=output></div>
          
              <div id=testground></div>
          
              <script src="driver.js"></script>
              <script src="test.js"></script>
              <script src="doc_test.js"></script>
              <script src="multi_test.js"></script>
              <script src="scroll_test.js"></script>
              <script src="comment_test.js"></script>
              <script src="search_test.js"></script>
              <script src="mode_test.js"></script>
          
              <script src="../mode/css/test.js"></script>
              <script src="../mode/css/scss_test.js"></script>
              <script src="../mode/css/less_test.js"></script>
              <script src="../mode/gfm/test.js"></script>
              <script src="../mode/haml/test.js"></script>
              <script src="../mode/javascript/test.js"></script>
              <script src="../mode/markdown/test.js"></script>
              <script src="../mode/php/test.js"></script>
              <script src="../mode/ruby/test.js"></script>
              <script src="../mode/shell/test.js"></script>
              <script src="../mode/slim/test.js"></script>
              <script src="../mode/stex/test.js"></script>
              <script src="../mode/textile/test.js"></script>
              <script src="../mode/verilog/test.js"></script>
              <script src="../mode/xml/test.js"></script>
              <script src="../mode/xquery/test.js"></script>
              <script src="../addon/mode/multiplex_test.js"></script>
              <script src="emacs_test.js"></script>
              <script src="sql-hint-test.js"></script>
              <script src="sublime_test.js"></script>
              <script src="vim_test.js"></script>
              <script>
                window.onload = runHarness;
                CodeMirror.on(window, 'hashchange', runHarness);
          
                function esc(str) {
                  return str.replace(/[<&]/, function(ch) { return ch == "<" ? "&lt;" : "&amp;"; });
                }
          
                var output = document.getElementById("output"),
                    progress = document.getElementById("progress"),
                    progressRan = document.getElementById("progress_ran").childNodes[0],
                    progressTotal = document.getElementById("progress_total").childNodes[0];
                var count = 0,
                    failed = 0,
                    skipped = 0,
                    bad = "",
                    running = false, // Flag that states tests are running
                    quit = false, // Flag to quit tests ASAP
                    verbose = false; // Adds message for *every* test to output
          
                function runHarness(){
                  if (running) {
                    quit = true;
                    setStatus("Restarting tests...", '', true);
                    setTimeout(function(){runHarness();}, 500);
                    return;
                  }
                  filters = [];
                  verbose = false;
                  if (window.location.hash.substr(1)){
                    var strings = window.location.hash.substr(1).split(",");
                    while (strings.length) {
                      var s = strings.shift();
                      if (s === "verbose")
                        verbose = true;
                      else
                        filters.push(parseTestFilter(decodeURIComponent(s)));
                    }
                  }
                  quit = false;
                  running = true;
                  setStatus("Loading tests...");
                  count = 0;
                  failed = 0;
                  skipped = 0;
                  bad = "";
                  totalTests = countTests();
                  progressTotal.nodeValue = " of " + totalTests;
                  progressRan.nodeValue = count;
                  output.innerHTML = '';
                  document.getElementById("testground").innerHTML = "<form>" +
                    "<textarea id=\"code\" name=\"code\"></textarea>" +
                    "<input type=submit value=ok name=submit>" +
                    "</form>";
                  runTests(displayTest);
                }
          
                function setStatus(message, className, force){
                  if (quit && !force) return;
                  if (!message) throw("must provide message");
                  var status = document.getElementById("status").childNodes[0];
                  status.nodeValue = message;
                  status.parentNode.className = className;
                }
                function addOutput(name, className, code){
                  var newOutput = document.createElement("dl");
                  var newTitle = document.createElement("dt");
                  newTitle.className = className;
                  newTitle.appendChild(document.createTextNode(name));
                  newOutput.appendChild(newTitle);
                  var newMessage = document.createElement("dd");
                  newMessage.innerHTML = code;
                  newOutput.appendChild(newTitle);
                  newOutput.appendChild(newMessage);
                  output.appendChild(newOutput);
                }
                function displayTest(type, name, customMessage) {
                  var message = "???";
                  if (type != "done" && type != "skipped") ++count;
                  progress.style.width = (count * (progress.parentNode.clientWidth - 2) / totalTests) + "px";
                  progressRan.nodeValue = count;
                  if (type == "ok") {
                    message = "Test '" + name + "' succeeded";
                    if (!verbose) customMessage = false;
                  } else if (type == "skipped") {
                    message = "Test '" + name + "' skipped";
                    ++skipped;
                    if (!verbose) customMessage = false;
                  } else if (type == "expected") {
                    message = "Test '" + name + "' failed as expected";
                    if (!verbose) customMessage = false;
                  } else if (type == "error" || type == "fail") {
                    ++failed;
                    message = "Test '" + name + "' failed";
                  } else if (type == "done") {
                    if (failed) {
                      type += " fail";
                      message = failed + " failure" + (failed > 1 ? "s" : "");
                    } else if (count < totalTests) {
                      failed = totalTests - count;
                      type += " fail";
                      message = failed + " failure" + (failed > 1 ? "s" : "");
                    } else {
                      type += " ok";
                      message = "All passed";
                      if (skipped) {
                        message += " (" + skipped + " skipped)";
                      }
                    }
                    progressTotal.nodeValue = '';
                    customMessage = true; // Hack to avoid adding to output
                  }
                  if (verbose && !customMessage)  customMessage = message;
                  setStatus(message, type);
                  if (customMessage && customMessage.length > 0) {
                    addOutput(name, type, customMessage);
                  }
                }
              </script>
          
          </article>
          
        • lint.js
          var blint = require("blint");
          
          ["mode", "lib", "addon", "keymap"].forEach(function(dir) {
            blint.checkDir(dir, {
              browser: true,
              allowedGlobals: ["CodeMirror", "define", "test", "requirejs"],
              blob: "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http:\/\/codemirror.net\/LICENSE\n\n"
            });
          });
          
          module.exports = {ok: blint.success()};
          
        • mode_test.css
          .mt-output .mt-token {
            border: 1px solid #ddd;
            white-space: pre;
            font-family: "Consolas", monospace;
            text-align: center;
          }
          
          .mt-output .mt-style {
            font-size: x-small;
          }
          
          .mt-output .mt-state {
            font-size: x-small;
            vertical-align: top;
          }
          
          .mt-output .mt-state-row {
            display: none;
          }
          
          .mt-state-unhide .mt-output .mt-state-row {
            display: table-row;
          }
          
        • mode_test.js
          /**
           * Helper to test CodeMirror highlighting modes. It pretty prints output of the
           * highlighter and can check against expected styles.
           *
           * Mode tests are registered by calling test.mode(testName, mode,
           * tokens), where mode is a mode object as returned by
           * CodeMirror.getMode, and tokens is an array of lines that make up
           * the test.
           *
           * These lines are strings, in which styled stretches of code are
           * enclosed in brackets `[]`, and prefixed by their style. For
           * example, `[keyword if]`. Brackets in the code itself must be
           * duplicated to prevent them from being interpreted as token
           * boundaries. For example `a[[i]]` for `a[i]`. If a token has
           * multiple styles, the styles must be separated by ampersands, for
           * example `[tag&error </hmtl>]`.
           *
           * See the test.js files in the css, markdown, gfm, and stex mode
           * directories for examples.
           */
          (function() {
            function findSingle(str, pos, ch) {
              for (;;) {
                var found = str.indexOf(ch, pos);
                if (found == -1) return null;
                if (str.charAt(found + 1) != ch) return found;
                pos = found + 2;
              }
            }
          
            var styleName = /[\w&-_]+/g;
            function parseTokens(strs) {
              var tokens = [], plain = "";
              for (var i = 0; i < strs.length; ++i) {
                if (i) plain += "\n";
                var str = strs[i], pos = 0;
                while (pos < str.length) {
                  var style = null, text;
                  if (str.charAt(pos) == "[" && str.charAt(pos+1) != "[") {
                    styleName.lastIndex = pos + 1;
                    var m = styleName.exec(str);
                    style = m[0].replace(/&/g, " ");
                    var textStart = pos + style.length + 2;
                    var end = findSingle(str, textStart, "]");
                    if (end == null) throw new Error("Unterminated token at " + pos + " in '" + str + "'" + style);
                    text = str.slice(textStart, end);
                    pos = end + 1;
                  } else {
                    var end = findSingle(str, pos, "[");
                    if (end == null) end = str.length;
                    text = str.slice(pos, end);
                    pos = end;
                  }
                  text = text.replace(/\[\[|\]\]/g, function(s) {return s.charAt(0);});
                  tokens.push({style: style, text: text});
                  plain += text;
                }
              }
              return {tokens: tokens, plain: plain};
            }
          
            test.mode = function(name, mode, tokens, modeName) {
              var data = parseTokens(tokens);
              return test((modeName || mode.name) + "_" + name, function() {
                return compare(data.plain, data.tokens, mode);
              });
            };
          
            function esc(str) {
              return str.replace('&', '&amp;').replace('<', '&lt;').replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
          ;
            }
          
            function compare(text, expected, mode) {
          
              var expectedOutput = [];
              for (var i = 0; i < expected.length; ++i) {
                var sty = expected[i].style;
                if (sty && sty.indexOf(" ")) sty = sty.split(' ').sort().join(' ');
                expectedOutput.push({style: sty, text: expected[i].text});
              }
          
              var observedOutput = highlight(text, mode);
          
              var s = "";
              var diff = highlightOutputsDifferent(expectedOutput, observedOutput);
              if (diff != null) {
                s += '<div class="mt-test mt-fail">';
                s +=   '<pre>' + esc(text) + '</pre>';
                s +=   '<div class="cm-s-default">';
                s += 'expected:';
                s +=   prettyPrintOutputTable(expectedOutput, diff);
                s += 'observed: [<a onclick="this.parentElement.className+=\' mt-state-unhide\'">display states</a>]';
                s +=   prettyPrintOutputTable(observedOutput, diff);
                s +=   '</div>';
                s += '</div>';
              }
              if (observedOutput.indentFailures) {
                for (var i = 0; i < observedOutput.indentFailures.length; i++)
                  s += "<div class='mt-test mt-fail'>" + esc(observedOutput.indentFailures[i]) + "</div>";
              }
              if (s) throw new Failure(s);
            }
          
            function stringify(obj) {
              function replacer(key, obj) {
                if (typeof obj == "function") {
                  var m = obj.toString().match(/function\s*[^\s(]*/);
                  return m ? m[0] : "function";
                }
                return obj;
              }
              if (window.JSON && JSON.stringify)
                return JSON.stringify(obj, replacer, 2);
              return "[unsupported]";  // Fail safely if no native JSON.
            }
          
            function highlight(string, mode) {
              var state = mode.startState();
          
              var lines = string.replace(/\r\n/g,'\n').split('\n');
              var st = [], pos = 0;
              for (var i = 0; i < lines.length; ++i) {
                var line = lines[i], newLine = true;
                if (mode.indent) {
                  var ws = line.match(/^\s*/)[0];
                  var indent = mode.indent(state, line.slice(ws.length));
                  if (indent != CodeMirror.Pass && indent != ws.length)
                    (st.indentFailures || (st.indentFailures = [])).push(
                      "Indentation of line " + (i + 1) + " is " + indent + " (expected " + ws.length + ")");
                }
                var stream = new CodeMirror.StringStream(line);
                if (line == "" && mode.blankLine) mode.blankLine(state);
                /* Start copied code from CodeMirror.highlight */
                while (!stream.eol()) {
                  for (var j = 0; j < 10 && stream.start >= stream.pos; j++)
                    var compare = mode.token(stream, state);
                  if (j == 10)
                    throw new Failure("Failed to advance the stream." + stream.string + " " + stream.pos);
                  var substr = stream.current();
                  if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' ');
                  stream.start = stream.pos;
                  if (pos && st[pos-1].style == compare && !newLine) {
                    st[pos-1].text += substr;
                  } else if (substr) {
                    st[pos++] = {style: compare, text: substr, state: stringify(state)};
                  }
                  // Give up when line is ridiculously long
                  if (stream.pos > 5000) {
                    st[pos++] = {style: null, text: this.text.slice(stream.pos)};
                    break;
                  }
                  newLine = false;
                }
              }
          
              return st;
            }
          
            function highlightOutputsDifferent(o1, o2) {
              var minLen = Math.min(o1.length, o2.length);
              for (var i = 0; i < minLen; ++i)
                if (o1[i].style != o2[i].style || o1[i].text != o2[i].text) return i;
              if (o1.length > minLen || o2.length > minLen) return minLen;
            }
          
            function prettyPrintOutputTable(output, diffAt) {
              var s = '<table class="mt-output">';
              s += '<tr>';
              for (var i = 0; i < output.length; ++i) {
                var style = output[i].style, val = output[i].text;
                s +=
                '<td class="mt-token"' + (i == diffAt * 2 ? " style='background: pink'" : "") + '>' +
                  '<span class="cm-' + esc(String(style)) + '">' +
                  esc(val.replace(/ /g,'\xb7')) +  // · MIDDLE DOT
                  '</span>' +
                  '</td>';
              }
              s += '</tr><tr>';
              for (var i = 0; i < output.length; ++i) {
                s += '<td class="mt-style"><span>' + (output[i].style || null) + '</span></td>';
              }
              if(output[0].state) {
                s += '</tr><tr class="mt-state-row" title="State AFTER each token">';
                for (var i = 0; i < output.length; ++i) {
                  s += '<td class="mt-state"><pre>' + esc(output[i].state) + '</pre></td>';
                }
              }
              s += '</tr></table>';
              return s;
            }
          })();
          
        • multi_test.js
          (function() {
            namespace = "multi_";
          
            function hasSelections(cm) {
              var sels = cm.listSelections();
              var given = (arguments.length - 1) / 4;
              if (sels.length != given)
                throw new Failure("expected " + given + " selections, found " + sels.length);
              for (var i = 0, p = 1; i < given; i++, p += 4) {
                var anchor = Pos(arguments[p], arguments[p + 1]);
                var head = Pos(arguments[p + 2], arguments[p + 3]);
                eqPos(sels[i].anchor, anchor, "anchor of selection " + i);
                eqPos(sels[i].head, head, "head of selection " + i);
              }
            }
            function hasCursors(cm) {
              var sels = cm.listSelections();
              var given = (arguments.length - 1) / 2;
              if (sels.length != given)
                throw new Failure("expected " + given + " selections, found " + sels.length);
              for (var i = 0, p = 1; i < given; i++, p += 2) {
                eqPos(sels[i].anchor, sels[i].head, "something selected for " + i);
                var head = Pos(arguments[p], arguments[p + 1]);
                eqPos(sels[i].head, head, "selection " + i);
              }
            }
          
            testCM("getSelection", function(cm) {
              select(cm, {anchor: Pos(0, 0), head: Pos(1, 2)}, {anchor: Pos(2, 2), head: Pos(2, 0)});
              eq(cm.getSelection(), "1234\n56\n90");
              eq(cm.getSelection(false).join("|"), "1234|56|90");
              eq(cm.getSelections().join("|"), "1234\n56|90");
            }, {value: "1234\n5678\n90"});
          
            testCM("setSelection", function(cm) {
              select(cm, Pos(3, 0), Pos(0, 0), {anchor: Pos(2, 5), head: Pos(1, 0)});
              hasSelections(cm, 0, 0, 0, 0,
                            2, 5, 1, 0,
                            3, 0, 3, 0);
              cm.setSelection(Pos(1, 2), Pos(1, 1));
              hasSelections(cm, 1, 2, 1, 1);
              select(cm, {anchor: Pos(1, 1), head: Pos(2, 4)},
                     {anchor: Pos(0, 0), head: Pos(1, 3)},
                     Pos(3, 0), Pos(2, 2));
              hasSelections(cm, 0, 0, 2, 4,
                            3, 0, 3, 0);
              cm.setSelections([{anchor: Pos(0, 1), head: Pos(0, 2)},
                                {anchor: Pos(1, 1), head: Pos(1, 2)},
                                {anchor: Pos(2, 1), head: Pos(2, 2)}], 1);
              eqPos(cm.getCursor("head"), Pos(1, 2));
              eqPos(cm.getCursor("anchor"), Pos(1, 1));
              eqPos(cm.getCursor("from"), Pos(1, 1));
              eqPos(cm.getCursor("to"), Pos(1, 2));
              cm.setCursor(Pos(1, 1));
              hasCursors(cm, 1, 1);
            }, {value: "abcde\nabcde\nabcde\n"});
          
            testCM("somethingSelected", function(cm) {
              select(cm, Pos(0, 1), {anchor: Pos(0, 3), head: Pos(0, 5)});
              eq(cm.somethingSelected(), true);
              select(cm, Pos(0, 1), Pos(0, 3), Pos(0, 5));
              eq(cm.somethingSelected(), false);
            }, {value: "123456789"});
          
            testCM("extendSelection", function(cm) {
              select(cm, Pos(0, 1), Pos(1, 1), Pos(2, 1));
              cm.setExtending(true);
              cm.extendSelections([Pos(0, 2), Pos(1, 0), Pos(2, 3)]);
              hasSelections(cm, 0, 1, 0, 2,
                            1, 1, 1, 0,
                            2, 1, 2, 3);
              cm.extendSelection(Pos(2, 4), Pos(2, 0));
              hasSelections(cm, 2, 4, 2, 0);
            }, {value: "1234\n1234\n1234"});
          
            testCM("addSelection", function(cm) {
              select(cm, Pos(0, 1), Pos(1, 1));
              cm.addSelection(Pos(0, 0), Pos(0, 4));
              hasSelections(cm, 0, 0, 0, 4,
                            1, 1, 1, 1);
              cm.addSelection(Pos(2, 2));
              hasSelections(cm, 0, 0, 0, 4,
                            1, 1, 1, 1,
                            2, 2, 2, 2);
            }, {value: "1234\n1234\n1234"});
          
            testCM("replaceSelection", function(cm) {
              var selections = [{anchor: Pos(0, 0), head: Pos(0, 1)},
                                {anchor: Pos(0, 2), head: Pos(0, 3)},
                                {anchor: Pos(0, 4), head: Pos(0, 5)},
                                {anchor: Pos(2, 1), head: Pos(2, 4)},
                                {anchor: Pos(2, 5), head: Pos(2, 6)}];
              var val = "123456\n123456\n123456";
              cm.setValue(val);
              cm.setSelections(selections);
              cm.replaceSelection("ab", "around");
              eq(cm.getValue(), "ab2ab4ab6\n123456\n1ab5ab");
              hasSelections(cm, 0, 0, 0, 2,
                            0, 3, 0, 5,
                            0, 6, 0, 8,
                            2, 1, 2, 3,
                            2, 4, 2, 6);
              cm.setValue(val);
              cm.setSelections(selections);
              cm.replaceSelection("", "around");
              eq(cm.getValue(), "246\n123456\n15");
              hasSelections(cm, 0, 0, 0, 0,
                            0, 1, 0, 1,
                            0, 2, 0, 2,
                            2, 1, 2, 1,
                            2, 2, 2, 2);
              cm.setValue(val);
              cm.setSelections(selections);
              cm.replaceSelection("X\nY\nZ", "around");
              hasSelections(cm, 0, 0, 2, 1,
                            2, 2, 4, 1,
                            4, 2, 6, 1,
                            8, 1, 10, 1,
                            10, 2, 12, 1);
              cm.replaceSelection("a", "around");
              hasSelections(cm, 0, 0, 0, 1,
                            0, 2, 0, 3,
                            0, 4, 0, 5,
                            2, 1, 2, 2,
                            2, 3, 2, 4);
              cm.replaceSelection("xy", "start");
              hasSelections(cm, 0, 0, 0, 0,
                            0, 3, 0, 3,
                            0, 6, 0, 6,
                            2, 1, 2, 1,
                            2, 4, 2, 4);
              cm.replaceSelection("z\nf");
              hasSelections(cm, 1, 1, 1, 1,
                            2, 1, 2, 1,
                            3, 1, 3, 1,
                            6, 1, 6, 1,
                            7, 1, 7, 1);
              eq(cm.getValue(), "z\nfxy2z\nfxy4z\nfxy6\n123456\n1z\nfxy5z\nfxy");
            });
          
            function select(cm) {
              var sels = [];
              for (var i = 1; i < arguments.length; i++) {
                var arg = arguments[i];
                if (arg.head) sels.push(arg);
                else sels.push({head: arg, anchor: arg});
              }
              cm.setSelections(sels, sels.length - 1);
            }
          
            testCM("indentSelection", function(cm) {
              select(cm, Pos(0, 1), Pos(1, 1));
              cm.indentSelection(4);
              eq(cm.getValue(), "    foo\n    bar\nbaz");
          
              select(cm, Pos(0, 2), Pos(0, 3), Pos(0, 4));
              cm.indentSelection(-2);
              eq(cm.getValue(), "  foo\n    bar\nbaz");
          
              select(cm, {anchor: Pos(0, 0), head: Pos(1, 2)},
                     {anchor: Pos(1, 3), head: Pos(2, 0)});
              cm.indentSelection(-2);
              eq(cm.getValue(), "foo\n  bar\nbaz");
            }, {value: "foo\nbar\nbaz"});
          
            testCM("killLine", function(cm) {
              select(cm, Pos(0, 1), Pos(0, 2), Pos(1, 1));
              cm.execCommand("killLine");
              eq(cm.getValue(), "f\nb\nbaz");
              cm.execCommand("killLine");
              eq(cm.getValue(), "fbbaz");
              cm.setValue("foo\nbar\nbaz");
              select(cm, Pos(0, 1), {anchor: Pos(0, 2), head: Pos(2, 1)});
              cm.execCommand("killLine");
              eq(cm.getValue(), "faz");
            }, {value: "foo\nbar\nbaz"});
          
            testCM("deleteLine", function(cm) {
              select(cm, Pos(0, 0),
                     {head: Pos(0, 1), anchor: Pos(2, 0)},
                     Pos(4, 0));
              cm.execCommand("deleteLine");
              eq(cm.getValue(), "4\n6\n7");
              select(cm, Pos(2, 1));
              cm.execCommand("deleteLine");
              eq(cm.getValue(), "4\n6\n");
            }, {value: "1\n2\n3\n4\n5\n6\n7"});
          
            testCM("deleteH", function(cm) {
              select(cm, Pos(0, 4), {anchor: Pos(1, 4), head: Pos(1, 5)});
              cm.execCommand("delWordAfter");
              eq(cm.getValue(), "foo bar baz\nabc ef ghi\n");
              cm.execCommand("delWordAfter");
              eq(cm.getValue(), "foo  baz\nabc  ghi\n");
              cm.execCommand("delCharBefore");
              cm.execCommand("delCharBefore");
              eq(cm.getValue(), "fo baz\nab ghi\n");
              select(cm, Pos(0, 3), Pos(0, 4), Pos(0, 5));
              cm.execCommand("delWordAfter");
              eq(cm.getValue(), "fo \nab ghi\n");
            }, {value: "foo bar baz\nabc def ghi\n"});
          
            testCM("goLineStart", function(cm) {
              select(cm, Pos(0, 2), Pos(0, 3), Pos(1, 1));
              cm.execCommand("goLineStart");
              hasCursors(cm, 0, 0, 1, 0);
              select(cm, Pos(1, 1), Pos(0, 1));
              cm.setExtending(true);
              cm.execCommand("goLineStart");
              hasSelections(cm, 0, 1, 0, 0,
                            1, 1, 1, 0);
            }, {value: "foo\nbar\nbaz"});
          
            testCM("moveV", function(cm) {
              select(cm, Pos(0, 2), Pos(1, 2));
              cm.execCommand("goLineDown");
              hasCursors(cm, 1, 2, 2, 2);
              cm.execCommand("goLineUp");
              hasCursors(cm, 0, 2, 1, 2);
              cm.execCommand("goLineUp");
              hasCursors(cm, 0, 0, 0, 2);
              cm.execCommand("goLineUp");
              hasCursors(cm, 0, 0);
              select(cm, Pos(0, 2), Pos(1, 2));
              cm.setExtending(true);
              cm.execCommand("goLineDown");
              hasSelections(cm, 0, 2, 2, 2);
            }, {value: "12345\n12345\n12345"});
          
            testCM("moveH", function(cm) {
              select(cm, Pos(0, 1), Pos(0, 3), Pos(0, 5), Pos(2, 3));
              cm.execCommand("goCharRight");
              hasCursors(cm, 0, 2, 0, 4, 1, 0, 2, 4);
              cm.execCommand("goCharLeft");
              hasCursors(cm, 0, 1, 0, 3, 0, 5, 2, 3);
              for (var i = 0; i < 15; i++)
                cm.execCommand("goCharRight");
              hasCursors(cm, 2, 4, 2, 5);
            }, {value: "12345\n12345\n12345"});
          
            testCM("newlineAndIndent", function(cm) {
              select(cm, Pos(0, 5), Pos(1, 5));
              cm.execCommand("newlineAndIndent");
              hasCursors(cm, 1, 2, 3, 2);
              eq(cm.getValue(), "x = [\n  1];\ny = [\n  2];");
              cm.undo();
              eq(cm.getValue(), "x = [1];\ny = [2];");
              hasCursors(cm, 0, 5, 1, 5);
              select(cm, Pos(0, 5), Pos(0, 6));
              cm.execCommand("newlineAndIndent");
              hasCursors(cm, 1, 2, 2, 0);
              eq(cm.getValue(), "x = [\n  1\n];\ny = [2];");
            }, {value: "x = [1];\ny = [2];", mode: "javascript"});
          
            testCM("goDocStartEnd", function(cm) {
              select(cm, Pos(0, 1), Pos(1, 1));
              cm.execCommand("goDocStart");
              hasCursors(cm, 0, 0);
              select(cm, Pos(0, 1), Pos(1, 1));
              cm.execCommand("goDocEnd");
              hasCursors(cm, 1, 3);
              select(cm, Pos(0, 1), Pos(1, 1));
              cm.setExtending(true);
              cm.execCommand("goDocEnd");
              hasSelections(cm, 1, 1, 1, 3);
            }, {value: "abc\ndef"});
          
            testCM("selectionHistory", function(cm) {
              for (var i = 0; i < 3; ++i)
                cm.addSelection(Pos(0, i * 2), Pos(0, i * 2 + 1));
              cm.execCommand("undoSelection");
              eq(cm.getSelection(), "1\n2");
              cm.execCommand("undoSelection");
              eq(cm.getSelection(), "1");
              cm.execCommand("undoSelection");
              eq(cm.getSelection(), "");
              eqPos(cm.getCursor(), Pos(0, 0));
              cm.execCommand("redoSelection");
              eq(cm.getSelection(), "1");
              cm.execCommand("redoSelection");
              eq(cm.getSelection(), "1\n2");
              cm.execCommand("redoSelection");
              eq(cm.getSelection(), "1\n2\n3");
            }, {value: "1 2 3"});
          })();
          
        • phantom_driver.js
          var page = require('webpage').create();
          
          page.open("http://localhost:3000/test/index.html", function (status) {
            if (status != "success") {
              console.log("page couldn't be loaded successfully");
              phantom.exit(1);
            }
            waitFor(function () {
              return page.evaluate(function () {
                var output = document.getElementById('status');
                if (!output) { return false; }
                return (/^(\d+ failures?|all passed)/i).test(output.innerText);
              });
            }, function () {
              var failed = page.evaluate(function () { return window.failed; });
              var output = page.evaluate(function () {
                return document.getElementById('output').innerText + "\n" +
                  document.getElementById('status').innerText;
              });
              console.log(output);
              phantom.exit(failed > 0 ? 1 : 0);
            });
          });
          
          function waitFor (test, cb) {
            if (test()) {
              cb();
            } else {
              setTimeout(function () { waitFor(test, cb); }, 250);
            }
          }
          
        • run.js
          #!/usr/bin/env node
          
          var ok = require("./lint").ok;
          
          var files = new (require('node-static').Server)();
          
          var server = require('http').createServer(function (req, res) {
            req.addListener('end', function () {
              files.serve(req, res, function (err/*, result */) {
                if (err) {
                  console.error(err);
                  process.exit(1);
                }
              });
            }).resume();
          }).addListener('error', function (err) {
            throw err;
          }).listen(3000, function () {
            var childProcess = require('child_process');
            var phantomjs = require("phantomjs");
            var childArgs = [
              require("path").join(__dirname, 'phantom_driver.js')
            ];
            childProcess.execFile(phantomjs.path, childArgs, function (err, stdout, stderr) {
              server.close();
              console.log(stdout);
              if (err) console.error(err);
              if (stderr) console.error(stderr);
              process.exit(err || stderr || !ok ? 1 : 0);
            });
          });
          
        • scroll_test.js
          (function() {
            "use strict";
          
            namespace = "scroll_";
          
            testCM("bars_hidden", function(cm) {
              for (var i = 0;; i++) {
                var wrapBox = cm.getWrapperElement().getBoundingClientRect();
                var scrollBox = cm.getScrollerElement().getBoundingClientRect();
                is(wrapBox.bottom < scrollBox.bottom - 10);
                is(wrapBox.right < scrollBox.right - 10);
                if (i == 1) break;
                cm.getWrapperElement().style.height = "auto";
                cm.refresh();
              }
            });
            
            function barH(cm) { return byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0]; }
            function barV(cm) { return byClassName(cm.getWrapperElement(), "CodeMirror-vscrollbar")[0]; }
          
            function displayBottom(cm, scrollbar) {
              if (scrollbar)
                return barH(cm).getBoundingClientRect().top;
              else
                return cm.getWrapperElement().getBoundingClientRect().bottom - 1;
            }
          
            function displayRight(cm, scrollbar) {
              if (scrollbar)
                return barV(cm).getBoundingClientRect().left;
              else
                return cm.getWrapperElement().getBoundingClientRect().right - 1;
            }
          
            function testMovedownFixed(cm, hScroll) {
              cm.setSize("100px", "100px");
              if (hScroll) cm.setValue(new Array(100).join("x"));
              var bottom = displayBottom(cm, hScroll);
              for (var i = 0; i < 30; i++) {
                cm.replaceSelection("x\n");
                var cursorBottom = cm.cursorCoords(null, "window").bottom;
                is(cursorBottom <= bottom);
              }
              is(cursorBottom >= bottom - 5);
            }
          
            testCM("movedown_fixed", function(cm) {testMovedownFixed(cm, false);});
            testCM("movedown_hscroll_fixed", function(cm) {testMovedownFixed(cm, true);});
          
            function testMovedownResize(cm, hScroll) {
              cm.getWrapperElement().style.height = "auto";
              if (hScroll) cm.setValue(new Array(100).join("x"));
              cm.refresh();
              for (var i = 0; i < 30; i++) {
                cm.replaceSelection("x\n");
                var bottom = displayBottom(cm, hScroll);
                var cursorBottom = cm.cursorCoords(null, "window").bottom;
                is(cursorBottom <= bottom);
                is(cursorBottom >= bottom - 5);
              }
            }
          
            testCM("movedown_resize", function(cm) {testMovedownResize(cm, false);});
            testCM("movedown_hscroll_resize", function(cm) {testMovedownResize(cm, true);});
          
            function testMoveright(cm, wrap, scroll) {
              cm.setSize("100px", "100px");
              if (wrap) cm.setOption("lineWrapping", true);
              if (scroll) {
                cm.setValue("\n" + new Array(100).join("x\n"));
                cm.setCursor(Pos(0, 0));
              }
              var right = displayRight(cm, scroll);
              for (var i = 0; i < 10; i++) {
                cm.replaceSelection("xxxxxxxxxx");
                var cursorRight = cm.cursorCoords(null, "window").right;
                is(cursorRight < right);
              }
              if (!wrap) is(cursorRight > right - 20);
            }
          
            testCM("moveright", function(cm) {testMoveright(cm, false, false);});
            testCM("moveright_wrap", function(cm) {testMoveright(cm, true, false);});
            testCM("moveright_scroll", function(cm) {testMoveright(cm, false, true);});
            testCM("moveright_scroll_wrap", function(cm) {testMoveright(cm, true, true);});
          
            testCM("suddenly_wide", function(cm) {
              addDoc(cm, 100, 100);
              cm.replaceSelection(new Array(600).join("l ") + "\n");
              cm.execCommand("goLineUp");
              cm.execCommand("goLineEnd");
              is(barH(cm).scrollLeft > cm.getScrollerElement().scrollLeft - 1);
            });
          
            testCM("wrap_changes_height", function(cm) {
              var line = new Array(20).join("a ") + "\n";
              cm.setValue(new Array(20).join(line));
              var box = cm.getWrapperElement().getBoundingClientRect();
              cm.setSize(cm.cursorCoords(Pos(0), "window").right - box.left + 2,
                         cm.cursorCoords(Pos(19, 0), "window").bottom - box.top + 2);
              cm.setCursor(Pos(19, 0));
              cm.replaceSelection("\n");
              is(cm.cursorCoords(null, "window").bottom < displayBottom(cm, false));
            }, {lineWrapping: true});
          })();
          
        • search_test.js
          (function() {
            "use strict";
          
            function test(name) {
              var text = Array.prototype.slice.call(arguments, 1, arguments.length - 1).join("\n");
              var body = arguments[arguments.length - 1];
              return window.test("search_" + name, function() {
                body(new CodeMirror.Doc(text));
              });
            }
          
            function run(doc, query, insensitive) {
              var cursor = doc.getSearchCursor(query, null, insensitive);
              for (var i = 3; i < arguments.length; i += 4) {
                var found = cursor.findNext();
                is(found, "not enough results (forward)");
                eqPos(Pos(arguments[i], arguments[i + 1]), cursor.from(), "from, forward, " + (i - 3) / 4);
                eqPos(Pos(arguments[i + 2], arguments[i + 3]), cursor.to(), "to, forward, " + (i - 3) / 4);
              }
              is(!cursor.findNext(), "too many matches (forward)");
              for (var i = arguments.length - 4; i >= 3; i -= 4) {
                var found = cursor.findPrevious();
                is(found, "not enough results (backwards)");
                eqPos(Pos(arguments[i], arguments[i + 1]), cursor.from(), "from, backwards, " + (i - 3) / 4);
                eqPos(Pos(arguments[i + 2], arguments[i + 3]), cursor.to(), "to, backwards, " + (i - 3) / 4);
              }
              is(!cursor.findPrevious(), "too many matches (backwards)");
            }
          
            test("simple", "abcdefg", "abcdefg", function(doc) {
              run(doc, "cde", false, 0, 2, 0, 5, 1, 2, 1, 5);
            });
          
            test("multiline", "hallo", "goodbye", function(doc) {
              run(doc, "llo\ngoo", false, 0, 2, 1, 3);
              run(doc, "blah\nhall", false);
              run(doc, "bye\neye", false);
            });
          
            test("regexp", "abcde", "abcde", function(doc) {
              run(doc, /bcd/, false, 0, 1, 0, 4, 1, 1, 1, 4);
              run(doc, /BCD/, false);
              run(doc, /BCD/i, false, 0, 1, 0, 4, 1, 1, 1, 4);
            });
          
            test("insensitive", "hallo", "HALLO", "oink", "hAllO", function(doc) {
              run(doc, "All", false, 3, 1, 3, 4);
              run(doc, "All", true, 0, 1, 0, 4, 1, 1, 1, 4, 3, 1, 3, 4);
            });
          
            test("multilineInsensitive", "zie ginds komT", "De Stoomboot", "uit Spanje weer aan", function(doc) {
              run(doc, "komt\nde stoomboot\nuit", false);
              run(doc, "komt\nde stoomboot\nuit", true, 0, 10, 2, 3);
              run(doc, "kOMt\ndE stOOmboot\nuiT", true, 0, 10, 2, 3);
            });
          
            test("expandingCaseFold", "<b>İİ İİ</b>", "<b>uu uu</b>", function(doc) {
              if (phantom) return; // A Phantom bug makes this hang
              run(doc, "</b>", true, 0, 8, 0, 12, 1, 8, 1, 12);
              run(doc, "İİ", true, 0, 3, 0, 5, 0, 6, 0, 8);
            });
          })();
          
        • sql-hint-test.js
          // CodeMirror, copyright (c) by Marijn Haverbeke and others
          // Distributed under an MIT license: http://codemirror.net/LICENSE
          
          (function() {
            var Pos = CodeMirror.Pos;
          
            var simpleTables = {
              "users": ["name", "score", "birthDate"],
              "xcountries": ["name", "population", "size"]
            };
          
            var schemaTables = {
              "schema.users": ["name", "score", "birthDate"],
              "schema.countries": ["name", "population", "size"]
            };
          
            var displayTextTables = [{
              text: "mytable",
              displayText: "mytable | The main table",
              columns: [{text: "id", displayText: "id | Unique ID"},
                        {text: "name", displayText: "name | The name"}]
            }];
          
            namespace = "sql-hint_";
          
            function test(name, spec) {
              testCM(name, function(cm) {
                cm.setValue(spec.value);
                cm.setCursor(spec.cursor);
                var completion = CodeMirror.hint.sql(cm, {tables: spec.tables});
                if (!deepCompare(completion.list, spec.list))
                  throw new Failure("Wrong completion results " + JSON.stringify(completion.list) + " vs " + JSON.stringify(spec.list));
                eqPos(completion.from, spec.from);
                eqPos(completion.to, spec.to);
              }, {
                value: spec.value,
                mode: "text/x-mysql"
              });
            }
          
            test("keywords", {
              value: "SEL",
              cursor: Pos(0, 3),
              list: ["SELECT"],
              from: Pos(0, 0),
              to: Pos(0, 3)
            });
          
            test("from", {
              value: "SELECT * fr",
              cursor: Pos(0, 11),
              list: ["FROM"],
              from: Pos(0, 9),
              to: Pos(0, 11)
            });
          
            test("table", {
              value: "SELECT xc",
              cursor: Pos(0, 9),
              tables: simpleTables,
              list: ["xcountries"],
              from: Pos(0, 7),
              to: Pos(0, 9)
            });
          
            test("columns", {
              value: "SELECT users.",
              cursor: Pos(0, 13),
              tables: simpleTables,
              list: ["users.name", "users.score", "users.birthDate"],
              from: Pos(0, 7),
              to: Pos(0, 13)
            });
          
            test("singlecolumn", {
              value: "SELECT users.na",
              cursor: Pos(0, 15),
              tables: simpleTables,
              list: ["users.name"],
              from: Pos(0, 7),
              to: Pos(0, 15)
            });
          
            test("quoted", {
              value: "SELECT `users`.`na",
              cursor: Pos(0, 18),
              tables: simpleTables,
              list: ["`users`.`name`"],
              from: Pos(0, 7),
              to: Pos(0, 18)
            });
          
            test("quotedcolumn", {
              value: "SELECT users.`na",
              cursor: Pos(0, 16),
              tables: simpleTables,
              list: ["`users`.`name`"],
              from: Pos(0, 7),
              to: Pos(0, 16)
            });
          
            test("schema", {
              value: "SELECT schem",
              cursor: Pos(0, 12),
              tables: schemaTables,
              list: ["schema.users", "schema.countries",
                     "SCHEMA", "SCHEMA_NAME", "SCHEMAS"],
              from: Pos(0, 7),
              to: Pos(0, 12)
            });
          
            test("schemaquoted", {
              value: "SELECT `sch",
              cursor: Pos(0, 11),
              tables: schemaTables,
              list: ["`schema`.`users`", "`schema`.`countries`"],
              from: Pos(0, 7),
              to: Pos(0, 11)
            });
          
            test("schemacolumn", {
              value: "SELECT schema.users.",
              cursor: Pos(0, 20),
              tables: schemaTables,
              list: ["schema.users.name",
                     "schema.users.score",
                     "schema.users.birthDate"],
              from: Pos(0, 7),
              to: Pos(0, 20)
            });
          
            test("schemacolumnquoted", {
              value: "SELECT `schema`.`users`.",
              cursor: Pos(0, 24),
              tables: schemaTables,
              list: ["`schema`.`users`.`name`",
                     "`schema`.`users`.`score`",
                     "`schema`.`users`.`birthDate`"],
              from: Pos(0, 7),
              to: Pos(0, 24)
            });
          
            test("displayText_table", {
              value: "SELECT myt",
              cursor: Pos(0, 10),
              tables: displayTextTables,
              list: displayTextTables,
              from: Pos(0, 7),
              to: Pos(0, 10)
            });
          
            test("displayText_column", {
              value: "SELECT mytable.",
              cursor: Pos(0, 15),
              tables: displayTextTables,
              list: [{text: "mytable.id", displayText: "id | Unique ID"},
                     {text: "mytable.name", displayText: "name | The name"}],
              from: Pos(0, 7),
              to: Pos(0, 15)
            });
          
            test("alias_complete", {
              value: "SELECT t. FROM users t",
              cursor: Pos(0, 9),
              tables: simpleTables,
              list: ["t.name", "t.score", "t.birthDate"],
              from: Pos(0, 7),
              to: Pos(0, 9)
            });
          
            function deepCompare(a, b) {
              if (!a || typeof a != "object")
                return a === b;
              if (!b || typeof b != "object")
                return false;
              for (var prop in a) if (!deepCompare(a[prop], b[prop])) return false;
              return true;
            }
          })();
          
        • sublime_test.js
          (function() {
            "use strict";
            
            var Pos = CodeMirror.Pos;
            namespace = "sublime_";
          
            function stTest(name) {
              var actions = Array.prototype.slice.call(arguments, 1);
              testCM(name, function(cm) {
                for (var i = 0; i < actions.length; i++) {
                  var action = actions[i];
                  if (typeof action == "string" && i == 0)
                    cm.setValue(action);
                  else if (typeof action == "string")
                    cm.execCommand(action);
                  else if (action instanceof Pos)
                    cm.setCursor(action);
                  else
                    action(cm);
                }
              });
            }
          
            function at(line, ch, msg) {
              return function(cm) {
                eq(cm.listSelections().length, 1);
                eqPos(cm.getCursor("head"), Pos(line, ch), msg);
                eqPos(cm.getCursor("anchor"), Pos(line, ch), msg);
              };
            }
          
            function val(content, msg) {
              return function(cm) { eq(cm.getValue(), content, msg); };
            }
          
            function argsToRanges(args) {
              if (args.length % 4) throw new Error("Wrong number of arguments for ranges.");
              var ranges = [];
              for (var i = 0; i < args.length; i += 4)
                ranges.push({anchor: Pos(args[i], args[i + 1]),
                             head: Pos(args[i + 2], args[i + 3])});
              return ranges;
            }
          
            function setSel() {
              var ranges = argsToRanges(arguments);
              return function(cm) { cm.setSelections(ranges, 0); };
            }
          
            function hasSel() {
              var ranges = argsToRanges(arguments);
              return function(cm) {
                var sels = cm.listSelections();
                if (sels.length != ranges.length)
                  throw new Failure("Expected " + ranges.length + " selections, but found " + sels.length);
                for (var i = 0; i < sels.length; i++) {
                  eqPos(sels[i].anchor, ranges[i].anchor, "anchor " + i);
                  eqPos(sels[i].head, ranges[i].head, "head " + i);
                }
              };
            }
          
            stTest("bySubword", "the foo_bar DooDahBah \n a",
                   "goSubwordLeft", at(0, 0),
                   "goSubwordRight", at(0, 3),
                   "goSubwordRight", at(0, 7),
                   "goSubwordRight", at(0, 11),
                   "goSubwordRight", at(0, 15),
                   "goSubwordRight", at(0, 18),
                   "goSubwordRight", at(0, 21),
                   "goSubwordRight", at(0, 22),
                   "goSubwordRight", at(1, 0),
                   "goSubwordRight", at(1, 2),
                   "goSubwordRight", at(1, 2),
                   "goSubwordLeft", at(1, 1),
                   "goSubwordLeft", at(1, 0),
                   "goSubwordLeft", at(0, 22),
                   "goSubwordLeft", at(0, 18),
                   "goSubwordLeft", at(0, 15),
                   "goSubwordLeft", at(0, 12),
                   "goSubwordLeft", at(0, 8),
                   "goSubwordLeft", at(0, 4),
                   "goSubwordLeft", at(0, 0));
          
            stTest("splitSelectionByLine", "abc\ndef\nghi",
                   setSel(0, 1, 2, 2),
                   "splitSelectionByLine",
                   hasSel(0, 1, 0, 3,
                          1, 0, 1, 3,
                          2, 0, 2, 2));
          
            stTest("splitSelectionByLineMulti", "abc\ndef\nghi\njkl",
                   setSel(0, 1, 1, 1,
                          1, 2, 3, 2,
                          3, 3, 3, 3),
                   "splitSelectionByLine",
                   hasSel(0, 1, 0, 3,
                          1, 0, 1, 1,
                          1, 2, 1, 3,
                          2, 0, 2, 3,
                          3, 0, 3, 2,
                          3, 3, 3, 3));
          
            stTest("selectLine", "abc\ndef\nghi",
                   setSel(0, 1, 0, 1,
                          2, 0, 2, 1),
                   "selectLine",
                   hasSel(0, 0, 1, 0,
                          2, 0, 2, 3),
                   setSel(0, 1, 1, 0),
                   "selectLine",
                   hasSel(0, 0, 2, 0));
          
            stTest("insertLineAfter", "abcde\nfghijkl\nmn",
                   setSel(0, 1, 0, 1,
                          0, 3, 0, 3,
                          1, 2, 1, 2,
                          1, 3, 1, 5), "insertLineAfter",
                   hasSel(1, 0, 1, 0,
                          3, 0, 3, 0), val("abcde\n\nfghijkl\n\nmn"));
          
            stTest("insertLineBefore", "abcde\nfghijkl\nmn",
                   setSel(0, 1, 0, 1,
                          0, 3, 0, 3,
                          1, 2, 1, 2,
                          1, 3, 1, 5), "insertLineBefore",
                   hasSel(0, 0, 0, 0,
                          2, 0, 2, 0), val("\nabcde\n\nfghijkl\nmn"));
          
            stTest("selectNextOccurrence", "a foo bar\nfoobar foo",
                   setSel(0, 2, 0, 5),
                   "selectNextOccurrence", hasSel(0, 2, 0, 5,
                                                  1, 0, 1, 3),
                   "selectNextOccurrence", hasSel(0, 2, 0, 5,
                                                  1, 0, 1, 3,
                                                  1, 7, 1, 10),
                   "selectNextOccurrence", hasSel(0, 2, 0, 5,
                                                  1, 0, 1, 3,
                                                  1, 7, 1, 10),
                   Pos(0, 3), "selectNextOccurrence", hasSel(0, 2, 0, 5),
                  "selectNextOccurrence", hasSel(0, 2, 0, 5,
                                                 1, 7, 1, 10),
                   setSel(0, 6, 0, 9),
                   "selectNextOccurrence", hasSel(0, 6, 0, 9,
                                                  1, 3, 1, 6));
          
            stTest("selectScope", "foo(a) {\n  bar[1, 2];\n}",
                   "selectScope", hasSel(0, 0, 2, 1),
                   Pos(0, 4), "selectScope", hasSel(0, 4, 0, 5),
                   Pos(0, 5), "selectScope", hasSel(0, 4, 0, 5),
                   Pos(0, 6), "selectScope", hasSel(0, 0, 2, 1),
                   Pos(0, 8), "selectScope", hasSel(0, 8, 2, 0),
                   Pos(1, 2), "selectScope", hasSel(0, 8, 2, 0),
                   Pos(1, 6), "selectScope", hasSel(1, 6, 1, 10),
                   Pos(1, 9), "selectScope", hasSel(1, 6, 1, 10));
          
            stTest("goToBracket", "foo(a) {\n  bar[1, 2];\n}",
                   Pos(0, 0), "goToBracket", at(0, 0),
                   Pos(0, 4), "goToBracket", at(0, 5), "goToBracket", at(0, 4),
                   Pos(0, 8), "goToBracket", at(2, 0), "goToBracket", at(0, 8),
                   Pos(1, 2), "goToBracket", at(2, 0),
                   Pos(1, 7), "goToBracket", at(1, 10), "goToBracket", at(1, 6));
          
            stTest("swapLine", "1\n2\n3---\n4\n5",
                   "swapLineDown", val("2\n1\n3---\n4\n5"),
                   "swapLineUp", val("1\n2\n3---\n4\n5"),
                   "swapLineUp", val("1\n2\n3---\n4\n5"),
                   Pos(4, 1), "swapLineDown", val("1\n2\n3---\n4\n5"),
                   setSel(0, 1, 0, 1,
                          1, 0, 2, 0,
                          2, 2, 2, 2),
                   "swapLineDown", val("4\n1\n2\n3---\n5"),
                   hasSel(1, 1, 1, 1,
                          2, 0, 3, 0,
                          3, 2, 3, 2),
                   "swapLineUp", val("1\n2\n3---\n4\n5"),
                   hasSel(0, 1, 0, 1,
                          1, 0, 2, 0,
                          2, 2, 2, 2));
          
            stTest("swapLineEmptyBottomSel", "1\n2\n3",
                   setSel(0, 1, 1, 0),
                   "swapLineDown", val("2\n1\n3"), hasSel(1, 1, 2, 0),
                   "swapLineUp", val("1\n2\n3"), hasSel(0, 1, 1, 0),
                   "swapLineUp", val("1\n2\n3"), hasSel(0, 0, 0, 0));
          
            stTest("swapLineUpFromEnd", "a\nb\nc",
                   Pos(2, 1), "swapLineUp",
                   hasSel(1, 1, 1, 1), val("a\nc\nb"));
          
            stTest("joinLines", "abc\ndef\nghi\njkl",
                   "joinLines", val("abc def\nghi\njkl"), at(0, 4),
                   "undo",
                   setSel(0, 2, 1, 1), "joinLines",
                   val("abc def ghi\njkl"), hasSel(0, 2, 0, 8),
                   "undo",
                   setSel(0, 1, 0, 1,
                          1, 1, 1, 1,
                          3, 1, 3, 1), "joinLines",
                   val("abc def ghi\njkl"), hasSel(0, 4, 0, 4,
                                                   0, 8, 0, 8,
                                                   1, 3, 1, 3));
          
            stTest("duplicateLine", "abc\ndef\nghi",
                   Pos(1, 0), "duplicateLine", val("abc\ndef\ndef\nghi"), at(2, 0),
                   "undo",
                   setSel(0, 1, 0, 1,
                          1, 1, 1, 1,
                          2, 1, 2, 1), "duplicateLine",
                   val("abc\nabc\ndef\ndef\nghi\nghi"), hasSel(1, 1, 1, 1,
                                                               3, 1, 3, 1,
                                                               5, 1, 5, 1));
            stTest("duplicateLineSelection", "abcdef",
                   setSel(0, 1, 0, 1,
                          0, 2, 0, 4,
                          0, 5, 0, 5),
                   "duplicateLine",
                   val("abcdef\nabcdcdef\nabcdcdef"), hasSel(2, 1, 2, 1,
                                                             2, 4, 2, 6,
                                                             2, 7, 2, 7));
          
            stTest("selectLinesUpward", "123\n345\n789\n012",
                   setSel(0, 1, 0, 1,
                          1, 1, 1, 3,
                          2, 0, 2, 0,
                          3, 0, 3, 0),
                   "selectLinesUpward",
                   hasSel(0, 1, 0, 1,
                          0, 3, 0, 3,
                          1, 0, 1, 0,
                          1, 1, 1, 3,
                          2, 0, 2, 0,
                          3, 0, 3, 0));
          
            stTest("selectLinesDownward", "123\n345\n789\n012",
                   setSel(0, 1, 0, 1,
                          1, 1, 1, 3,
                          2, 0, 2, 0,
                          3, 0, 3, 0),
                   "selectLinesDownward",
                   hasSel(0, 1, 0, 1,
                          1, 1, 1, 3,
                          2, 0, 2, 0,
                          2, 3, 2, 3,
                          3, 0, 3, 0));
          
            stTest("sortLines", "c\nb\na\nC\nB\nA",
                   "sortLines", val("A\nB\nC\na\nb\nc"),
                   "undo",
                   setSel(0, 0, 2, 0,
                          3, 0, 5, 0),
                   "sortLines", val("a\nb\nc\nA\nB\nC"),
                   hasSel(0, 0, 2, 1,
                          3, 0, 5, 1),
                   "undo",
                   setSel(1, 0, 4, 0), "sortLinesInsensitive", val("c\na\nB\nb\nC\nA"));
          
            stTest("bookmarks", "abc\ndef\nghi\njkl",
                   Pos(0, 1), "toggleBookmark",
                   setSel(1, 1, 1, 2), "toggleBookmark",
                   setSel(2, 1, 2, 2), "toggleBookmark",
                   "nextBookmark", hasSel(0, 1, 0, 1),
                   "nextBookmark", hasSel(1, 1, 1, 2),
                   "nextBookmark", hasSel(2, 1, 2, 2),
                   "prevBookmark", hasSel(1, 1, 1, 2),
                   "prevBookmark", hasSel(0, 1, 0, 1),
                   "prevBookmark", hasSel(2, 1, 2, 2),
                   "prevBookmark", hasSel(1, 1, 1, 2),
                   "toggleBookmark",
                   "prevBookmark", hasSel(2, 1, 2, 2),
                   "prevBookmark", hasSel(0, 1, 0, 1),
                   "selectBookmarks", hasSel(0, 1, 0, 1,
                                             2, 1, 2, 2),
                   "clearBookmarks",
                   Pos(0, 0), "selectBookmarks", at(0, 0));
          
            stTest("upAndDowncaseAtCursor", "abc\ndef  x\nghI",
                   setSel(0, 1, 0, 3,
                          1, 1, 1, 1,
                          1, 4, 1, 4), "upcaseAtCursor",
                   val("aBC\nDEF  x\nghI"), hasSel(0, 1, 0, 3,
                                                   1, 3, 1, 3,
                                                   1, 4, 1, 4),
                   "downcaseAtCursor",
                   val("abc\ndef  x\nghI"), hasSel(0, 1, 0, 3,
                                                   1, 3, 1, 3,
                                                   1, 4, 1, 4));
          
            stTest("mark", "abc\ndef\nghi",
                   Pos(1, 1), "setSublimeMark",
                   Pos(2, 1), "selectToSublimeMark", hasSel(2, 1, 1, 1),
                   Pos(0, 1), "swapWithSublimeMark", at(1, 1), "swapWithSublimeMark", at(0, 1),
                   "deleteToSublimeMark", val("aef\nghi"),
                   "sublimeYank", val("abc\ndef\nghi"), at(1, 1));
          
            stTest("findUnder", "foo foobar  a",
                   "findUnder", hasSel(0, 4, 0, 7),
                   "findUnder", hasSel(0, 0, 0, 3),
                   "findUnderPrevious", hasSel(0, 4, 0, 7),
                   "findUnderPrevious", hasSel(0, 0, 0, 3),
                   Pos(0, 4), "findUnder", hasSel(0, 4, 0, 10),
                   Pos(0, 11), "findUnder", hasSel(0, 11, 0, 11));
          })();
          
        • test.js
          var Pos = CodeMirror.Pos;
          
          CodeMirror.defaults.rtlMoveVisually = true;
          
          function forEach(arr, f) {
            for (var i = 0, e = arr.length; i < e; ++i) f(arr[i], i);
          }
          
          function addDoc(cm, width, height) {
            var content = [], line = "";
            for (var i = 0; i < width; ++i) line += "x";
            for (var i = 0; i < height; ++i) content.push(line);
            cm.setValue(content.join("\n"));
          }
          
          function byClassName(elt, cls) {
            if (elt.getElementsByClassName) return elt.getElementsByClassName(cls);
            var found = [], re = new RegExp("\\b" + cls + "\\b");
            function search(elt) {
              if (elt.nodeType == 3) return;
              if (re.test(elt.className)) found.push(elt);
              for (var i = 0, e = elt.childNodes.length; i < e; ++i)
                search(elt.childNodes[i]);
            }
            search(elt);
            return found;
          }
          
          var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
          var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
          var mac = /Mac/.test(navigator.platform);
          var phantom = /PhantomJS/.test(navigator.userAgent);
          var opera = /Opera\/\./.test(navigator.userAgent);
          var opera_version = opera && navigator.userAgent.match(/Version\/(\d+\.\d+)/);
          if (opera_version) opera_version = Number(opera_version);
          var opera_lt10 = opera && (!opera_version || opera_version < 10);
          
          namespace = "core_";
          
          test("core_fromTextArea", function() {
            var te = document.getElementById("code");
            te.value = "CONTENT";
            var cm = CodeMirror.fromTextArea(te);
            is(!te.offsetHeight);
            eq(cm.getValue(), "CONTENT");
            cm.setValue("foo\nbar");
            eq(cm.getValue(), "foo\nbar");
            cm.save();
            is(/^foo\r?\nbar$/.test(te.value));
            cm.setValue("xxx");
            cm.toTextArea();
            is(te.offsetHeight);
            eq(te.value, "xxx");
          });
          
          testCM("getRange", function(cm) {
            eq(cm.getLine(0), "1234");
            eq(cm.getLine(1), "5678");
            eq(cm.getLine(2), null);
            eq(cm.getLine(-1), null);
            eq(cm.getRange(Pos(0, 0), Pos(0, 3)), "123");
            eq(cm.getRange(Pos(0, -1), Pos(0, 200)), "1234");
            eq(cm.getRange(Pos(0, 2), Pos(1, 2)), "34\n56");
            eq(cm.getRange(Pos(1, 2), Pos(100, 0)), "78");
          }, {value: "1234\n5678"});
          
          testCM("replaceRange", function(cm) {
            eq(cm.getValue(), "");
            cm.replaceRange("foo\n", Pos(0, 0));
            eq(cm.getValue(), "foo\n");
            cm.replaceRange("a\nb", Pos(0, 1));
            eq(cm.getValue(), "fa\nboo\n");
            eq(cm.lineCount(), 3);
            cm.replaceRange("xyzzy", Pos(0, 0), Pos(1, 1));
            eq(cm.getValue(), "xyzzyoo\n");
            cm.replaceRange("abc", Pos(0, 0), Pos(10, 0));
            eq(cm.getValue(), "abc");
            eq(cm.lineCount(), 1);
          });
          
          testCM("selection", function(cm) {
            cm.setSelection(Pos(0, 4), Pos(2, 2));
            is(cm.somethingSelected());
            eq(cm.getSelection(), "11\n222222\n33");
            eqPos(cm.getCursor(false), Pos(2, 2));
            eqPos(cm.getCursor(true), Pos(0, 4));
            cm.setSelection(Pos(1, 0));
            is(!cm.somethingSelected());
            eq(cm.getSelection(), "");
            eqPos(cm.getCursor(true), Pos(1, 0));
            cm.replaceSelection("abc", "around");
            eq(cm.getSelection(), "abc");
            eq(cm.getValue(), "111111\nabc222222\n333333");
            cm.replaceSelection("def", "end");
            eq(cm.getSelection(), "");
            eqPos(cm.getCursor(true), Pos(1, 3));
            cm.setCursor(Pos(2, 1));
            eqPos(cm.getCursor(true), Pos(2, 1));
            cm.setCursor(1, 2);
            eqPos(cm.getCursor(true), Pos(1, 2));
          }, {value: "111111\n222222\n333333"});
          
          testCM("extendSelection", function(cm) {
            cm.setExtending(true);
            addDoc(cm, 10, 10);
            cm.setSelection(Pos(3, 5));
            eqPos(cm.getCursor("head"), Pos(3, 5));
            eqPos(cm.getCursor("anchor"), Pos(3, 5));
            cm.setSelection(Pos(2, 5), Pos(5, 5));
            eqPos(cm.getCursor("head"), Pos(5, 5));
            eqPos(cm.getCursor("anchor"), Pos(2, 5));
            eqPos(cm.getCursor("start"), Pos(2, 5));
            eqPos(cm.getCursor("end"), Pos(5, 5));
            cm.setSelection(Pos(5, 5), Pos(2, 5));
            eqPos(cm.getCursor("head"), Pos(2, 5));
            eqPos(cm.getCursor("anchor"), Pos(5, 5));
            eqPos(cm.getCursor("start"), Pos(2, 5));
            eqPos(cm.getCursor("end"), Pos(5, 5));
            cm.extendSelection(Pos(3, 2));
            eqPos(cm.getCursor("head"), Pos(3, 2));
            eqPos(cm.getCursor("anchor"), Pos(5, 5));
            cm.extendSelection(Pos(6, 2));
            eqPos(cm.getCursor("head"), Pos(6, 2));
            eqPos(cm.getCursor("anchor"), Pos(5, 5));
            cm.extendSelection(Pos(6, 3), Pos(6, 4));
            eqPos(cm.getCursor("head"), Pos(6, 4));
            eqPos(cm.getCursor("anchor"), Pos(5, 5));
            cm.extendSelection(Pos(0, 3), Pos(0, 4));
            eqPos(cm.getCursor("head"), Pos(0, 3));
            eqPos(cm.getCursor("anchor"), Pos(5, 5));
            cm.extendSelection(Pos(4, 5), Pos(6, 5));
            eqPos(cm.getCursor("head"), Pos(6, 5));
            eqPos(cm.getCursor("anchor"), Pos(4, 5));
            cm.setExtending(false);
            cm.extendSelection(Pos(0, 3), Pos(0, 4));
            eqPos(cm.getCursor("head"), Pos(0, 3));
            eqPos(cm.getCursor("anchor"), Pos(0, 4));
          });
          
          testCM("lines", function(cm) {
            eq(cm.getLine(0), "111111");
            eq(cm.getLine(1), "222222");
            eq(cm.getLine(-1), null);
            cm.replaceRange("", Pos(1, 0), Pos(2, 0))
            cm.replaceRange("abc", Pos(1, 0), Pos(1));
            eq(cm.getValue(), "111111\nabc");
          }, {value: "111111\n222222\n333333"});
          
          testCM("indent", function(cm) {
            cm.indentLine(1);
            eq(cm.getLine(1), "   blah();");
            cm.setOption("indentUnit", 8);
            cm.indentLine(1);
            eq(cm.getLine(1), "\tblah();");
            cm.setOption("indentUnit", 10);
            cm.setOption("tabSize", 4);
            cm.indentLine(1);
            eq(cm.getLine(1), "\t\t  blah();");
          }, {value: "if (x) {\nblah();\n}", indentUnit: 3, indentWithTabs: true, tabSize: 8});
          
          testCM("indentByNumber", function(cm) {
            cm.indentLine(0, 2);
            eq(cm.getLine(0), "  foo");
            cm.indentLine(0, -200);
            eq(cm.getLine(0), "foo");
            cm.setSelection(Pos(0, 0), Pos(1, 2));
            cm.indentSelection(3);
            eq(cm.getValue(), "   foo\n   bar\nbaz");
          }, {value: "foo\nbar\nbaz"});
          
          test("core_defaults", function() {
            var defsCopy = {}, defs = CodeMirror.defaults;
            for (var opt in defs) defsCopy[opt] = defs[opt];
            defs.indentUnit = 5;
            defs.value = "uu";
            defs.indentWithTabs = true;
            defs.tabindex = 55;
            var place = document.getElementById("testground"), cm = CodeMirror(place);
            try {
              eq(cm.getOption("indentUnit"), 5);
              cm.setOption("indentUnit", 10);
              eq(defs.indentUnit, 5);
              eq(cm.getValue(), "uu");
              eq(cm.getOption("indentWithTabs"), true);
              eq(cm.getInputField().tabIndex, 55);
            }
            finally {
              for (var opt in defsCopy) defs[opt] = defsCopy[opt];
              place.removeChild(cm.getWrapperElement());
            }
          });
          
          testCM("lineInfo", function(cm) {
            eq(cm.lineInfo(-1), null);
            var mark = document.createElement("span");
            var lh = cm.setGutterMarker(1, "FOO", mark);
            var info = cm.lineInfo(1);
            eq(info.text, "222222");
            eq(info.gutterMarkers.FOO, mark);
            eq(info.line, 1);
            eq(cm.lineInfo(2).gutterMarkers, null);
            cm.setGutterMarker(lh, "FOO", null);
            eq(cm.lineInfo(1).gutterMarkers, null);
            cm.setGutterMarker(1, "FOO", mark);
            cm.setGutterMarker(0, "FOO", mark);
            cm.clearGutter("FOO");
            eq(cm.lineInfo(0).gutterMarkers, null);
            eq(cm.lineInfo(1).gutterMarkers, null);
          }, {value: "111111\n222222\n333333"});
          
          testCM("coords", function(cm) {
            cm.setSize(null, 100);
            addDoc(cm, 32, 200);
            var top = cm.charCoords(Pos(0, 0));
            var bot = cm.charCoords(Pos(200, 30));
            is(top.left < bot.left);
            is(top.top < bot.top);
            is(top.top < top.bottom);
            cm.scrollTo(null, 100);
            var top2 = cm.charCoords(Pos(0, 0));
            is(top.top > top2.top);
            eq(top.left, top2.left);
          });
          
          testCM("coordsChar", function(cm) {
            addDoc(cm, 35, 70);
            for (var i = 0; i < 2; ++i) {
              var sys = i ? "local" : "page";
              for (var ch = 0; ch <= 35; ch += 5) {
                for (var line = 0; line < 70; line += 5) {
                  cm.setCursor(line, ch);
                  var coords = cm.charCoords(Pos(line, ch), sys);
                  var pos = cm.coordsChar({left: coords.left + 1, top: coords.top + 1}, sys);
                  eqPos(pos, Pos(line, ch));
                }
              }
            }
          }, {lineNumbers: true});
          
          testCM("posFromIndex", function(cm) {
            cm.setValue(
              "This function should\n" +
              "convert a zero based index\n" +
              "to line and ch."
            );
          
            var examples = [
              { index: -1, line: 0, ch: 0  }, // <- Tests clipping
              { index: 0,  line: 0, ch: 0  },
              { index: 10, line: 0, ch: 10 },
              { index: 39, line: 1, ch: 18 },
              { index: 55, line: 2, ch: 7  },
              { index: 63, line: 2, ch: 15 },
              { index: 64, line: 2, ch: 15 }  // <- Tests clipping
            ];
          
            for (var i = 0; i < examples.length; i++) {
              var example = examples[i];
              var pos = cm.posFromIndex(example.index);
              eq(pos.line, example.line);
              eq(pos.ch, example.ch);
              if (example.index >= 0 && example.index < 64)
                eq(cm.indexFromPos(pos), example.index);
            }
          });
          
          testCM("undo", function(cm) {
            cm.replaceRange("def", Pos(0, 0), Pos(0));
            eq(cm.historySize().undo, 1);
            cm.undo();
            eq(cm.getValue(), "abc");
            eq(cm.historySize().undo, 0);
            eq(cm.historySize().redo, 1);
            cm.redo();
            eq(cm.getValue(), "def");
            eq(cm.historySize().undo, 1);
            eq(cm.historySize().redo, 0);
            cm.setValue("1\n\n\n2");
            cm.clearHistory();
            eq(cm.historySize().undo, 0);
            for (var i = 0; i < 20; ++i) {
              cm.replaceRange("a", Pos(0, 0));
              cm.replaceRange("b", Pos(3, 0));
            }
            eq(cm.historySize().undo, 40);
            for (var i = 0; i < 40; ++i)
              cm.undo();
            eq(cm.historySize().redo, 40);
            eq(cm.getValue(), "1\n\n\n2");
          }, {value: "abc"});
          
          testCM("undoDepth", function(cm) {
            cm.replaceRange("d", Pos(0));
            cm.replaceRange("e", Pos(0));
            cm.replaceRange("f", Pos(0));
            cm.undo(); cm.undo(); cm.undo();
            eq(cm.getValue(), "abcd");
          }, {value: "abc", undoDepth: 4});
          
          testCM("undoDoesntClearValue", function(cm) {
            cm.undo();
            eq(cm.getValue(), "x");
          }, {value: "x"});
          
          testCM("undoMultiLine", function(cm) {
            cm.operation(function() {
              cm.replaceRange("x", Pos(0, 0));
              cm.replaceRange("y", Pos(1, 0));
            });
            cm.undo();
            eq(cm.getValue(), "abc\ndef\nghi");
            cm.operation(function() {
              cm.replaceRange("y", Pos(1, 0));
              cm.replaceRange("x", Pos(0, 0));
            });
            cm.undo();
            eq(cm.getValue(), "abc\ndef\nghi");
            cm.operation(function() {
              cm.replaceRange("y", Pos(2, 0));
              cm.replaceRange("x", Pos(1, 0));
              cm.replaceRange("z", Pos(2, 0));
            });
            cm.undo();
            eq(cm.getValue(), "abc\ndef\nghi", 3);
          }, {value: "abc\ndef\nghi"});
          
          testCM("undoComposite", function(cm) {
            cm.replaceRange("y", Pos(1));
            cm.operation(function() {
              cm.replaceRange("x", Pos(0));
              cm.replaceRange("z", Pos(2));
            });
            eq(cm.getValue(), "ax\nby\ncz\n");
            cm.undo();
            eq(cm.getValue(), "a\nby\nc\n");
            cm.undo();
            eq(cm.getValue(), "a\nb\nc\n");
            cm.redo(); cm.redo();
            eq(cm.getValue(), "ax\nby\ncz\n");
          }, {value: "a\nb\nc\n"});
          
          testCM("undoSelection", function(cm) {
            cm.setSelection(Pos(0, 2), Pos(0, 4));
            cm.replaceSelection("");
            cm.setCursor(Pos(1, 0));
            cm.undo();
            eqPos(cm.getCursor(true), Pos(0, 2));
            eqPos(cm.getCursor(false), Pos(0, 4));
            cm.setCursor(Pos(1, 0));
            cm.redo();
            eqPos(cm.getCursor(true), Pos(0, 2));
            eqPos(cm.getCursor(false), Pos(0, 2));
          }, {value: "abcdefgh\n"});
          
          testCM("undoSelectionAsBefore", function(cm) {
            cm.replaceSelection("abc", "around");
            cm.undo();
            cm.redo();
            eq(cm.getSelection(), "abc");
          });
          
          testCM("selectionChangeConfusesHistory", function(cm) {
            cm.replaceSelection("abc", null, "dontmerge");
            cm.operation(function() {
              cm.setCursor(Pos(0, 0));
              cm.replaceSelection("abc", null, "dontmerge");
            });
            eq(cm.historySize().undo, 2);
          });
          
          testCM("markTextSingleLine", function(cm) {
            forEach([{a: 0, b: 1, c: "", f: 2, t: 5},
                     {a: 0, b: 4, c: "", f: 0, t: 2},
                     {a: 1, b: 2, c: "x", f: 3, t: 6},
                     {a: 4, b: 5, c: "", f: 3, t: 5},
                     {a: 4, b: 5, c: "xx", f: 3, t: 7},
                     {a: 2, b: 5, c: "", f: 2, t: 3},
                     {a: 2, b: 5, c: "abcd", f: 6, t: 7},
                     {a: 2, b: 6, c: "x", f: null, t: null},
                     {a: 3, b: 6, c: "", f: null, t: null},
                     {a: 0, b: 9, c: "hallo", f: null, t: null},
                     {a: 4, b: 6, c: "x", f: 3, t: 4},
                     {a: 4, b: 8, c: "", f: 3, t: 4},
                     {a: 6, b: 6, c: "a", f: 3, t: 6},
                     {a: 8, b: 9, c: "", f: 3, t: 6}], function(test) {
              cm.setValue("1234567890");
              var r = cm.markText(Pos(0, 3), Pos(0, 6), {className: "foo"});
              cm.replaceRange(test.c, Pos(0, test.a), Pos(0, test.b));
              var f = r.find();
              eq(f && f.from.ch, test.f); eq(f && f.to.ch, test.t);
            });
          });
          
          testCM("markTextMultiLine", function(cm) {
            function p(v) { return v && Pos(v[0], v[1]); }
            forEach([{a: [0, 0], b: [0, 5], c: "", f: [0, 0], t: [2, 5]},
                     {a: [0, 0], b: [0, 5], c: "foo\n", f: [1, 0], t: [3, 5]},
                     {a: [0, 1], b: [0, 10], c: "", f: [0, 1], t: [2, 5]},
                     {a: [0, 5], b: [0, 6], c: "x", f: [0, 6], t: [2, 5]},
                     {a: [0, 0], b: [1, 0], c: "", f: [0, 0], t: [1, 5]},
                     {a: [0, 6], b: [2, 4], c: "", f: [0, 5], t: [0, 7]},
                     {a: [0, 6], b: [2, 4], c: "aa", f: [0, 5], t: [0, 9]},
                     {a: [1, 2], b: [1, 8], c: "", f: [0, 5], t: [2, 5]},
                     {a: [0, 5], b: [2, 5], c: "xx", f: null, t: null},
                     {a: [0, 0], b: [2, 10], c: "x", f: null, t: null},
                     {a: [1, 5], b: [2, 5], c: "", f: [0, 5], t: [1, 5]},
                     {a: [2, 0], b: [2, 3], c: "", f: [0, 5], t: [2, 2]},
                     {a: [2, 5], b: [3, 0], c: "a\nb", f: [0, 5], t: [2, 5]},
                     {a: [2, 3], b: [3, 0], c: "x", f: [0, 5], t: [2, 3]},
                     {a: [1, 1], b: [1, 9], c: "1\n2\n3", f: [0, 5], t: [4, 5]}], function(test) {
              cm.setValue("aaaaaaaaaa\nbbbbbbbbbb\ncccccccccc\ndddddddd\n");
              var r = cm.markText(Pos(0, 5), Pos(2, 5),
                                  {className: "CodeMirror-matchingbracket"});
              cm.replaceRange(test.c, p(test.a), p(test.b));
              var f = r.find();
              eqPos(f && f.from, p(test.f)); eqPos(f && f.to, p(test.t));
            });
          });
          
          testCM("markTextUndo", function(cm) {
            var marker1, marker2, bookmark;
            marker1 = cm.markText(Pos(0, 1), Pos(0, 3),
                                  {className: "CodeMirror-matchingbracket"});
            marker2 = cm.markText(Pos(0, 0), Pos(2, 1),
                                  {className: "CodeMirror-matchingbracket"});
            bookmark = cm.setBookmark(Pos(1, 5));
            cm.operation(function(){
              cm.replaceRange("foo", Pos(0, 2));
              cm.replaceRange("bar\nbaz\nbug\n", Pos(2, 0), Pos(3, 0));
            });
            var v1 = cm.getValue();
            cm.setValue("");
            eq(marker1.find(), null); eq(marker2.find(), null); eq(bookmark.find(), null);
            cm.undo();
            eqPos(bookmark.find(), Pos(1, 5), "still there");
            cm.undo();
            var m1Pos = marker1.find(), m2Pos = marker2.find();
            eqPos(m1Pos.from, Pos(0, 1)); eqPos(m1Pos.to, Pos(0, 3));
            eqPos(m2Pos.from, Pos(0, 0)); eqPos(m2Pos.to, Pos(2, 1));
            eqPos(bookmark.find(), Pos(1, 5));
            cm.redo(); cm.redo();
            eq(bookmark.find(), null);
            cm.undo();
            eqPos(bookmark.find(), Pos(1, 5));
            eq(cm.getValue(), v1);
          }, {value: "1234\n56789\n00\n"});
          
          testCM("markTextStayGone", function(cm) {
            var m1 = cm.markText(Pos(0, 0), Pos(0, 1));
            cm.replaceRange("hi", Pos(0, 2));
            m1.clear();
            cm.undo();
            eq(m1.find(), null);
          }, {value: "hello"});
          
          testCM("markTextAllowEmpty", function(cm) {
            var m1 = cm.markText(Pos(0, 1), Pos(0, 2), {clearWhenEmpty: false});
            is(m1.find());
            cm.replaceRange("x", Pos(0, 0));
            is(m1.find());
            cm.replaceRange("y", Pos(0, 2));
            is(m1.find());
            cm.replaceRange("z", Pos(0, 3), Pos(0, 4));
            is(!m1.find());
            var m2 = cm.markText(Pos(0, 1), Pos(0, 2), {clearWhenEmpty: false,
                                                        inclusiveLeft: true,
                                                        inclusiveRight: true});
            cm.replaceRange("q", Pos(0, 1), Pos(0, 2));
            is(m2.find());
            cm.replaceRange("", Pos(0, 0), Pos(0, 3));
            is(!m2.find());
            var m3 = cm.markText(Pos(0, 1), Pos(0, 1), {clearWhenEmpty: false});
            cm.replaceRange("a", Pos(0, 3));
            is(m3.find());
            cm.replaceRange("b", Pos(0, 1));
            is(!m3.find());
          }, {value: "abcde"});
          
          testCM("markTextStacked", function(cm) {
            var m1 = cm.markText(Pos(0, 0), Pos(0, 0), {clearWhenEmpty: false});
            var m2 = cm.markText(Pos(0, 0), Pos(0, 0), {clearWhenEmpty: false});
            cm.replaceRange("B", Pos(0, 1));
            is(m1.find() && m2.find());
          }, {value: "A"});
          
          testCM("undoPreservesNewMarks", function(cm) {
            cm.markText(Pos(0, 3), Pos(0, 4));
            cm.markText(Pos(1, 1), Pos(1, 3));
            cm.replaceRange("", Pos(0, 3), Pos(3, 1));
            var mBefore = cm.markText(Pos(0, 0), Pos(0, 1));
            var mAfter = cm.markText(Pos(0, 5), Pos(0, 6));
            var mAround = cm.markText(Pos(0, 2), Pos(0, 4));
            cm.undo();
            eqPos(mBefore.find().from, Pos(0, 0));
            eqPos(mBefore.find().to, Pos(0, 1));
            eqPos(mAfter.find().from, Pos(3, 3));
            eqPos(mAfter.find().to, Pos(3, 4));
            eqPos(mAround.find().from, Pos(0, 2));
            eqPos(mAround.find().to, Pos(3, 2));
            var found = cm.findMarksAt(Pos(2, 2));
            eq(found.length, 1);
            eq(found[0], mAround);
          }, {value: "aaaa\nbbbb\ncccc\ndddd"});
          
          testCM("markClearBetween", function(cm) {
            cm.setValue("aaa\nbbb\nccc\nddd\n");
            cm.markText(Pos(0, 0), Pos(2));
            cm.replaceRange("aaa\nbbb\nccc", Pos(0, 0), Pos(2));
            eq(cm.findMarksAt(Pos(1, 1)).length, 0);
          });
          
          testCM("deleteSpanCollapsedInclusiveLeft", function(cm) {
            var from = Pos(1, 0), to = Pos(1, 1);
            var m = cm.markText(from, to, {collapsed: true, inclusiveLeft: true});
            // Delete collapsed span.
            cm.replaceRange("", from, to);
          }, {value: "abc\nX\ndef"});
          
          testCM("markTextCSS", function(cm) {
            function present() {
              var spans = cm.display.lineDiv.getElementsByTagName("span");
              for (var i = 0; i < spans.length; i++)
                if (spans[i].style.color == "cyan" && span[i].textContent == "cdefg") return true;
            }
            var m = cm.markText(Pos(0, 2), Pos(0, 6), {css: "color: cyan"});
            m.clear();
            is(!present());
          }, {value: "abcdefgh"});
          
          testCM("bookmark", function(cm) {
            function p(v) { return v && Pos(v[0], v[1]); }
            forEach([{a: [1, 0], b: [1, 1], c: "", d: [1, 4]},
                     {a: [1, 1], b: [1, 1], c: "xx", d: [1, 7]},
                     {a: [1, 4], b: [1, 5], c: "ab", d: [1, 6]},
                     {a: [1, 4], b: [1, 6], c: "", d: null},
                     {a: [1, 5], b: [1, 6], c: "abc", d: [1, 5]},
                     {a: [1, 6], b: [1, 8], c: "", d: [1, 5]},
                     {a: [1, 4], b: [1, 4], c: "\n\n", d: [3, 1]},
                     {bm: [1, 9], a: [1, 1], b: [1, 1], c: "\n", d: [2, 8]}], function(test) {
              cm.setValue("1234567890\n1234567890\n1234567890");
              var b = cm.setBookmark(p(test.bm) || Pos(1, 5));
              cm.replaceRange(test.c, p(test.a), p(test.b));
              eqPos(b.find(), p(test.d));
            });
          });
          
          testCM("bookmarkInsertLeft", function(cm) {
            var br = cm.setBookmark(Pos(0, 2), {insertLeft: false});
            var bl = cm.setBookmark(Pos(0, 2), {insertLeft: true});
            cm.setCursor(Pos(0, 2));
            cm.replaceSelection("hi");
            eqPos(br.find(), Pos(0, 2));
            eqPos(bl.find(), Pos(0, 4));
            cm.replaceRange("", Pos(0, 4), Pos(0, 5));
            cm.replaceRange("", Pos(0, 2), Pos(0, 4));
            cm.replaceRange("", Pos(0, 1), Pos(0, 2));
            // Verify that deleting next to bookmarks doesn't kill them
            eqPos(br.find(), Pos(0, 1));
            eqPos(bl.find(), Pos(0, 1));
          }, {value: "abcdef"});
          
          testCM("bookmarkCursor", function(cm) {
            var pos01 = cm.cursorCoords(Pos(0, 1)), pos11 = cm.cursorCoords(Pos(1, 1)),
                pos20 = cm.cursorCoords(Pos(2, 0)), pos30 = cm.cursorCoords(Pos(3, 0)),
                pos41 = cm.cursorCoords(Pos(4, 1));
            cm.setBookmark(Pos(0, 1), {widget: document.createTextNode("←"), insertLeft: true});
            cm.setBookmark(Pos(2, 0), {widget: document.createTextNode("←"), insertLeft: true});
            cm.setBookmark(Pos(1, 1), {widget: document.createTextNode("→")});
            cm.setBookmark(Pos(3, 0), {widget: document.createTextNode("→")});
            var new01 = cm.cursorCoords(Pos(0, 1)), new11 = cm.cursorCoords(Pos(1, 1)),
                new20 = cm.cursorCoords(Pos(2, 0)), new30 = cm.cursorCoords(Pos(3, 0));
            near(new01.left, pos01.left, 1);
            near(new01.top, pos01.top, 1);
            is(new11.left > pos11.left, "at right, middle of line");
            near(new11.top == pos11.top, 1);
            near(new20.left, pos20.left, 1);
            near(new20.top, pos20.top, 1);
            is(new30.left > pos30.left, "at right, empty line");
            near(new30.top, pos30, 1);
            cm.setBookmark(Pos(4, 0), {widget: document.createTextNode("→")});
            is(cm.cursorCoords(Pos(4, 1)).left > pos41.left, "single-char bug");
          }, {value: "foo\nbar\n\n\nx\ny"});
          
          testCM("multiBookmarkCursor", function(cm) {
            if (phantom) return;
            var ms = [], m;
            function add(insertLeft) {
              for (var i = 0; i < 3; ++i) {
                var node = document.createElement("span");
                node.innerHTML = "X";
                ms.push(cm.setBookmark(Pos(0, 1), {widget: node, insertLeft: insertLeft}));
              }
            }
            var base1 = cm.cursorCoords(Pos(0, 1)).left, base4 = cm.cursorCoords(Pos(0, 4)).left;
            add(true);
            near(base1, cm.cursorCoords(Pos(0, 1)).left, 1);
            while (m = ms.pop()) m.clear();
            add(false);
            near(base4, cm.cursorCoords(Pos(0, 1)).left, 1);
          }, {value: "abcdefg"});
          
          testCM("getAllMarks", function(cm) {
            addDoc(cm, 10, 10);
            var m1 = cm.setBookmark(Pos(0, 2));
            var m2 = cm.markText(Pos(0, 2), Pos(3, 2));
            var m3 = cm.markText(Pos(1, 2), Pos(1, 8));
            var m4 = cm.markText(Pos(8, 0), Pos(9, 0));
            eq(cm.getAllMarks().length, 4);
            m1.clear();
            m3.clear();
            eq(cm.getAllMarks().length, 2);
          });
          
          testCM("setValueClears", function(cm) {
            cm.addLineClass(0, "wrap", "foo");
            var mark = cm.markText(Pos(0, 0), Pos(1, 1), {inclusiveLeft: true, inclusiveRight: true});
            cm.setValue("foo");
            is(!cm.lineInfo(0).wrapClass);
            is(!mark.find());
          }, {value: "a\nb"});
          
          testCM("bug577", function(cm) {
            cm.setValue("a\nb");
            cm.clearHistory();
            cm.setValue("fooooo");
            cm.undo();
          });
          
          testCM("scrollSnap", function(cm) {
            cm.setSize(100, 100);
            addDoc(cm, 200, 200);
            cm.setCursor(Pos(100, 180));
            var info = cm.getScrollInfo();
            is(info.left > 0 && info.top > 0);
            cm.setCursor(Pos(0, 0));
            info = cm.getScrollInfo();
            is(info.left == 0 && info.top == 0, "scrolled clean to top");
            cm.setCursor(Pos(100, 180));
            cm.setCursor(Pos(199, 0));
            info = cm.getScrollInfo();
            is(info.left == 0 && info.top + 2 > info.height - cm.getScrollerElement().clientHeight, "scrolled clean to bottom");
          });
          
          testCM("scrollIntoView", function(cm) {
            if (phantom) return;
            var outer = cm.getWrapperElement().getBoundingClientRect();
            function test(line, ch, msg) {
              var pos = Pos(line, ch);
              cm.scrollIntoView(pos);
              var box = cm.charCoords(pos, "window");
              is(box.left >= outer.left, msg + " (left)");
              is(box.right <= outer.right, msg + " (right)");
              is(box.top >= outer.top, msg + " (top)");
              is(box.bottom <= outer.bottom, msg + " (bottom)");
            }
            addDoc(cm, 200, 200);
            test(199, 199, "bottom right");
            test(0, 0, "top left");
            test(100, 100, "center");
            test(199, 0, "bottom left");
            test(0, 199, "top right");
            test(100, 100, "center again");
          });
          
          testCM("scrollBackAndForth", function(cm) {
            addDoc(cm, 1, 200);
            cm.operation(function() {
              cm.scrollIntoView(Pos(199, 0));
              cm.scrollIntoView(Pos(4, 0));
            });
            is(cm.getScrollInfo().top > 0);
          });
          
          testCM("selectAllNoScroll", function(cm) {
            addDoc(cm, 1, 200);
            cm.execCommand("selectAll");
            eq(cm.getScrollInfo().top, 0);
            cm.setCursor(199);
            cm.execCommand("selectAll");
            is(cm.getScrollInfo().top > 0);
          });
          
          testCM("selectionPos", function(cm) {
            if (phantom || cm.getOption("inputStyle") != "textarea") return;
            cm.setSize(100, 100);
            addDoc(cm, 200, 100);
            cm.setSelection(Pos(1, 100), Pos(98, 100));
            var lineWidth = cm.charCoords(Pos(0, 200), "local").left;
            var lineHeight = (cm.charCoords(Pos(99)).top - cm.charCoords(Pos(0)).top) / 100;
            cm.scrollTo(0, 0);
            var selElt = byClassName(cm.getWrapperElement(), "CodeMirror-selected");
            var outer = cm.getWrapperElement().getBoundingClientRect();
            var sawMiddle, sawTop, sawBottom;
            for (var i = 0, e = selElt.length; i < e; ++i) {
              var box = selElt[i].getBoundingClientRect();
              var atLeft = box.left - outer.left < 30;
              var width = box.right - box.left;
              var atRight = box.right - outer.left > .8 * lineWidth;
              if (atLeft && atRight) {
                sawMiddle = true;
                is(box.bottom - box.top > 90 * lineHeight, "middle high");
                is(width > .9 * lineWidth, "middle wide");
              } else {
                is(width > .4 * lineWidth, "top/bot wide enough");
                is(width < .6 * lineWidth, "top/bot slim enough");
                if (atLeft) {
                  sawBottom = true;
                  is(box.top - outer.top > 96 * lineHeight, "bot below");
                } else if (atRight) {
                  sawTop = true;
                  is(box.top - outer.top < 2.1 * lineHeight, "top above");
                }
              }
            }
            is(sawTop && sawBottom && sawMiddle, "all parts");
          }, null);
          
          testCM("restoreHistory", function(cm) {
            cm.setValue("abc\ndef");
            cm.replaceRange("hello", Pos(1, 0), Pos(1));
            cm.replaceRange("goop", Pos(0, 0), Pos(0));
            cm.undo();
            var storedVal = cm.getValue(), storedHist = cm.getHistory();
            if (window.JSON) storedHist = JSON.parse(JSON.stringify(storedHist));
            eq(storedVal, "abc\nhello");
            cm.setValue("");
            cm.clearHistory();
            eq(cm.historySize().undo, 0);
            cm.setValue(storedVal);
            cm.setHistory(storedHist);
            cm.redo();
            eq(cm.getValue(), "goop\nhello");
            cm.undo(); cm.undo();
            eq(cm.getValue(), "abc\ndef");
          });
          
          testCM("doubleScrollbar", function(cm) {
            var dummy = document.body.appendChild(document.createElement("p"));
            dummy.style.cssText = "height: 50px; overflow: scroll; width: 50px";
            var scrollbarWidth = dummy.offsetWidth + 1 - dummy.clientWidth;
            document.body.removeChild(dummy);
            if (scrollbarWidth < 2) return;
            cm.setSize(null, 100);
            addDoc(cm, 1, 300);
            var wrap = cm.getWrapperElement();
            is(wrap.offsetWidth - byClassName(wrap, "CodeMirror-lines")[0].offsetWidth <= scrollbarWidth * 1.5);
          });
          
          testCM("weirdLinebreaks", function(cm) {
            cm.setValue("foo\nbar\rbaz\r\nquux\n\rplop");
            is(cm.getValue(), "foo\nbar\nbaz\nquux\n\nplop");
            is(cm.lineCount(), 6);
            cm.setValue("\n\n");
            is(cm.lineCount(), 3);
          });
          
          testCM("setSize", function(cm) {
            cm.setSize(100, 100);
            var wrap = cm.getWrapperElement();
            is(wrap.offsetWidth, 100);
            is(wrap.offsetHeight, 100);
            cm.setSize("100%", "3em");
            is(wrap.style.width, "100%");
            is(wrap.style.height, "3em");
            cm.setSize(null, 40);
            is(wrap.style.width, "100%");
            is(wrap.style.height, "40px");
          });
          
          function foldLines(cm, start, end, autoClear) {
            return cm.markText(Pos(start, 0), Pos(end - 1), {
              inclusiveLeft: true,
              inclusiveRight: true,
              collapsed: true,
              clearOnEnter: autoClear
            });
          }
          
          testCM("collapsedLines", function(cm) {
            addDoc(cm, 4, 10);
            var range = foldLines(cm, 4, 5), cleared = 0;
            CodeMirror.on(range, "clear", function() {cleared++;});
            cm.setCursor(Pos(3, 0));
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(5, 0));
            cm.replaceRange("abcdefg", Pos(3, 0), Pos(3));
            cm.setCursor(Pos(3, 6));
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(5, 4));
            cm.replaceRange("ab", Pos(3, 0), Pos(3));
            cm.setCursor(Pos(3, 2));
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(5, 2));
            cm.operation(function() {range.clear(); range.clear();});
            eq(cleared, 1);
          });
          
          testCM("collapsedRangeCoordsChar", function(cm) {
            var pos_1_3 = cm.charCoords(Pos(1, 3));
            pos_1_3.left += 2; pos_1_3.top += 2;
            var opts = {collapsed: true, inclusiveLeft: true, inclusiveRight: true};
            var m1 = cm.markText(Pos(0, 0), Pos(2, 0), opts);
            eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));
            m1.clear();
            var m1 = cm.markText(Pos(0, 0), Pos(1, 1), {collapsed: true, inclusiveLeft: true});
            var m2 = cm.markText(Pos(1, 1), Pos(2, 0), {collapsed: true, inclusiveRight: true});
            eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));
            m1.clear(); m2.clear();
            var m1 = cm.markText(Pos(0, 0), Pos(1, 6), opts);
            eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));
          }, {value: "123456\nabcdef\nghijkl\nmnopqr\n"});
          
          testCM("collapsedRangeBetweenLinesSelected", function(cm) {
            if (cm.getOption("inputStyle") != "textarea") return;
            var widget = document.createElement("span");
            widget.textContent = "\u2194";
            cm.markText(Pos(0, 3), Pos(1, 0), {replacedWith: widget});
            cm.setSelection(Pos(0, 3), Pos(1, 0));
            var selElts = byClassName(cm.getWrapperElement(), "CodeMirror-selected");
            for (var i = 0, w = 0; i < selElts.length; i++)
              w += selElts[i].offsetWidth;
            is(w > 0);
          }, {value: "one\ntwo"});
          
          testCM("randomCollapsedRanges", function(cm) {
            addDoc(cm, 20, 500);
            cm.operation(function() {
              for (var i = 0; i < 200; i++) {
                var start = Pos(Math.floor(Math.random() * 500), Math.floor(Math.random() * 20));
                if (i % 4)
                  try { cm.markText(start, Pos(start.line + 2, 1), {collapsed: true}); }
                  catch(e) { if (!/overlapping/.test(String(e))) throw e; }
                else
                  cm.markText(start, Pos(start.line, start.ch + 4), {"className": "foo"});
              }
            });
          });
          
          testCM("hiddenLinesAutoUnfold", function(cm) {
            var range = foldLines(cm, 1, 3, true), cleared = 0;
            CodeMirror.on(range, "clear", function() {cleared++;});
            cm.setCursor(Pos(3, 0));
            eq(cleared, 0);
            cm.execCommand("goCharLeft");
            eq(cleared, 1);
            range = foldLines(cm, 1, 3, true);
            CodeMirror.on(range, "clear", function() {cleared++;});
            eqPos(cm.getCursor(), Pos(3, 0));
            cm.setCursor(Pos(0, 3));
            cm.execCommand("goCharRight");
            eq(cleared, 2);
          }, {value: "abc\ndef\nghi\njkl"});
          
          testCM("hiddenLinesSelectAll", function(cm) {  // Issue #484
            addDoc(cm, 4, 20);
            foldLines(cm, 0, 10);
            foldLines(cm, 11, 20);
            CodeMirror.commands.selectAll(cm);
            eqPos(cm.getCursor(true), Pos(10, 0));
            eqPos(cm.getCursor(false), Pos(10, 4));
          });
          
          
          testCM("everythingFolded", function(cm) {
            addDoc(cm, 2, 2);
            function enterPress() {
              cm.triggerOnKeyDown({type: "keydown", keyCode: 13, preventDefault: function(){}, stopPropagation: function(){}});
            }
            var fold = foldLines(cm, 0, 2);
            enterPress();
            eq(cm.getValue(), "xx\nxx");
            fold.clear();
            fold = foldLines(cm, 0, 2, true);
            eq(fold.find(), null);
            enterPress();
            eq(cm.getValue(), "\nxx\nxx");
          });
          
          testCM("structuredFold", function(cm) {
            if (phantom) return;
            addDoc(cm, 4, 8);
            var range = cm.markText(Pos(1, 2), Pos(6, 2), {
              replacedWith: document.createTextNode("Q")
            });
            cm.setCursor(0, 3);
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(6, 2));
            CodeMirror.commands.goCharLeft(cm);
            eqPos(cm.getCursor(), Pos(1, 2));
            CodeMirror.commands.delCharAfter(cm);
            eq(cm.getValue(), "xxxx\nxxxx\nxxxx");
            addDoc(cm, 4, 8);
            range = cm.markText(Pos(1, 2), Pos(6, 2), {
              replacedWith: document.createTextNode("M"),
              clearOnEnter: true
            });
            var cleared = 0;
            CodeMirror.on(range, "clear", function(){++cleared;});
            cm.setCursor(0, 3);
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(6, 2));
            CodeMirror.commands.goCharLeft(cm);
            eqPos(cm.getCursor(), Pos(6, 1));
            eq(cleared, 1);
            range.clear();
            eq(cleared, 1);
            range = cm.markText(Pos(1, 2), Pos(6, 2), {
              replacedWith: document.createTextNode("Q"),
              clearOnEnter: true
            });
            range.clear();
            cm.setCursor(1, 2);
            CodeMirror.commands.goCharRight(cm);
            eqPos(cm.getCursor(), Pos(1, 3));
            range = cm.markText(Pos(2, 0), Pos(4, 4), {
              replacedWith: document.createTextNode("M")
            });
            cm.setCursor(1, 0);
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(2, 0));
          }, null);
          
          testCM("nestedFold", function(cm) {
            addDoc(cm, 10, 3);
            function fold(ll, cl, lr, cr) {
              return cm.markText(Pos(ll, cl), Pos(lr, cr), {collapsed: true});
            }
            var inner1 = fold(0, 6, 1, 3), inner2 = fold(0, 2, 1, 8), outer = fold(0, 1, 2, 3), inner0 = fold(0, 5, 0, 6);
            cm.setCursor(0, 1);
            CodeMirror.commands.goCharRight(cm);
            eqPos(cm.getCursor(), Pos(2, 3));
            inner0.clear();
            CodeMirror.commands.goCharLeft(cm);
            eqPos(cm.getCursor(), Pos(0, 1));
            outer.clear();
            CodeMirror.commands.goCharRight(cm);
            eqPos(cm.getCursor(), Pos(0, 2));
            CodeMirror.commands.goCharRight(cm);
            eqPos(cm.getCursor(), Pos(1, 8));
            inner2.clear();
            CodeMirror.commands.goCharLeft(cm);
            eqPos(cm.getCursor(), Pos(1, 7));
            cm.setCursor(0, 5);
            CodeMirror.commands.goCharRight(cm);
            eqPos(cm.getCursor(), Pos(0, 6));
            CodeMirror.commands.goCharRight(cm);
            eqPos(cm.getCursor(), Pos(1, 3));
          });
          
          testCM("badNestedFold", function(cm) {
            addDoc(cm, 4, 4);
            cm.markText(Pos(0, 2), Pos(3, 2), {collapsed: true});
            var caught;
            try {cm.markText(Pos(0, 1), Pos(0, 3), {collapsed: true});}
            catch(e) {caught = e;}
            is(caught instanceof Error, "no error");
            is(/overlap/i.test(caught.message), "wrong error");
          });
          
          testCM("nestedFoldOnSide", function(cm) {
            var m1 = cm.markText(Pos(0, 1), Pos(2, 1), {collapsed: true, inclusiveRight: true});
            var m2 = cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true});
            cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true}).clear();
            try { cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true, inclusiveLeft: true}); }
            catch(e) { var caught = e; }
            is(caught && /overlap/i.test(caught.message));
            var m3 = cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true});
            var m4 = cm.markText(Pos(2, 0), Pos(2, 1), {collapse: true, inclusiveRight: true});
            m1.clear(); m4.clear();
            m1 = cm.markText(Pos(0, 1), Pos(2, 1), {collapsed: true});
            cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true}).clear();
            try { cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true, inclusiveRight: true}); }
            catch(e) { var caught = e; }
            is(caught && /overlap/i.test(caught.message));
          }, {value: "ab\ncd\ef"});
          
          testCM("editInFold", function(cm) {
            addDoc(cm, 4, 6);
            var m = cm.markText(Pos(1, 2), Pos(3, 2), {collapsed: true});
            cm.replaceRange("", Pos(0, 0), Pos(1, 3));
            cm.replaceRange("", Pos(2, 1), Pos(3, 3));
            cm.replaceRange("a\nb\nc\nd", Pos(0, 1), Pos(1, 0));
            cm.cursorCoords(Pos(0, 0));
          });
          
          testCM("wrappingInlineWidget", function(cm) {
            cm.setSize("11em");
            var w = document.createElement("span");
            w.style.color = "red";
            w.innerHTML = "one two three four";
            cm.markText(Pos(0, 6), Pos(0, 9), {replacedWith: w});
            var cur0 = cm.cursorCoords(Pos(0, 0)), cur1 = cm.cursorCoords(Pos(0, 10));
            is(cur0.top < cur1.top);
            is(cur0.bottom < cur1.bottom);
            var curL = cm.cursorCoords(Pos(0, 6)), curR = cm.cursorCoords(Pos(0, 9));
            eq(curL.top, cur0.top);
            eq(curL.bottom, cur0.bottom);
            eq(curR.top, cur1.top);
            eq(curR.bottom, cur1.bottom);
            cm.replaceRange("", Pos(0, 9), Pos(0));
            curR = cm.cursorCoords(Pos(0, 9));
            if (phantom) return;
            eq(curR.top, cur1.top);
            eq(curR.bottom, cur1.bottom);
          }, {value: "1 2 3 xxx 4", lineWrapping: true});
          
          testCM("showEmptyWidgetSpan", function(cm) {
            var marker = cm.markText(Pos(0, 2), Pos(0, 2), {
              clearWhenEmpty: false,
              replacedWith: document.createTextNode("X")
            });
            eq(cm.display.view[0].text.textContent, "abXc");
          }, {value: "abc"});
          
          testCM("changedInlineWidget", function(cm) {
            cm.setSize("10em");
            var w = document.createElement("span");
            w.innerHTML = "x";
            var m = cm.markText(Pos(0, 4), Pos(0, 5), {replacedWith: w});
            w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed";
            m.changed();
            var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0];
            is(hScroll.scrollWidth > hScroll.clientWidth);
          }, {value: "hello there"});
          
          testCM("changedBookmark", function(cm) {
            cm.setSize("10em");
            var w = document.createElement("span");
            w.innerHTML = "x";
            var m = cm.setBookmark(Pos(0, 4), {widget: w});
            w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed";
            m.changed();
            var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0];
            is(hScroll.scrollWidth > hScroll.clientWidth);
          }, {value: "abcdefg"});
          
          testCM("inlineWidget", function(cm) {
            var w = cm.setBookmark(Pos(0, 2), {widget: document.createTextNode("uu")});
            cm.setCursor(0, 2);
            CodeMirror.commands.goLineDown(cm);
            eqPos(cm.getCursor(), Pos(1, 4));
            cm.setCursor(0, 2);
            cm.replaceSelection("hi");
            eqPos(w.find(), Pos(0, 2));
            cm.setCursor(0, 1);
            cm.replaceSelection("ay");
            eqPos(w.find(), Pos(0, 4));
            eq(cm.getLine(0), "uayuhiuu");
          }, {value: "uuuu\nuuuuuu"});
          
          testCM("wrappingAndResizing", function(cm) {
            cm.setSize(null, "auto");
            cm.setOption("lineWrapping", true);
            var wrap = cm.getWrapperElement(), h0 = wrap.offsetHeight;
            var doc = "xxx xxx xxx xxx xxx";
            cm.setValue(doc);
            for (var step = 10, w = cm.charCoords(Pos(0, 18), "div").right;; w += step) {
              cm.setSize(w);
              if (wrap.offsetHeight <= h0 * (opera_lt10 ? 1.2 : 1.5)) {
                if (step == 10) { w -= 10; step = 1; }
                else break;
              }
            }
            // Ensure that putting the cursor at the end of the maximally long
            // line doesn't cause wrapping to happen.
            cm.setCursor(Pos(0, doc.length));
            eq(wrap.offsetHeight, h0);
            cm.replaceSelection("x");
            is(wrap.offsetHeight > h0, "wrapping happens");
            // Now add a max-height and, in a document consisting of
            // almost-wrapped lines, go over it so that a scrollbar appears.
            cm.setValue(doc + "\n" + doc + "\n");
            cm.getScrollerElement().style.maxHeight = "100px";
            cm.replaceRange("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n!\n", Pos(2, 0));
            forEach([Pos(0, doc.length), Pos(0, doc.length - 1),
                     Pos(0, 0), Pos(1, doc.length), Pos(1, doc.length - 1)],
                    function(pos) {
              var coords = cm.charCoords(pos);
              eqPos(pos, cm.coordsChar({left: coords.left + 2, top: coords.top + 5}));
            });
          }, null, ie_lt8);
          
          testCM("measureEndOfLine", function(cm) {
            cm.setSize(null, "auto");
            var inner = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild;
            var lh = inner.offsetHeight;
            for (var step = 10, w = cm.charCoords(Pos(0, 7), "div").right;; w += step) {
              cm.setSize(w);
              if (inner.offsetHeight < 2.5 * lh) {
                if (step == 10) { w -= 10; step = 1; }
                else break;
              }
            }
            cm.setValue(cm.getValue() + "\n\n");
            var endPos = cm.charCoords(Pos(0, 18), "local");
            is(endPos.top > lh * .8, "not at top");
            is(endPos.left > w - 20, "not at right");
            endPos = cm.charCoords(Pos(0, 18));
            eqPos(cm.coordsChar({left: endPos.left, top: endPos.top + 5}), Pos(0, 18));
          }, {mode: "text/html", value: "<!-- foo barrr -->", lineWrapping: true}, ie_lt8 || opera_lt10);
          
          testCM("scrollVerticallyAndHorizontally", function(cm) {
            if (cm.getOption("inputStyle") != "textarea") return;
            cm.setSize(100, 100);
            addDoc(cm, 40, 40);
            cm.setCursor(39);
            var wrap = cm.getWrapperElement(), bar = byClassName(wrap, "CodeMirror-vscrollbar")[0];
            is(bar.offsetHeight < wrap.offsetHeight, "vertical scrollbar limited by horizontal one");
            var cursorBox = byClassName(wrap, "CodeMirror-cursor")[0].getBoundingClientRect();
            var editorBox = wrap.getBoundingClientRect();
            is(cursorBox.bottom < editorBox.top + cm.getScrollerElement().clientHeight,
               "bottom line visible");
          }, {lineNumbers: true});
          
          testCM("moveVstuck", function(cm) {
            var lines = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild, h0 = lines.offsetHeight;
            var val = "fooooooooooooooooooooooooo baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar\n";
            cm.setValue(val);
            for (var w = cm.charCoords(Pos(0, 26), "div").right * 2.8;; w += 5) {
              cm.setSize(w);
              if (lines.offsetHeight <= 3.5 * h0) break;
            }
            cm.setCursor(Pos(0, val.length - 1));
            cm.moveV(-1, "line");
            eqPos(cm.getCursor(), Pos(0, 26));
          }, {lineWrapping: true}, ie_lt8 || opera_lt10);
          
          testCM("collapseOnMove", function(cm) {
            cm.setSelection(Pos(0, 1), Pos(2, 4));
            cm.execCommand("goLineUp");
            is(!cm.somethingSelected());
            eqPos(cm.getCursor(), Pos(0, 1));
            cm.setSelection(Pos(0, 1), Pos(2, 4));
            cm.execCommand("goPageDown");
            is(!cm.somethingSelected());
            eqPos(cm.getCursor(), Pos(2, 4));
            cm.execCommand("goLineUp");
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(0, 4));
            cm.setSelection(Pos(0, 1), Pos(2, 4));
            cm.execCommand("goCharLeft");
            is(!cm.somethingSelected());
            eqPos(cm.getCursor(), Pos(0, 1));
          }, {value: "aaaaa\nb\nccccc"});
          
          testCM("clickTab", function(cm) {
            var p0 = cm.charCoords(Pos(0, 0));
            eqPos(cm.coordsChar({left: p0.left + 5, top: p0.top + 5}), Pos(0, 0));
            eqPos(cm.coordsChar({left: p0.right - 5, top: p0.top + 5}), Pos(0, 1));
          }, {value: "\t\n\n", lineWrapping: true, tabSize: 8});
          
          testCM("verticalScroll", function(cm) {
            cm.setSize(100, 200);
            cm.setValue("foo\nbar\nbaz\n");
            var sc = cm.getScrollerElement(), baseWidth = sc.scrollWidth;
            cm.replaceRange("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah", Pos(0, 0), Pos(0));
            is(sc.scrollWidth > baseWidth, "scrollbar present");
            cm.replaceRange("foo", Pos(0, 0), Pos(0));
            if (!phantom) eq(sc.scrollWidth, baseWidth, "scrollbar gone");
            cm.replaceRange("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah", Pos(0, 0), Pos(0));
            cm.replaceRange("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbh", Pos(1, 0), Pos(1));
            is(sc.scrollWidth > baseWidth, "present again");
            var curWidth = sc.scrollWidth;
            cm.replaceRange("foo", Pos(0, 0), Pos(0));
            is(sc.scrollWidth < curWidth, "scrollbar smaller");
            is(sc.scrollWidth > baseWidth, "but still present");
          });
          
          testCM("extraKeys", function(cm) {
            var outcome;
            function fakeKey(expected, code, props) {
              if (typeof code == "string") code = code.charCodeAt(0);
              var e = {type: "keydown", keyCode: code, preventDefault: function(){}, stopPropagation: function(){}};
              if (props) for (var n in props) e[n] = props[n];
              outcome = null;
              cm.triggerOnKeyDown(e);
              eq(outcome, expected);
            }
            CodeMirror.commands.testCommand = function() {outcome = "tc";};
            CodeMirror.commands.goTestCommand = function() {outcome = "gtc";};
            cm.setOption("extraKeys", {"Shift-X": function() {outcome = "sx";},
                                       "X": function() {outcome = "x";},
                                       "Ctrl-Alt-U": function() {outcome = "cau";},
                                       "End": "testCommand",
                                       "Home": "goTestCommand",
                                       "Tab": false});
            fakeKey(null, "U");
            fakeKey("cau", "U", {ctrlKey: true, altKey: true});
            fakeKey(null, "U", {shiftKey: true, ctrlKey: true, altKey: true});
            fakeKey("x", "X");
            fakeKey("sx", "X", {shiftKey: true});
            fakeKey("tc", 35);
            fakeKey(null, 35, {shiftKey: true});
            fakeKey("gtc", 36);
            fakeKey("gtc", 36, {shiftKey: true});
            fakeKey(null, 9);
          }, null, window.opera && mac);
          
          testCM("wordMovementCommands", function(cm) {
            cm.execCommand("goWordLeft");
            eqPos(cm.getCursor(), Pos(0, 0));
            cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
            eqPos(cm.getCursor(), Pos(0, 7));
            cm.execCommand("goWordLeft");
            eqPos(cm.getCursor(), Pos(0, 5));
            cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
            eqPos(cm.getCursor(), Pos(0, 12));
            cm.execCommand("goWordLeft");
            eqPos(cm.getCursor(), Pos(0, 9));
            cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
            eqPos(cm.getCursor(), Pos(0, 24));
            cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
            eqPos(cm.getCursor(), Pos(1, 9));
            cm.execCommand("goWordRight");
            eqPos(cm.getCursor(), Pos(1, 13));
            cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
            eqPos(cm.getCursor(), Pos(2, 0));
          }, {value: "this is (the) firstline.\na foo12\u00e9\u00f8\u00d7bar\n"});
          
          testCM("groupMovementCommands", function(cm) {
            cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(0, 0));
            cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(0, 4));
            cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(0, 7));
            cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(0, 10));
            cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(0, 7));
            cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(0, 15));
            cm.setCursor(Pos(0, 17));
            cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(0, 16));
            cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(0, 14));
            cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(0, 20));
            cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(1, 0));
            cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(1, 2));
            cm.execCommand("goGroupRight");
            eqPos(cm.getCursor(), Pos(1, 5));
            cm.execCommand("goGroupLeft"); cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(1, 0));
            cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(0, 20));
            cm.execCommand("goGroupLeft");
            eqPos(cm.getCursor(), Pos(0, 16));
          }, {value: "booo ba---quux. ffff\n  abc d"});
          
          testCM("groupsAndWhitespace", function(cm) {
            var positions = [Pos(0, 0), Pos(0, 2), Pos(0, 5), Pos(0, 9), Pos(0, 11),
                             Pos(1, 0), Pos(1, 2), Pos(1, 5)];
            for (var i = 1; i < positions.length; i++) {
              cm.execCommand("goGroupRight");
              eqPos(cm.getCursor(), positions[i]);
            }
            for (var i = positions.length - 2; i >= 0; i--) {
              cm.execCommand("goGroupLeft");
              eqPos(cm.getCursor(), i == 2 ? Pos(0, 6) : positions[i]);
            }
          }, {value: "  foo +++  \n  bar"});
          
          testCM("charMovementCommands", function(cm) {
            cm.execCommand("goCharLeft"); cm.execCommand("goColumnLeft");
            eqPos(cm.getCursor(), Pos(0, 0));
            cm.execCommand("goCharRight"); cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(0, 2));
            cm.setCursor(Pos(1, 0));
            cm.execCommand("goColumnLeft");
            eqPos(cm.getCursor(), Pos(1, 0));
            cm.execCommand("goCharLeft");
            eqPos(cm.getCursor(), Pos(0, 5));
            cm.execCommand("goColumnRight");
            eqPos(cm.getCursor(), Pos(0, 5));
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(1, 0));
            cm.execCommand("goLineEnd");
            eqPos(cm.getCursor(), Pos(1, 5));
            cm.execCommand("goLineStartSmart");
            eqPos(cm.getCursor(), Pos(1, 1));
            cm.execCommand("goLineStartSmart");
            eqPos(cm.getCursor(), Pos(1, 0));
            cm.setCursor(Pos(2, 0));
            cm.execCommand("goCharRight"); cm.execCommand("goColumnRight");
            eqPos(cm.getCursor(), Pos(2, 0));
          }, {value: "line1\n ine2\n"});
          
          testCM("verticalMovementCommands", function(cm) {
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(0, 0));
            cm.execCommand("goLineDown");
            if (!phantom) // This fails in PhantomJS, though not in a real Webkit
              eqPos(cm.getCursor(), Pos(1, 0));
            cm.setCursor(Pos(1, 12));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(2, 5));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(3, 0));
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(2, 5));
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(1, 12));
            cm.execCommand("goPageDown");
            eqPos(cm.getCursor(), Pos(5, 0));
            cm.execCommand("goPageDown"); cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(5, 0));
            cm.execCommand("goPageUp");
            eqPos(cm.getCursor(), Pos(0, 0));
          }, {value: "line1\nlong long line2\nline3\n\nline5\n"});
          
          testCM("verticalMovementCommandsWrapping", function(cm) {
            cm.setSize(120);
            cm.setCursor(Pos(0, 5));
            cm.execCommand("goLineDown");
            eq(cm.getCursor().line, 0);
            is(cm.getCursor().ch > 5, "moved beyond wrap");
            for (var i = 0; ; ++i) {
              is(i < 20, "no endless loop");
              cm.execCommand("goLineDown");
              var cur = cm.getCursor();
              if (cur.line == 1) eq(cur.ch, 5);
              if (cur.line == 2) { eq(cur.ch, 1); break; }
            }
          }, {value: "a very long line that wraps around somehow so that we can test cursor movement\nshortone\nk",
              lineWrapping: true});
          
          testCM("rtlMovement", function(cm) {
            if (cm.getOption("inputStyle") != "textarea") return;
            forEach(["خحج", "خحabcخحج", "abخحخحجcd", "abخde", "abخح2342خ1حج", "خ1ح2خح3حxج",
                     "خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!", "foobarر", "خ ة ق",
                     "<img src=\"/בדיקה3.jpg\">", "يتم السحب في 05 فبراير 2014"], function(line) {
              var inv = line.charCodeAt(0) > 128;
              cm.setValue(line + "\n"); cm.execCommand(inv ? "goLineEnd" : "goLineStart");
              var cursors = byClassName(cm.getWrapperElement(), "CodeMirror-cursors")[0];
              var cursor = cursors.firstChild;
              var prevX = cursor.offsetLeft, prevY = cursor.offsetTop;
              for (var i = 0; i <= line.length; ++i) {
                cm.execCommand("goCharRight");
                cursor = cursors.firstChild;
                if (i == line.length) is(cursor.offsetTop > prevY, "next line");
                else is(cursor.offsetLeft > prevX, "moved right");
                prevX = cursor.offsetLeft; prevY = cursor.offsetTop;
              }
              cm.setCursor(0, 0); cm.execCommand(inv ? "goLineStart" : "goLineEnd");
              prevX = cursors.firstChild.offsetLeft;
              for (var i = 0; i < line.length; ++i) {
                cm.execCommand("goCharLeft");
                cursor = cursors.firstChild;
                is(cursor.offsetLeft < prevX, "moved left");
                prevX = cursor.offsetLeft;
              }
            });
          }, null, ie_lt9);
          
          // Verify that updating a line clears its bidi ordering
          testCM("bidiUpdate", function(cm) {
            cm.setCursor(Pos(0, 2));
            cm.replaceSelection("خحج", "start");
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(0, 4));
          }, {value: "abcd\n"});
          
          testCM("movebyTextUnit", function(cm) {
            cm.setValue("בְּרֵאשִ\nééé́\n");
            cm.execCommand("goLineEnd");
            for (var i = 0; i < 4; ++i) cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(0, 0));
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(1, 0));
            cm.execCommand("goCharRight");
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(1, 4));
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(1, 7));
          });
          
          testCM("lineChangeEvents", function(cm) {
            addDoc(cm, 3, 5);
            var log = [], want = ["ch 0", "ch 1", "del 2", "ch 0", "ch 0", "del 1", "del 3", "del 4"];
            for (var i = 0; i < 5; ++i) {
              CodeMirror.on(cm.getLineHandle(i), "delete", function(i) {
                return function() {log.push("del " + i);};
              }(i));
              CodeMirror.on(cm.getLineHandle(i), "change", function(i) {
                return function() {log.push("ch " + i);};
              }(i));
            }
            cm.replaceRange("x", Pos(0, 1));
            cm.replaceRange("xy", Pos(1, 1), Pos(2));
            cm.replaceRange("foo\nbar", Pos(0, 1));
            cm.replaceRange("", Pos(0, 0), Pos(cm.lineCount()));
            eq(log.length, want.length, "same length");
            for (var i = 0; i < log.length; ++i)
              eq(log[i], want[i]);
          });
          
          testCM("scrollEntirelyToRight", function(cm) {
            if (phantom || cm.getOption("inputStyle") != "textarea") return;
            addDoc(cm, 500, 2);
            cm.setCursor(Pos(0, 500));
            var wrap = cm.getWrapperElement(), cur = byClassName(wrap, "CodeMirror-cursor")[0];
            is(wrap.getBoundingClientRect().right > cur.getBoundingClientRect().left);
          });
          
          testCM("lineWidgets", function(cm) {
            addDoc(cm, 500, 3);
            var last = cm.charCoords(Pos(2, 0));
            var node = document.createElement("div");
            node.innerHTML = "hi";
            var widget = cm.addLineWidget(1, node);
            is(last.top < cm.charCoords(Pos(2, 0)).top, "took up space");
            cm.setCursor(Pos(1, 1));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(2, 1));
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(1, 1));
          });
          
          testCM("lineWidgetFocus", function(cm) {
            var place = document.getElementById("testground");
            place.className = "offscreen";
            try {
              addDoc(cm, 500, 10);
              var node = document.createElement("input");
              var widget = cm.addLineWidget(1, node);
              node.focus();
              eq(document.activeElement, node);
              cm.replaceRange("new stuff", Pos(1, 0));
              eq(document.activeElement, node);
            } finally {
              place.className = "";
            }
          });
          
          testCM("lineWidgetCautiousRedraw", function(cm) {
            var node = document.createElement("div");
            node.innerHTML = "hahah";
            var w = cm.addLineWidget(0, node);
            var redrawn = false;
            w.on("redraw", function() { redrawn = true; });
            cm.replaceSelection("0");
            is(!redrawn);
          }, {value: "123\n456"});
          
          
          var knownScrollbarWidth;
          function scrollbarWidth(measure) {
            if (knownScrollbarWidth != null) return knownScrollbarWidth;
            var div = document.createElement('div');
            div.style.cssText = "width: 50px; height: 50px; overflow-x: scroll";
            document.body.appendChild(div);
            knownScrollbarWidth = div.offsetHeight - div.clientHeight;
            document.body.removeChild(div);
            return knownScrollbarWidth || 0;
          }
          
          testCM("lineWidgetChanged", function(cm) {
            addDoc(cm, 2, 300);
            var halfScrollbarWidth = scrollbarWidth(cm.display.measure)/2;
            cm.setOption('lineNumbers', true);
            cm.setSize(600, cm.defaultTextHeight() * 50);
            cm.scrollTo(null, cm.heightAtLine(125, "local"));
          
            var expectedWidgetHeight = 60;
            var expectedLinesInWidget = 3;
            function w() {
              var node = document.createElement("div");
              // we use these children with just under half width of the line to check measurements are made with correct width
              // when placed in the measure div.
              // If the widget is measured at a width much narrower than it is displayed at, the underHalf children will span two lines and break the test.
              // If the widget is measured at a width much wider than it is displayed at, the overHalf children will combine and break the test.
              // Note that this test only checks widgets where coverGutter is true, because these require extra styling to get the width right.
              // It may also be worthwhile to check this for non-coverGutter widgets.
              // Visually:
              // Good:
              // | ------------- display width ------------- |
              // | ------- widget-width when measured ------ |
              // | | -- under-half -- | | -- under-half -- | | 
              // | | --- over-half --- |                     |
              // | | --- over-half --- |                     |
              // Height: measured as 3 lines, same as it will be when actually displayed
          
              // Bad (too narrow):
              // | ------------- display width ------------- |
              // | ------ widget-width when measured ----- |  < -- uh oh
              // | | -- under-half -- |                    |
              // | | -- under-half -- |                    |  < -- when measured, shoved to next line
              // | | --- over-half --- |                   |
              // | | --- over-half --- |                   |
              // Height: measured as 4 lines, more than expected . Will be displayed as 3 lines!
          
              // Bad (too wide):
              // | ------------- display width ------------- |
              // | -------- widget-width when measured ------- | < -- uh oh
              // | | -- under-half -- | | -- under-half -- |   | 
              // | | --- over-half --- | | --- over-half --- | | < -- when measured, combined on one line
              // Height: measured as 2 lines, less than expected. Will be displayed as 3 lines!
          
              var barelyUnderHalfWidthHtml = '<div style="display: inline-block; height: 1px; width: '+(285 - halfScrollbarWidth)+'px;"></div>';
              var barelyOverHalfWidthHtml = '<div style="display: inline-block; height: 1px; width: '+(305 - halfScrollbarWidth)+'px;"></div>';
              node.innerHTML = new Array(3).join(barelyUnderHalfWidthHtml) + new Array(3).join(barelyOverHalfWidthHtml);
              node.style.cssText = "background: yellow;font-size:0;line-height: " + (expectedWidgetHeight/expectedLinesInWidget) + "px;";
              return node;
            }
            var info0 = cm.getScrollInfo();
            var w0 = cm.addLineWidget(0, w(), { coverGutter: true });
            var w150 = cm.addLineWidget(150, w(), { coverGutter: true });
            var w300 = cm.addLineWidget(300, w(), { coverGutter: true });
            var info1 = cm.getScrollInfo();
            eq(info0.height + (3 * expectedWidgetHeight), info1.height);
            eq(info0.top + expectedWidgetHeight, info1.top);
            expectedWidgetHeight = 12;
            w0.node.style.lineHeight = w150.node.style.lineHeight = w300.node.style.lineHeight = (expectedWidgetHeight/expectedLinesInWidget) + "px";
            w0.changed(); w150.changed(); w300.changed();
            var info2 = cm.getScrollInfo();
            eq(info0.height + (3 * expectedWidgetHeight), info2.height);
            eq(info0.top + expectedWidgetHeight, info2.top);
          });
          
          testCM("getLineNumber", function(cm) {
            addDoc(cm, 2, 20);
            var h1 = cm.getLineHandle(1);
            eq(cm.getLineNumber(h1), 1);
            cm.replaceRange("hi\nbye\n", Pos(0, 0));
            eq(cm.getLineNumber(h1), 3);
            cm.setValue("");
            eq(cm.getLineNumber(h1), null);
          });
          
          testCM("jumpTheGap", function(cm) {
            if (phantom) return;
            var longLine = "abcdef ghiklmnop qrstuvw xyz ";
            longLine += longLine; longLine += longLine; longLine += longLine;
            cm.replaceRange(longLine, Pos(2, 0), Pos(2));
            cm.setSize("200px", null);
            cm.getWrapperElement().style.lineHeight = 2;
            cm.refresh();
            cm.setCursor(Pos(0, 1));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(1, 1));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(2, 1));
            cm.execCommand("goLineDown");
            eq(cm.getCursor().line, 2);
            is(cm.getCursor().ch > 1);
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(2, 1));
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(1, 1));
            var node = document.createElement("div");
            node.innerHTML = "hi"; node.style.height = "30px";
            cm.addLineWidget(0, node);
            cm.addLineWidget(1, node.cloneNode(true), {above: true});
            cm.setCursor(Pos(0, 2));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(1, 2));
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(0, 2));
          }, {lineWrapping: true, value: "abc\ndef\nghi\njkl\n"});
          
          testCM("addLineClass", function(cm) {
            function cls(line, text, bg, wrap, gutter) {
              var i = cm.lineInfo(line);
              eq(i.textClass, text);
              eq(i.bgClass, bg);
              eq(i.wrapClass, wrap);
              if (typeof i.handle.gutterClass !== 'undefined') {
                  eq(i.handle.gutterClass, gutter);
              }
            }
            cm.addLineClass(0, "text", "foo");
            cm.addLineClass(0, "text", "bar");
            cm.addLineClass(1, "background", "baz");
            cm.addLineClass(1, "wrap", "foo");
            cm.addLineClass(1, "gutter", "gutter-class");
            cls(0, "foo bar", null, null, null);
            cls(1, null, "baz", "foo", "gutter-class");
            var lines = cm.display.lineDiv;
            eq(byClassName(lines, "foo").length, 2);
            eq(byClassName(lines, "bar").length, 1);
            eq(byClassName(lines, "baz").length, 1);
            eq(byClassName(lines, "gutter-class").length, 1);
            cm.removeLineClass(0, "text", "foo");
            cls(0, "bar", null, null, null);
            cm.removeLineClass(0, "text", "foo");
            cls(0, "bar", null, null, null);
            cm.removeLineClass(0, "text", "bar");
            cls(0, null, null, null);
          
            cm.addLineClass(1, "wrap", "quux");
            cls(1, null, "baz", "foo quux", "gutter-class");
            cm.removeLineClass(1, "wrap");
            cls(1, null, "baz", null, "gutter-class");
            cm.removeLineClass(1, "gutter", "gutter-class");
            eq(byClassName(lines, "gutter-class").length, 0);
            cls(1, null, "baz", null, null);
          
            cm.addLineClass(1, "gutter", "gutter-class");
            cls(1, null, "baz", null, "gutter-class");
            cm.removeLineClass(1, "gutter", "gutter-class");
            cls(1, null, "baz", null, null);
          
          }, {value: "hohoho\n", lineNumbers: true});
          
          testCM("atomicMarker", function(cm) {
            addDoc(cm, 10, 10);
            function atom(ll, cl, lr, cr, li, ri) {
              return cm.markText(Pos(ll, cl), Pos(lr, cr),
                                 {atomic: true, inclusiveLeft: li, inclusiveRight: ri});
            }
            var m = atom(0, 1, 0, 5);
            cm.setCursor(Pos(0, 1));
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(0, 5));
            cm.execCommand("goCharLeft");
            eqPos(cm.getCursor(), Pos(0, 1));
            m.clear();
            m = atom(0, 0, 0, 5, true);
            eqPos(cm.getCursor(), Pos(0, 5), "pushed out");
            cm.execCommand("goCharLeft");
            eqPos(cm.getCursor(), Pos(0, 5));
            m.clear();
            m = atom(8, 4, 9, 10, false, true);
            cm.setCursor(Pos(9, 8));
            eqPos(cm.getCursor(), Pos(8, 4), "set");
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(8, 4), "char right");
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(8, 4), "line down");
            cm.execCommand("goCharLeft");
            eqPos(cm.getCursor(), Pos(8, 3));
            m.clear();
            m = atom(1, 1, 3, 8);
            cm.setCursor(Pos(0, 0));
            cm.setCursor(Pos(2, 0));
            eqPos(cm.getCursor(), Pos(3, 8));
            cm.execCommand("goCharLeft");
            eqPos(cm.getCursor(), Pos(1, 1));
            cm.execCommand("goCharRight");
            eqPos(cm.getCursor(), Pos(3, 8));
            cm.execCommand("goLineUp");
            eqPos(cm.getCursor(), Pos(1, 1));
            cm.execCommand("goLineDown");
            eqPos(cm.getCursor(), Pos(3, 8));
            cm.execCommand("delCharBefore");
            eq(cm.getValue().length, 80, "del chunk");
            m = atom(3, 0, 5, 5);
            cm.setCursor(Pos(3, 0));
            cm.execCommand("delWordAfter");
            eq(cm.getValue().length, 53, "del chunk");
          });
          
          testCM("selectionBias", function(cm) {
            cm.markText(Pos(0, 1), Pos(0, 3), {atomic: true});
            cm.setCursor(Pos(0, 2));
            eqPos(cm.getCursor(), Pos(0, 3));
            cm.setCursor(Pos(0, 2));
            eqPos(cm.getCursor(), Pos(0, 1));
            cm.setCursor(Pos(0, 2), null, {bias: -1});
            eqPos(cm.getCursor(), Pos(0, 1));
            cm.setCursor(Pos(0, 4));
            cm.setCursor(Pos(0, 2), null, {bias: 1});
            eqPos(cm.getCursor(), Pos(0, 3));
          }, {value: "12345"});
          
          testCM("selectionHomeEnd", function(cm) {
            cm.markText(Pos(1, 0), Pos(1, 1), {atomic: true, inclusiveLeft: true});
            cm.markText(Pos(1, 3), Pos(1, 4), {atomic: true, inclusiveRight: true});
            cm.setCursor(Pos(1, 2));
            cm.execCommand("goLineStart");
            eqPos(cm.getCursor(), Pos(1, 1));
            cm.execCommand("goLineEnd");
            eqPos(cm.getCursor(), Pos(1, 3));
          }, {value: "ab\ncdef\ngh"});
          
          testCM("readOnlyMarker", function(cm) {
            function mark(ll, cl, lr, cr, at) {
              return cm.markText(Pos(ll, cl), Pos(lr, cr),
                                 {readOnly: true, atomic: at});
            }
            var m = mark(0, 1, 0, 4);
            cm.setCursor(Pos(0, 2));
            cm.replaceSelection("hi", "end");
            eqPos(cm.getCursor(), Pos(0, 2));
            eq(cm.getLine(0), "abcde");
            cm.execCommand("selectAll");
            cm.replaceSelection("oops", "around");
            eq(cm.getValue(), "oopsbcd");
            cm.undo();
            eqPos(m.find().from, Pos(0, 1));
            eqPos(m.find().to, Pos(0, 4));
            m.clear();
            cm.setCursor(Pos(0, 2));
            cm.replaceSelection("hi", "around");
            eq(cm.getLine(0), "abhicde");
            eqPos(cm.getCursor(), Pos(0, 4));
            m = mark(0, 2, 2, 2, true);
            cm.setSelection(Pos(1, 1), Pos(2, 4));
            cm.replaceSelection("t", "end");
            eqPos(cm.getCursor(), Pos(2, 3));
            eq(cm.getLine(2), "klto");
            cm.execCommand("goCharLeft");
            cm.execCommand("goCharLeft");
            eqPos(cm.getCursor(), Pos(0, 2));
            cm.setSelection(Pos(0, 1), Pos(0, 3));
            cm.replaceSelection("xx", "around");
            eqPos(cm.getCursor(), Pos(0, 3));
            eq(cm.getLine(0), "axxhicde");
          }, {value: "abcde\nfghij\nklmno\n"});
          
          testCM("dirtyBit", function(cm) {
            eq(cm.isClean(), true);
            cm.replaceSelection("boo", null, "test");
            eq(cm.isClean(), false);
            cm.undo();
            eq(cm.isClean(), true);
            cm.replaceSelection("boo", null, "test");
            cm.replaceSelection("baz", null, "test");
            cm.undo();
            eq(cm.isClean(), false);
            cm.markClean();
            eq(cm.isClean(), true);
            cm.undo();
            eq(cm.isClean(), false);
            cm.redo();
            eq(cm.isClean(), true);
          });
          
          testCM("changeGeneration", function(cm) {
            cm.replaceSelection("x");
            var softGen = cm.changeGeneration();
            cm.replaceSelection("x");
            cm.undo();
            eq(cm.getValue(), "");
            is(!cm.isClean(softGen));
            cm.replaceSelection("x");
            var hardGen = cm.changeGeneration(true);
            cm.replaceSelection("x");
            cm.undo();
            eq(cm.getValue(), "x");
            is(cm.isClean(hardGen));
          });
          
          testCM("addKeyMap", function(cm) {
            function sendKey(code) {
              cm.triggerOnKeyDown({type: "keydown", keyCode: code,
                                   preventDefault: function(){}, stopPropagation: function(){}});
            }
          
            sendKey(39);
            eqPos(cm.getCursor(), Pos(0, 1));
            var test = 0;
            var map1 = {Right: function() { ++test; }}, map2 = {Right: function() { test += 10; }}
            cm.addKeyMap(map1);
            sendKey(39);
            eqPos(cm.getCursor(), Pos(0, 1));
            eq(test, 1);
            cm.addKeyMap(map2, true);
            sendKey(39);
            eq(test, 2);
            cm.removeKeyMap(map1);
            sendKey(39);
            eq(test, 12);
            cm.removeKeyMap(map2);
            sendKey(39);
            eq(test, 12);
            eqPos(cm.getCursor(), Pos(0, 2));
            cm.addKeyMap({Right: function() { test = 55; }, name: "mymap"});
            sendKey(39);
            eq(test, 55);
            cm.removeKeyMap("mymap");
            sendKey(39);
            eqPos(cm.getCursor(), Pos(0, 3));
          }, {value: "abc"});
          
          testCM("findPosH", function(cm) {
            forEach([{from: Pos(0, 0), to: Pos(0, 1), by: 1},
                     {from: Pos(0, 0), to: Pos(0, 0), by: -1, hitSide: true},
                     {from: Pos(0, 0), to: Pos(0, 4), by: 1, unit: "word"},
                     {from: Pos(0, 0), to: Pos(0, 8), by: 2, unit: "word"},
                     {from: Pos(0, 0), to: Pos(2, 0), by: 20, unit: "word", hitSide: true},
                     {from: Pos(0, 7), to: Pos(0, 5), by: -1, unit: "word"},
                     {from: Pos(0, 4), to: Pos(0, 8), by: 1, unit: "word"},
                     {from: Pos(1, 0), to: Pos(1, 18), by: 3, unit: "word"},
                     {from: Pos(1, 22), to: Pos(1, 5), by: -3, unit: "word"},
                     {from: Pos(1, 15), to: Pos(1, 10), by: -5},
                     {from: Pos(1, 15), to: Pos(1, 10), by: -5, unit: "column"},
                     {from: Pos(1, 15), to: Pos(1, 0), by: -50, unit: "column", hitSide: true},
                     {from: Pos(1, 15), to: Pos(1, 24), by: 50, unit: "column", hitSide: true},
                     {from: Pos(1, 15), to: Pos(2, 0), by: 50, hitSide: true}], function(t) {
              var r = cm.findPosH(t.from, t.by, t.unit || "char");
              eqPos(r, t.to);
              eq(!!r.hitSide, !!t.hitSide);
            });
          }, {value: "line one\nline two.something.other\n"});
          
          testCM("beforeChange", function(cm) {
            cm.on("beforeChange", function(cm, change) {
              var text = [];
              for (var i = 0; i < change.text.length; ++i)
                text.push(change.text[i].replace(/\s/g, "_"));
              change.update(null, null, text);
            });
            cm.setValue("hello, i am a\nnew document\n");
            eq(cm.getValue(), "hello,_i_am_a\nnew_document\n");
            CodeMirror.on(cm.getDoc(), "beforeChange", function(doc, change) {
              if (change.from.line == 0) change.cancel();
            });
            cm.setValue("oops"); // Canceled
            eq(cm.getValue(), "hello,_i_am_a\nnew_document\n");
            cm.replaceRange("hey hey hey", Pos(1, 0), Pos(2, 0));
            eq(cm.getValue(), "hello,_i_am_a\nhey_hey_hey");
          }, {value: "abcdefghijk"});
          
          testCM("beforeChangeUndo", function(cm) {
            cm.replaceRange("hi", Pos(0, 0), Pos(0));
            cm.replaceRange("bye", Pos(0, 0), Pos(0));
            eq(cm.historySize().undo, 2);
            cm.on("beforeChange", function(cm, change) {
              is(!change.update);
              change.cancel();
            });
            cm.undo();
            eq(cm.historySize().undo, 0);
            eq(cm.getValue(), "bye\ntwo");
          }, {value: "one\ntwo"});
          
          testCM("beforeSelectionChange", function(cm) {
            function notAtEnd(cm, pos) {
              var len = cm.getLine(pos.line).length;
              if (!len || pos.ch == len) return Pos(pos.line, pos.ch - 1);
              return pos;
            }
            cm.on("beforeSelectionChange", function(cm, obj) {
              obj.update([{anchor: notAtEnd(cm, obj.ranges[0].anchor),
                           head: notAtEnd(cm, obj.ranges[0].head)}]);
            });
          
            addDoc(cm, 10, 10);
            cm.execCommand("goLineEnd");
            eqPos(cm.getCursor(), Pos(0, 9));
            cm.execCommand("selectAll");
            eqPos(cm.getCursor("start"), Pos(0, 0));
            eqPos(cm.getCursor("end"), Pos(9, 9));
          });
          
          testCM("change_removedText", function(cm) {
            cm.setValue("abc\ndef");
          
            var removedText = [];
            cm.on("change", function(cm, change) {
              removedText.push(change.removed);
            });
          
            cm.operation(function() {
              cm.replaceRange("xyz", Pos(0, 0), Pos(1,1));
              cm.replaceRange("123", Pos(0,0));
            });
          
            eq(removedText.length, 2);
            eq(removedText[0].join("\n"), "abc\nd");
            eq(removedText[1].join("\n"), "");
          
            var removedText = [];
            cm.undo();
            eq(removedText.length, 2);
            eq(removedText[0].join("\n"), "123");
            eq(removedText[1].join("\n"), "xyz");
          
            var removedText = [];
            cm.redo();
            eq(removedText.length, 2);
            eq(removedText[0].join("\n"), "abc\nd");
            eq(removedText[1].join("\n"), "");
          });
          
          testCM("lineStyleFromMode", function(cm) {
            CodeMirror.defineMode("test_mode", function() {
              return {token: function(stream) {
                if (stream.match(/^\[[^\]]*\]/)) return "  line-brackets  ";
                if (stream.match(/^\([^\)]*\)/)) return "  line-background-parens  ";
                if (stream.match(/^<[^>]*>/)) return "  span  line-line  line-background-bg  ";
                stream.match(/^\s+|^\S+/);
              }};
            });
            cm.setOption("mode", "test_mode");
            var bracketElts = byClassName(cm.getWrapperElement(), "brackets");
            eq(bracketElts.length, 1, "brackets count");
            eq(bracketElts[0].nodeName, "PRE");
            is(!/brackets.*brackets/.test(bracketElts[0].className));
            var parenElts = byClassName(cm.getWrapperElement(), "parens");
            eq(parenElts.length, 1, "parens count");
            eq(parenElts[0].nodeName, "DIV");
            is(!/parens.*parens/.test(parenElts[0].className));
            eq(parenElts[0].parentElement.nodeName, "DIV");
          
            eq(byClassName(cm.getWrapperElement(), "bg").length, 1);
            eq(byClassName(cm.getWrapperElement(), "line").length, 1);
            var spanElts = byClassName(cm.getWrapperElement(), "cm-span");
            eq(spanElts.length, 2);
            is(/^\s*cm-span\s*$/.test(spanElts[0].className));
          }, {value: "line1: [br] [br]\nline2: (par) (par)\nline3: <tag> <tag>"});
          
          testCM("lineStyleFromBlankLine", function(cm) {
            CodeMirror.defineMode("lineStyleFromBlankLine_mode", function() {
              return {token: function(stream) { stream.skipToEnd(); return "comment"; },
                      blankLine: function() { return "line-blank"; }};
            });
            cm.setOption("mode", "lineStyleFromBlankLine_mode");
            var blankElts = byClassName(cm.getWrapperElement(), "blank");
            eq(blankElts.length, 1);
            eq(blankElts[0].nodeName, "PRE");
            cm.replaceRange("x", Pos(1, 0));
            blankElts = byClassName(cm.getWrapperElement(), "blank");
            eq(blankElts.length, 0);
          }, {value: "foo\n\nbar"});
          
          CodeMirror.registerHelper("xxx", "a", "A");
          CodeMirror.registerHelper("xxx", "b", "B");
          CodeMirror.defineMode("yyy", function() {
            return {
              token: function(stream) { stream.skipToEnd(); },
              xxx: ["a", "b", "q"]
            };
          });
          CodeMirror.registerGlobalHelper("xxx", "c", function(m) { return m.enableC; }, "C");
          
          testCM("helpers", function(cm) {
            cm.setOption("mode", "yyy");
            eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "A/B");
            cm.setOption("mode", {name: "yyy", modeProps: {xxx: "b", enableC: true}});
            eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "B/C");
            cm.setOption("mode", "javascript");
            eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "");
          });
          
          testCM("selectionHistory", function(cm) {
            for (var i = 0; i < 3; i++) {
              cm.setExtending(true);
              cm.execCommand("goCharRight");
              cm.setExtending(false);
              cm.execCommand("goCharRight");
              cm.execCommand("goCharRight");
            }
            cm.execCommand("undoSelection");
            eq(cm.getSelection(), "c");
            cm.execCommand("undoSelection");
            eq(cm.getSelection(), "");
            eqPos(cm.getCursor(), Pos(0, 4));
            cm.execCommand("undoSelection");
            eq(cm.getSelection(), "b");
            cm.execCommand("redoSelection");
            eq(cm.getSelection(), "");
            eqPos(cm.getCursor(), Pos(0, 4));
            cm.execCommand("redoSelection");
            eq(cm.getSelection(), "c");
            cm.execCommand("redoSelection");
            eq(cm.getSelection(), "");
            eqPos(cm.getCursor(), Pos(0, 6));
          }, {value: "a b c d"});
          
          testCM("selectionChangeReducesRedo", function(cm) {
            cm.replaceSelection("X");
            cm.execCommand("goCharRight");
            cm.undoSelection();
            cm.execCommand("selectAll");
            cm.undoSelection();
            eq(cm.getValue(), "Xabc");
            eqPos(cm.getCursor(), Pos(0, 1));
            cm.undoSelection();
            eq(cm.getValue(), "abc");
          }, {value: "abc"});
          
          testCM("selectionHistoryNonOverlapping", function(cm) {
            cm.setSelection(Pos(0, 0), Pos(0, 1));
            cm.setSelection(Pos(0, 2), Pos(0, 3));
            cm.execCommand("undoSelection");
            eqPos(cm.getCursor("anchor"), Pos(0, 0));
            eqPos(cm.getCursor("head"), Pos(0, 1));
          }, {value: "1234"});
          
          testCM("cursorMotionSplitsHistory", function(cm) {
            cm.replaceSelection("a");
            cm.execCommand("goCharRight");
            cm.replaceSelection("b");
            cm.replaceSelection("c");
            cm.undo();
            eq(cm.getValue(), "a1234");
            eqPos(cm.getCursor(), Pos(0, 2));
            cm.undo();
            eq(cm.getValue(), "1234");
            eqPos(cm.getCursor(), Pos(0, 0));
          }, {value: "1234"});
          
          testCM("selChangeInOperationDoesNotSplit", function(cm) {
            for (var i = 0; i < 4; i++) {
              cm.operation(function() {
                cm.replaceSelection("x");
                cm.setCursor(Pos(0, cm.getCursor().ch - 1));
              });
            }
            eqPos(cm.getCursor(), Pos(0, 0));
            eq(cm.getValue(), "xxxxa");
            cm.undo();
            eq(cm.getValue(), "a");
          }, {value: "a"});
          
          testCM("alwaysMergeSelEventWithChangeOrigin", function(cm) {
            cm.replaceSelection("U", null, "foo");
            cm.setSelection(Pos(0, 0), Pos(0, 1), {origin: "foo"});
            cm.undoSelection();
            eq(cm.getValue(), "a");
            cm.replaceSelection("V", null, "foo");
            cm.setSelection(Pos(0, 0), Pos(0, 1), {origin: "bar"});
            cm.undoSelection();
            eq(cm.getValue(), "Va");
          }, {value: "a"});
          
          testCM("getTokenAt", function(cm) {
            var tokPlus = cm.getTokenAt(Pos(0, 2));
            eq(tokPlus.type, "operator");
            eq(tokPlus.string, "+");
            var toks = cm.getLineTokens(0);
            eq(toks.length, 3);
            forEach([["number", "1"], ["operator", "+"], ["number", "2"]], function(expect, i) {
              eq(toks[i].type, expect[0]);
              eq(toks[i].string, expect[1]);
            });
          }, {value: "1+2", mode: "javascript"});
          
          testCM("getTokenTypeAt", function(cm) {
            eq(cm.getTokenTypeAt(Pos(0, 0)), "number");
            eq(cm.getTokenTypeAt(Pos(0, 6)), "string");
            cm.addOverlay({
              token: function(stream) {
                if (stream.match("foo")) return "foo";
                else stream.next();
              }
            });
            eq(byClassName(cm.getWrapperElement(), "cm-foo").length, 1);
            eq(cm.getTokenTypeAt(Pos(0, 6)), "string");
          }, {value: "1 + 'foo'", mode: "javascript"});
          
          testCM("resizeLineWidget", function(cm) {
            addDoc(cm, 200, 3);
            var widget = document.createElement("pre");
            widget.innerHTML = "imwidget";
            widget.style.background = "yellow";
            cm.addLineWidget(1, widget, {noHScroll: true});
            cm.setSize(40);
            is(widget.parentNode.offsetWidth < 42);
          });
          
          testCM("combinedOperations", function(cm) {
            var place = document.getElementById("testground");
            var other = CodeMirror(place, {value: "123"});
            try {
              cm.operation(function() {
                cm.addLineClass(0, "wrap", "foo");
                other.addLineClass(0, "wrap", "foo");
              });
              eq(byClassName(cm.getWrapperElement(), "foo").length, 1);
              eq(byClassName(other.getWrapperElement(), "foo").length, 1);
              cm.operation(function() {
                cm.removeLineClass(0, "wrap", "foo");
                other.removeLineClass(0, "wrap", "foo");
              });
              eq(byClassName(cm.getWrapperElement(), "foo").length, 0);
              eq(byClassName(other.getWrapperElement(), "foo").length, 0);
            } finally {
              place.removeChild(other.getWrapperElement());
            }
          }, {value: "abc"});
          
          testCM("eventOrder", function(cm) {
            var seen = [];
            cm.on("change", function() {
              if (!seen.length) cm.replaceSelection(".");
              seen.push("change");
            });
            cm.on("cursorActivity", function() {
              cm.replaceSelection("!");
              seen.push("activity");
            });
            cm.replaceSelection("/");
            eq(seen.join(","), "change,change,activity,change");
          });
          
          testCM("splitSpaces_nonspecial", function(cm) {
            eq(byClassName(cm.getWrapperElement(), "cm-invalidchar").length, 0);
          }, {
            specialChars: /[\u00a0]/,
            value: "spaces ->            <- between"
          });
          
          test("core_rmClass", function() {
            var node = document.createElement("div");
            node.className = "foo-bar baz-quux yadda";
            CodeMirror.rmClass(node, "quux");
            eq(node.className, "foo-bar baz-quux yadda");
            CodeMirror.rmClass(node, "baz-quux");
            eq(node.className, "foo-bar yadda");
            CodeMirror.rmClass(node, "yadda");
            eq(node.className, "foo-bar");
            CodeMirror.rmClass(node, "foo-bar");
            eq(node.className, "");
            node.className = " foo ";
            CodeMirror.rmClass(node, "foo");
            eq(node.className, "");
          });
          
          test("core_addClass", function() {
            var node = document.createElement("div");
            CodeMirror.addClass(node, "a");
            eq(node.className, "a");
            CodeMirror.addClass(node, "a");
            eq(node.className, "a");
            CodeMirror.addClass(node, "b");
            eq(node.className, "a b");
            CodeMirror.addClass(node, "a");
            CodeMirror.addClass(node, "b");
            eq(node.className, "a b");
          });
          
        • vim_test.js
          CodeMirror.Vim.suppressErrorLogging = true;
          
          var code = '' +
          ' wOrd1 (#%\n' +
          ' word3] \n' +
          'aopop pop 0 1 2 3 4\n' +
          ' (a) [b] {c} \n' +
          'int getchar(void) {\n' +
          '  static char buf[BUFSIZ];\n' +
          '  static char *bufp = buf;\n' +
          '  if (n == 0) {  /* buffer is empty */\n' +
          '    n = read(0, buf, sizeof buf);\n' +
          '    bufp = buf;\n' +
          '  }\n' +
          '\n' +
          '  return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n' +
          ' \n' +
          '}\n';
          
          var lines = (function() {
            lineText = code.split('\n');
            var ret = [];
            for (var i = 0; i < lineText.length; i++) {
              ret[i] = {
                line: i,
                length: lineText[i].length,
                lineText: lineText[i],
                textStart: /^\s*/.exec(lineText[i])[0].length
              };
            }
            return ret;
          })();
          var endOfDocument = makeCursor(lines.length - 1,
              lines[lines.length - 1].length);
          var wordLine = lines[0];
          var bigWordLine = lines[1];
          var charLine = lines[2];
          var bracesLine = lines[3];
          var seekBraceLine = lines[4];
          
          var word1 = {
            start: { line: wordLine.line, ch: 1 },
            end: { line: wordLine.line, ch: 5 }
          };
          var word2 = {
            start: { line: wordLine.line, ch: word1.end.ch + 2 },
            end: { line: wordLine.line, ch: word1.end.ch + 4 }
          };
          var word3 = {
            start: { line: bigWordLine.line, ch: 1 },
            end: { line: bigWordLine.line, ch: 5 }
          };
          var bigWord1 = word1;
          var bigWord2 = word2;
          var bigWord3 = {
            start: { line: bigWordLine.line, ch: 1 },
            end: { line: bigWordLine.line, ch: 7 }
          };
          var bigWord4 = {
            start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 },
            end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 }
          };
          
          var oChars = [ { line: charLine.line, ch: 1 },
              { line: charLine.line, ch: 3 },
              { line: charLine.line, ch: 7 } ];
          var pChars = [ { line: charLine.line, ch: 2 },
              { line: charLine.line, ch: 4 },
              { line: charLine.line, ch: 6 },
              { line: charLine.line, ch: 8 } ];
          var numChars = [ { line: charLine.line, ch: 10 },
              { line: charLine.line, ch: 12 },
              { line: charLine.line, ch: 14 },
              { line: charLine.line, ch: 16 },
              { line: charLine.line, ch: 18 }];
          var parens1 = {
            start: { line: bracesLine.line, ch: 1 },
            end: { line: bracesLine.line, ch: 3 }
          };
          var squares1 = {
            start: { line: bracesLine.line, ch: 5 },
            end: { line: bracesLine.line, ch: 7 }
          };
          var curlys1 = {
            start: { line: bracesLine.line, ch: 9 },
            end: { line: bracesLine.line, ch: 11 }
          };
          var seekOutside = {
            start: { line: seekBraceLine.line, ch: 1 },
            end: { line: seekBraceLine.line, ch: 16 }
          };
          var seekInside = {
            start: { line: seekBraceLine.line, ch: 14 },
            end: { line: seekBraceLine.line, ch: 11 }
          };
          
          function copyCursor(cur) {
            return { ch: cur.ch, line: cur.line };
          }
          
          function forEach(arr, func) {
            for (var i = 0; i < arr.length; i++) {
              func(arr[i], i, arr);
            }
          }
          
          function testVim(name, run, opts, expectedFail) {
            var vimOpts = {
              lineNumbers: true,
              vimMode: true,
              showCursorWhenSelecting: true,
              value: code
            };
            for (var prop in opts) {
              if (opts.hasOwnProperty(prop)) {
                vimOpts[prop] = opts[prop];
              }
            }
            return test('vim_' + name, function() {
              var place = document.getElementById("testground");
              var cm = CodeMirror(place, vimOpts);
              var vim = CodeMirror.Vim.maybeInitVimState_(cm);
          
              function doKeysFn(cm) {
                return function(args) {
                  if (args instanceof Array) {
                    arguments = args;
                  }
                  for (var i = 0; i < arguments.length; i++) {
                    CodeMirror.Vim.handleKey(cm, arguments[i]);
                  }
                }
              }
              function doInsertModeKeysFn(cm) {
                return function(args) {
                  if (args instanceof Array) { arguments = args; }
                  function executeHandler(handler) {
                    if (typeof handler == 'string') {
                      CodeMirror.commands[handler](cm);
                    } else {
                      handler(cm);
                    }
                    return true;
                  }
                  for (var i = 0; i < arguments.length; i++) {
                    var key = arguments[i];
                    // Find key in keymap and handle.
                    var handled = CodeMirror.lookupKey(key, 'vim-insert', executeHandler);
                    // Record for insert mode.
                    if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') {
                      var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges;
                      if (lastChange) {
                        lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key));
                      }
                    }
                  }
                }
              }
              function doExFn(cm) {
                return function(command) {
                  cm.openDialog = helpers.fakeOpenDialog(command);
                  helpers.doKeys(':');
                }
              }
              function assertCursorAtFn(cm) {
                return function(line, ch) {
                  var pos;
                  if (ch == null && typeof line.line == 'number') {
                    pos = line;
                  } else {
                    pos = makeCursor(line, ch);
                  }
                  eqPos(pos, cm.getCursor());
                }
              }
              function fakeOpenDialog(result) {
                return function(text, callback) {
                  return callback(result);
                }
              }
              function fakeOpenNotification(matcher) {
                return function(text) {
                  matcher(text);
                }
              }
              var helpers = {
                doKeys: doKeysFn(cm),
                // Warning: Only emulates keymap events, not character insertions. Use
                // replaceRange to simulate character insertions.
                // Keys are in CodeMirror format, NOT vim format.
                doInsertModeKeys: doInsertModeKeysFn(cm),
                doEx: doExFn(cm),
                assertCursorAt: assertCursorAtFn(cm),
                fakeOpenDialog: fakeOpenDialog,
                fakeOpenNotification: fakeOpenNotification,
                getRegisterController: function() {
                  return CodeMirror.Vim.getRegisterController();
                }
              }
              CodeMirror.Vim.resetVimGlobalState_();
              var successful = false;
              var savedOpenNotification = cm.openNotification;
              try {
                run(cm, vim, helpers);
                successful = true;
              } finally {
                cm.openNotification = savedOpenNotification;
                if (!successful || verbose) {
                  place.style.visibility = "visible";
                } else {
                  place.removeChild(cm.getWrapperElement());
                }
              }
            }, expectedFail);
          };
          testVim('qq@q', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'q', 'l', 'l', 'q');
            helpers.assertCursorAt(0,2);
            helpers.doKeys('@', 'q');
            helpers.assertCursorAt(0,4);
          }, { value: '            '});
          testVim('@@', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'q', 'l', 'l', 'q');
            helpers.assertCursorAt(0,2);
            helpers.doKeys('@', 'q');
            helpers.assertCursorAt(0,4);
            helpers.doKeys('@', '@');
            helpers.assertCursorAt(0,6);
          }, { value: '            '});
          var jumplistScene = ''+
            'word\n'+
            '(word)\n'+
            '{word\n'+
            'word.\n'+
            '\n'+
            'word search\n'+
            '}word\n'+
            'word\n'+
            'word\n';
          function testJumplist(name, keys, endPos, startPos, dialog) {
            endPos = makeCursor(endPos[0], endPos[1]);
            startPos = makeCursor(startPos[0], startPos[1]);
            testVim(name, function(cm, vim, helpers) {
              CodeMirror.Vim.resetVimGlobalState_();
              if(dialog)cm.openDialog = helpers.fakeOpenDialog('word');
              cm.setCursor(startPos);
              helpers.doKeys.apply(null, keys);
              helpers.assertCursorAt(endPos);
            }, {value: jumplistScene});
          };
          testJumplist('jumplist_H', ['H', '<C-o>'], [5,2], [5,2]);
          testJumplist('jumplist_M', ['M', '<C-o>'], [2,2], [2,2]);
          testJumplist('jumplist_L', ['L', '<C-o>'], [2,2], [2,2]);
          testJumplist('jumplist_[[', ['[', '[', '<C-o>'], [5,2], [5,2]);
          testJumplist('jumplist_]]', [']', ']', '<C-o>'], [2,2], [2,2]);
          testJumplist('jumplist_G', ['G', '<C-o>'], [5,2], [5,2]);
          testJumplist('jumplist_gg', ['g', 'g', '<C-o>'], [5,2], [5,2]);
          testJumplist('jumplist_%', ['%', '<C-o>'], [1,5], [1,5]);
          testJumplist('jumplist_{', ['{', '<C-o>'], [1,5], [1,5]);
          testJumplist('jumplist_}', ['}', '<C-o>'], [1,5], [1,5]);
          testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', '<C-i>'], [1,0], [1,5]);
          testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', '<C-i>'], [1,5], [1,5]);
          testJumplist('jumplist_*_cachedCursor', ['*', '<C-o>'], [1,3], [1,3]);
          testJumplist('jumplist_#_cachedCursor', ['#', '<C-o>'], [1,3], [1,3]);
          testJumplist('jumplist_n', ['#', 'n', '<C-o>'], [1,1], [2,3]);
          testJumplist('jumplist_N', ['#', 'N', '<C-o>'], [1,1], [2,3]);
          testJumplist('jumplist_repeat_<c-o>', ['*', '*', '*', '3', '<C-o>'], [2,3], [2,3]);
          testJumplist('jumplist_repeat_<c-i>', ['*', '*', '*', '3', '<C-o>', '2', '<C-i>'], [5,0], [2,3]);
          testJumplist('jumplist_repeated_motion', ['3', '*', '<C-o>'], [2,3], [2,3]);
          testJumplist('jumplist_/', ['/', '<C-o>'], [2,3], [2,3], 'dialog');
          testJumplist('jumplist_?', ['?', '<C-o>'], [2,3], [2,3], 'dialog');
          testJumplist('jumplist_skip_delted_mark<c-o>',
                       ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-o>', '<C-o>'],
                       [0,2], [0,2]);
          testJumplist('jumplist_skip_delted_mark<c-i>',
                       ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-i>', '<C-i>'],
                       [1,0], [0,2]);
          
          /**
           * @param name Name of the test
           * @param keys An array of keys or a string with a single key to simulate.
           * @param endPos The expected end position of the cursor.
           * @param startPos The position the cursor should start at, defaults to 0, 0.
           */
          function testMotion(name, keys, endPos, startPos) {
            testVim(name, function(cm, vim, helpers) {
              if (!startPos) {
                startPos = { line: 0, ch: 0 };
              }
              cm.setCursor(startPos);
              helpers.doKeys(keys);
              helpers.assertCursorAt(endPos);
            });
          };
          
          function makeCursor(line, ch) {
            return { line: line, ch: ch };
          };
          
          function offsetCursor(cur, offsetLine, offsetCh) {
            return { line: cur.line + offsetLine, ch: cur.ch + offsetCh };
          };
          
          // Motion tests
          testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4));
          testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4));
          testMotion('h', 'h', makeCursor(0, 0), word1.start);
          testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end);
          testMotion('l', 'l', makeCursor(0, 1));
          testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2));
          testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end);
          testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end);
          testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument);
          testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end);
          testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4));
          testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4));
          testMotion('w', 'w', word1.start);
          testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2));
          testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51));
          testMotion('w_repeat', ['2', 'w'], word2.start);
          testMotion('w_wrap', ['w'], word3.start, word2.start);
          testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument);
          testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0));
          testMotion('W', 'W', bigWord1.start);
          testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start);
          testMotion('e', 'e', word1.end);
          testMotion('e_repeat', ['2', 'e'], word2.end);
          testMotion('e_wrap', 'e', word3.end, word2.end);
          testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument);
          testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0));
          testMotion('b', 'b', word3.start, word3.end);
          testMotion('b_repeat', ['2', 'b'], word2.start, word3.end);
          testMotion('b_wrap', 'b', word2.start, word3.start);
          testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0));
          testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument);
          testMotion('ge', ['g', 'e'], word2.end, word3.end);
          testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start);
          testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start);
          testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0),
              makeCursor(0, 0));
          testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument);
          testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart),
              makeCursor(3, 1));
          testMotion('gg_repeat', ['3', 'g', 'g'],
              makeCursor(lines[2].line, lines[2].textStart));
          testMotion('G', 'G',
              makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart),
              makeCursor(3, 1));
          testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line,
              lines[2].textStart));
          // TODO: Make the test code long enough to test Ctrl-F and Ctrl-B.
          testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8));
          testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8));
          testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8));
          testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4));
          testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8));
          testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1));
          testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1),
              makeCursor(0, 3));
          testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0));
          testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]);
          testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0));
          testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1),
              makeCursor(charLine.line, 0));
          testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1),
              pChars[0]);
          testMotion('F', ['F', 'p'], pChars[0], pChars[1]);
          testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]);
          testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]);
          testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]);
          testMotion('%_parens', ['%'], parens1.end, parens1.start);
          testMotion('%_squares', ['%'], squares1.end, squares1.start);
          testMotion('%_braces', ['%'], curlys1.end, curlys1.start);
          testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start);
          testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start);
          testVim('%_seek_skip', function(cm, vim, helpers) {
            cm.setCursor(0,0);
            helpers.doKeys(['%']);
            helpers.assertCursorAt(0,9);
          }, {value:'01234"("()'});
          testVim('%_skip_string', function(cm, vim, helpers) {
            cm.setCursor(0,0);
            helpers.doKeys(['%']);
            helpers.assertCursorAt(0,4);
            cm.setCursor(0,2);
            helpers.doKeys(['%']);
            helpers.assertCursorAt(0,0);
          }, {value:'(")")'});
          (')')
          testVim('%_skip_comment', function(cm, vim, helpers) {
            cm.setCursor(0,0);
            helpers.doKeys(['%']);
            helpers.assertCursorAt(0,6);
            cm.setCursor(0,3);
            helpers.doKeys(['%']);
            helpers.assertCursorAt(0,0);
          }, {value:'(/*)*/)'});
          // Make sure that moving down after going to the end of a line always leaves you
          // at the end of a line, but preserves the offset in other cases
          testVim('Changing lines after Eol operation', function(cm, vim, helpers) {
            cm.setCursor(0,0);
            helpers.doKeys(['$']);
            helpers.doKeys(['j']);
            // After moving to Eol and then down, we should be at Eol of line 2
            helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 });
            helpers.doKeys(['j']);
            // After moving down, we should be at Eol of line 3
            helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 });
            helpers.doKeys(['h']);
            helpers.doKeys(['j']);
            // After moving back one space and then down, since line 4 is shorter than line 2, we should
            // be at Eol of line 2 - 1
            helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 });
            helpers.doKeys(['j']);
            helpers.doKeys(['j']);
            // After moving down again, since line 3 has enough characters, we should be back to the
            // same place we were at on line 1
            helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 });
          });
          //making sure gj and gk recover from clipping
          testVim('gj_gk_clipping', function(cm,vim,helpers){
            cm.setCursor(0, 1);
            helpers.doKeys('g','j','g','j');
            helpers.assertCursorAt(2, 1);
            helpers.doKeys('g','k','g','k');
            helpers.assertCursorAt(0, 1);
          },{value: 'line 1\n\nline 2'});
          //testing a mix of j/k and gj/gk
          testVim('j_k_and_gj_gk', function(cm,vim,helpers){
            cm.setSize(120);
            cm.setCursor(0, 0);
            //go to the last character on the first line
            helpers.doKeys('$');
            //move up/down on the column within the wrapped line
            //side-effect: cursor is not locked to eol anymore
            helpers.doKeys('g','k');
            var cur=cm.getCursor();
            eq(cur.line,0);
            is((cur.ch<176),'gk didn\'t move cursor back (1)');
            helpers.doKeys('g','j');
            helpers.assertCursorAt(0, 176);
            //should move to character 177 on line 2 (j/k preserve character index within line)
            helpers.doKeys('j');
            //due to different line wrapping, the cursor can be on a different screen-x now
            //gj and gk preserve screen-x on movement, much like moveV
            helpers.doKeys('3','g','k');
            cur=cm.getCursor();
            eq(cur.line,1);
            is((cur.ch<176),'gk didn\'t move cursor back (2)');
            helpers.doKeys('g','j','2','g','j');
            //should return to the same character-index
            helpers.doKeys('k');
            helpers.assertCursorAt(0, 176);
          },{ lineWrapping:true, value: 'This line is intentially long to test movement of gj and gk over wrapped lines. I will start on the end of this line, then make a step up and back to set the origin for j and k.\nThis line is supposed to be even longer than the previous. I will jump here and make another wiggle with gj and gk, before I jump back to the line above. Both wiggles should not change my cursor\'s target character but both j/k and gj/gk change each other\'s reference position.'});
          testVim('gj_gk', function(cm, vim, helpers) {
            if (phantom) return;
            cm.setSize(120);
            // Test top of document edge case.
            cm.setCursor(0, 4);
            helpers.doKeys('g', 'j');
            helpers.doKeys('10', 'g', 'k');
            helpers.assertCursorAt(0, 4);
          
            // Test moving down preserves column position.
            helpers.doKeys('g', 'j');
            var pos1 = cm.getCursor();
            var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4};
            helpers.doKeys('g', 'j');
            helpers.assertCursorAt(expectedPos2);
          
            // Move to the last character
            cm.setCursor(0, 0);
            // Move left to reset HSPos
            helpers.doKeys('h');
            // Test bottom of document edge case.
            helpers.doKeys('100', 'g', 'j');
            var endingPos = cm.getCursor();
            is(endingPos != 0, 'gj should not be on wrapped line 0');
            var topLeftCharCoords = cm.charCoords(makeCursor(0, 0));
            var endingCharCoords = cm.charCoords(endingPos);
            is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0');
          },{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' });
          testVim('}', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('}');
            helpers.assertCursorAt(1, 0);
            cm.setCursor(0, 0);
            helpers.doKeys('2', '}');
            helpers.assertCursorAt(4, 0);
            cm.setCursor(0, 0);
            helpers.doKeys('6', '}');
            helpers.assertCursorAt(5, 0);
          }, { value: 'a\n\nb\nc\n\nd' });
          testVim('{', function(cm, vim, helpers) {
            cm.setCursor(5, 0);
            helpers.doKeys('{');
            helpers.assertCursorAt(4, 0);
            cm.setCursor(5, 0);
            helpers.doKeys('2', '{');
            helpers.assertCursorAt(1, 0);
            cm.setCursor(5, 0);
            helpers.doKeys('6', '{');
            helpers.assertCursorAt(0, 0);
          }, { value: 'a\n\nb\nc\n\nd' });
          testVim('paragraph_motions', function(cm, vim, helpers) {
            cm.setCursor(10, 0);
            helpers.doKeys('{');
            helpers.assertCursorAt(4, 0);
            helpers.doKeys('{');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('2', '}');
            helpers.assertCursorAt(7, 0);
            helpers.doKeys('2', '}');
            helpers.assertCursorAt(16, 0);
          
            cm.setCursor(9, 0);
            helpers.doKeys('}');
            helpers.assertCursorAt(14, 0);
          
            cm.setCursor(6, 0);
            helpers.doKeys('}');
            helpers.assertCursorAt(7, 0);
          
            // ip inside empty space
            cm.setCursor(10, 0);
            helpers.doKeys('v', 'i', 'p');
            eqPos(Pos(7, 0), cm.getCursor('anchor'));
            eqPos(Pos(12, 0), cm.getCursor('head'));
            helpers.doKeys('i', 'p');
            eqPos(Pos(7, 0), cm.getCursor('anchor'));
            eqPos(Pos(13, 1), cm.getCursor('head'));
            helpers.doKeys('2', 'i', 'p');
            eqPos(Pos(7, 0), cm.getCursor('anchor'));
            eqPos(Pos(16, 1), cm.getCursor('head'));
          
            // should switch to visualLine mode
            cm.setCursor(14, 0);
            helpers.doKeys('<Esc>', 'v', 'i', 'p');
            helpers.assertCursorAt(14, 0);
          
            cm.setCursor(14, 0);
            helpers.doKeys('<Esc>', 'V', 'i', 'p');
            eqPos(Pos(16, 1), cm.getCursor('head'));
          
            // ap inside empty space
            cm.setCursor(10, 0);
            helpers.doKeys('<Esc>', 'v', 'a', 'p');
            eqPos(Pos(7, 0), cm.getCursor('anchor'));
            eqPos(Pos(13, 1), cm.getCursor('head'));
            helpers.doKeys('a', 'p');
            eqPos(Pos(7, 0), cm.getCursor('anchor'));
            eqPos(Pos(16, 1), cm.getCursor('head'));
          
            cm.setCursor(13, 0);
            helpers.doKeys('v', 'a', 'p');
            eqPos(Pos(13, 0), cm.getCursor('anchor'));
            eqPos(Pos(14, 0), cm.getCursor('head'));
          
            cm.setCursor(16, 0);
            helpers.doKeys('v', 'a', 'p');
            eqPos(Pos(14, 0), cm.getCursor('anchor'));
            eqPos(Pos(16, 1), cm.getCursor('head'));
          
            cm.setCursor(0, 0);
            helpers.doKeys('v', 'a', 'p');
            eqPos(Pos(0, 0), cm.getCursor('anchor'));
            eqPos(Pos(4, 0), cm.getCursor('head'));
          
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'i', 'p');
            var register = helpers.getRegisterController().getRegister();
            eq('a\na\n', register.toString());
            is(register.linewise);
            helpers.doKeys('3', 'j', 'p');
            helpers.doKeys('y', 'i', 'p');
            is(register.linewise);
            eq('b\na\na\nc\n', register.toString());
          }, { value: 'a\na\n\n\n\nb\nc\n\n\n\n\n\n\nd\n\ne\nf' });
          
          // Operator tests
          testVim('dl', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 0);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'l');
            eq('word1 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(' ', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1 ' });
          testVim('dl_eol', function(cm, vim, helpers) {
            cm.setCursor(0, 6);
            helpers.doKeys('d', 'l');
            eq(' word1', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(' ', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 5);
          }, { value: ' word1 ' });
          testVim('dl_repeat', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 0);
            cm.setCursor(curStart);
            helpers.doKeys('2', 'd', 'l');
            eq('ord1 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(' w', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1 ' });
          testVim('dh', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'h');
            eq(' wrd1 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('o', register.toString());
            is(!register.linewise);
            eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor());
          }, { value: ' word1 ' });
          testVim('dj', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'j');
            eq(' word3', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(' word1\nword2\n', register.toString());
            is(register.linewise);
            helpers.assertCursorAt(0, 1);
          }, { value: ' word1\nword2\n word3' });
          testVim('dj_end_of_document', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'j');
            eq(' word1 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 3);
          }, { value: ' word1 ' });
          testVim('dk', function(cm, vim, helpers) {
            var curStart = makeCursor(1, 3);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'k');
            eq(' word3', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(' word1\nword2\n', register.toString());
            is(register.linewise);
            helpers.assertCursorAt(0, 1);
          }, { value: ' word1\nword2\n word3' });
          testVim('dk_start_of_document', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'k');
            eq(' word1 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 3);
          }, { value: ' word1 ' });
          testVim('dw_space', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 0);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'w');
            eq('word1 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(' ', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1 ' });
          testVim('dw_word', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 1);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'w');
            eq(' word2', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1 ', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1 word2' });
          testVim('dw_unicode_word', function(cm, vim, helpers) {
            helpers.doKeys('d', 'w');
            eq(cm.getValue().length, 10);
            helpers.doKeys('d', 'w');
            eq(cm.getValue().length, 6);
            helpers.doKeys('d', 'w');
            eq(cm.getValue().length, 5);
            helpers.doKeys('d', 'e');
            eq(cm.getValue().length, 2);
          }, { value: '  \u0562\u0561\u0580\u0587\xbbe\xb5g  ' });
          testVim('dw_only_word', function(cm, vim, helpers) {
            // Test that if there is only 1 word left, dw deletes till the end of the
            // line.
            cm.setCursor(0, 1);
            helpers.doKeys('d', 'w');
            eq(' ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1 ', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 0);
          }, { value: ' word1 ' });
          testVim('dw_eol', function(cm, vim, helpers) {
            // Assert that dw does not delete the newline if last word to delete is at end
            // of line.
            cm.setCursor(0, 1);
            helpers.doKeys('d', 'w');
            eq(' \nword2', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 0);
          }, { value: ' word1\nword2' });
          testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) {
            // Assert that dw does not delete the newline if last word to delete is at end
            // of line and it is followed by multiple newlines.
            cm.setCursor(0, 1);
            helpers.doKeys('d', 'w');
            eq(' \n\nword2', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 0);
          }, { value: ' word1\n\nword2' });
          testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'w');
            eq('  \nword', cm.getValue());
          }, { value: '\n  \nword' });
          testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'w');
            eq('word', cm.getValue());
          }, { value: '\nword' });
          testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'w');
            eq('\n', cm.getValue());
          }, { value: '\n\n' });
          testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'w');
            eq('\n   \n', cm.getValue());
          }, { value: '  \n   \n' });
          testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'w');
            eq('\n\n', cm.getValue());
          }, { value: '  \n\n' });
          testVim('dw_word_whitespace_word', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'w');
            eq('\n   \nword2', cm.getValue());
          }, { value: 'word1\n   \nword2'})
          testVim('dw_end_of_document', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('d', 'w');
            eq('\nab', cm.getValue());
          }, { value: '\nabc' });
          testVim('dw_repeat', function(cm, vim, helpers) {
            // Assert that dw does delete newline if it should go to the next line, and
            // that repeat works properly.
            cm.setCursor(0, 1);
            helpers.doKeys('d', '2', 'w');
            eq(' ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1\nword2', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 0);
          }, { value: ' word1\nword2' });
          testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'e');
            eq('\n\n', cm.getValue());
          }, { value: 'word\n\n' });
          testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            helpers.doKeys('d', 'e');
            eq('wor', cm.getValue());
          }, { value: 'word\n\n\n' });
          testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'e');
            eq('', cm.getValue());
          }, { value: '   \n\n\n' });
          testVim('de_end_of_document', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('d', 'e');
            eq('\nab', cm.getValue());
          }, { value: '\nabc' });
          testVim('db_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('d', 'b');
            eq('\n\n', cm.getValue());
          }, { value: '\n\n\n' });
          testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('d', 'b');
            eq('\nword', cm.getValue());
          }, { value: '\n\nword' });
          testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(2, 3);
            helpers.doKeys('d', 'b');
            eq('\n\nd', cm.getValue());
          }, { value: '\n\nword' });
          testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('d', 'b');
            eq('', cm.getValue());
          }, { value: '\n   \n' });
          testVim('db_start_of_document', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'b');
            eq('abc\n', cm.getValue());
          }, { value: 'abc\n' });
          testVim('dge_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(1, 0);
            helpers.doKeys('d', 'g', 'e');
            // Note: In real VIM the result should be '', but it's not quite consistent,
            // since 2 newlines are deleted. But in the similar case of word\n\n, only
            // 1 newline is deleted. We'll diverge from VIM's behavior since it's much
            // easier this way.
            eq('\n', cm.getValue());
          }, { value: '\n\n' });
          testVim('dge_word_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(1, 0);
            helpers.doKeys('d', 'g', 'e');
            eq('wor\n', cm.getValue());
          }, { value: 'word\n\n'});
          testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('d', 'g', 'e');
            eq('', cm.getValue());
          }, { value: '\n  \n' });
          testVim('dge_start_of_document', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('d', 'g', 'e');
            eq('bc\n', cm.getValue());
          }, { value: 'abc\n' });
          testVim('d_inclusive', function(cm, vim, helpers) {
            // Assert that when inclusive is set, the character the cursor is on gets
            // deleted too.
            var curStart = makeCursor(0, 1);
            cm.setCursor(curStart);
            helpers.doKeys('d', 'e');
            eq('  ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1 ' });
          testVim('d_reverse', function(cm, vim, helpers) {
            // Test that deleting in reverse works.
            cm.setCursor(1, 0);
            helpers.doKeys('d', 'b');
            eq(' word2 ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1\n', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 1);
          }, { value: ' word1\nword2 ' });
          testVim('dd', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
              { line: 1, ch: 0 });
            var expectedLineCount = cm.lineCount() - 1;
            helpers.doKeys('d', 'd');
            eq(expectedLineCount, cm.lineCount());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedBuffer, register.toString());
            is(register.linewise);
            helpers.assertCursorAt(0, lines[1].textStart);
          });
          testVim('dd_prefix_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
              { line: 2, ch: 0 });
            var expectedLineCount = cm.lineCount() - 2;
            helpers.doKeys('2', 'd', 'd');
            eq(expectedLineCount, cm.lineCount());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedBuffer, register.toString());
            is(register.linewise);
            helpers.assertCursorAt(0, lines[2].textStart);
          });
          testVim('dd_motion_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
              { line: 2, ch: 0 });
            var expectedLineCount = cm.lineCount() - 2;
            helpers.doKeys('d', '2', 'd');
            eq(expectedLineCount, cm.lineCount());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedBuffer, register.toString());
            is(register.linewise);
            helpers.assertCursorAt(0, lines[2].textStart);
          });
          testVim('dd_multiply_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
              { line: 6, ch: 0 });
            var expectedLineCount = cm.lineCount() - 6;
            helpers.doKeys('2', 'd', '3', 'd');
            eq(expectedLineCount, cm.lineCount());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedBuffer, register.toString());
            is(register.linewise);
            helpers.assertCursorAt(0, lines[6].textStart);
          });
          testVim('dd_lastline', function(cm, vim, helpers) {
            cm.setCursor(cm.lineCount(), 0);
            var expectedLineCount = cm.lineCount() - 1;
            helpers.doKeys('d', 'd');
            eq(expectedLineCount, cm.lineCount());
            helpers.assertCursorAt(cm.lineCount() - 1, 0);
          });
          testVim('dd_only_line', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            var expectedRegister = cm.getValue() + "\n";
            helpers.doKeys('d','d');
            eq(1, cm.lineCount());
            eq('', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedRegister, register.toString());
          }, { value: "thisistheonlyline" });
          // Yank commands should behave the exact same as d commands, expect that nothing
          // gets deleted.
          testVim('yw_repeat', function(cm, vim, helpers) {
            // Assert that yw does yank newline if it should go to the next line, and
            // that repeat works properly.
            var curStart = makeCursor(0, 1);
            cm.setCursor(curStart);
            helpers.doKeys('y', '2', 'w');
            eq(' word1\nword2', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1\nword2', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1\nword2' });
          testVim('yy_multiply_repeat', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
              { line: 6, ch: 0 });
            var expectedLineCount = cm.lineCount();
            helpers.doKeys('2', 'y', '3', 'y');
            eq(expectedLineCount, cm.lineCount());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedBuffer, register.toString());
            is(register.linewise);
            eqPos(curStart, cm.getCursor());
          });
          // Change commands behave like d commands except that it also enters insert
          // mode. In addition, when the change is linewise, an additional newline is
          // inserted so that insert mode starts on that line.
          testVim('cw', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('c', '2', 'w');
            eq(' word3', cm.getValue());
            helpers.assertCursorAt(0, 0);
          }, { value: 'word1 word2 word3'});
          testVim('cw_repeat', function(cm, vim, helpers) {
            // Assert that cw does delete newline if it should go to the next line, and
            // that repeat works properly.
            var curStart = makeCursor(0, 1);
            cm.setCursor(curStart);
            helpers.doKeys('c', '2', 'w');
            eq(' ', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('word1\nword2', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
            eq('vim-insert', cm.getOption('keyMap'));
          }, { value: ' word1\nword2' });
          testVim('cc_multiply_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
              { line: 6, ch: 0 });
            var expectedLineCount = cm.lineCount() - 5;
            helpers.doKeys('2', 'c', '3', 'c');
            eq(expectedLineCount, cm.lineCount());
            var register = helpers.getRegisterController().getRegister();
            eq(expectedBuffer, register.toString());
            is(register.linewise);
            eq('vim-insert', cm.getOption('keyMap'));
          });
          testVim('ct', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('c', 't', 'w');
            eq('  word1  word3', cm.getValue());
            helpers.doKeys('<Esc>', 'c', '|');
            eq(' word3', cm.getValue());
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('<Esc>', '2', 'u', 'w', 'h');
            helpers.doKeys('c', '2', 'g', 'e');
            eq('  wordword3', cm.getValue());
          }, { value: '  word1  word2  word3'});
          testVim('cc_should_not_append_to_document', function(cm, vim, helpers) {
            var expectedLineCount = cm.lineCount();
            cm.setCursor(cm.lastLine(), 0);
            helpers.doKeys('c', 'c');
            eq(expectedLineCount, cm.lineCount());
          });
          function fillArray(val, times) {
            var arr = [];
            for (var i = 0; i < times; i++) {
              arr.push(val);
            }
            return arr;
          }
          testVim('c_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'l', 'c');
            var replacement = fillArray('hello', 3);
            cm.replaceSelections(replacement);
            eq('1hello\n5hello\nahellofg', cm.getValue());
            helpers.doKeys('<Esc>');
            cm.setCursor(2, 3);
            helpers.doKeys('<C-v>', '2', 'k', 'h', 'C');
            replacement = fillArray('world', 3);
            cm.replaceSelections(replacement);
            eq('1hworld\n5hworld\nahworld', cm.getValue());
          }, {value: '1234\n5678\nabcdefg'});
          testVim('c_visual_block_replay', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'c');
            var replacement = fillArray('fo', 3);
            cm.replaceSelections(replacement);
            eq('1fo4\n5fo8\nafodefg', cm.getValue());
            helpers.doKeys('<Esc>');
            cm.setCursor(0, 0);
            helpers.doKeys('.');
            eq('foo4\nfoo8\nfoodefg', cm.getValue());
          }, {value: '1234\n5678\nabcdefg'});
          
          testVim('d_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'l', 'd');
            eq('1\n5\nafg', cm.getValue());
          }, {value: '1234\n5678\nabcdefg'});
          testVim('D_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'D');
            eq('1\n5\na', cm.getValue());
          }, {value: '1234\n5678\nabcdefg'});
          
          // Swapcase commands edit in place and do not modify registers.
          testVim('g~w_repeat', function(cm, vim, helpers) {
            // Assert that dw does delete newline if it should go to the next line, and
            // that repeat works properly.
            var curStart = makeCursor(0, 1);
            cm.setCursor(curStart);
            helpers.doKeys('g', '~', '2', 'w');
            eq(' WORD1\nWORD2', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1\nword2' });
          testVim('g~g~', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            var expectedLineCount = cm.lineCount();
            var expectedValue = cm.getValue().toUpperCase();
            helpers.doKeys('2', 'g', '~', '3', 'g', '~');
            eq(expectedValue, cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
          }, { value: ' word1\nword2\nword3\nword4\nword5\nword6' });
          testVim('gu_and_gU', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 7);
            var value = cm.getValue();
            cm.setCursor(curStart);
            helpers.doKeys('2', 'g', 'U', 'w');
            eq(cm.getValue(), 'wa wb xX WC wd');
            eqPos(curStart, cm.getCursor());
            helpers.doKeys('2', 'g', 'u', 'w');
            eq(cm.getValue(), value);
          
            helpers.doKeys('2', 'g', 'U', 'B');
            eq(cm.getValue(), 'wa WB Xx wc wd');
            eqPos(makeCursor(0, 3), cm.getCursor());
          
            cm.setCursor(makeCursor(0, 4));
            helpers.doKeys('g', 'u', 'i', 'w');
            eq(cm.getValue(), 'wa wb Xx wc wd');
            eqPos(makeCursor(0, 3), cm.getCursor());
          
            // TODO: support gUgU guu
            // eqPos(makeCursor(0, 0), cm.getCursor());
          
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
          }, { value: 'wa wb xx wc wd' });
          testVim('visual_block_~', function(cm, vim, helpers) {
            cm.setCursor(1, 1);
            helpers.doKeys('<C-v>', 'l', 'l', 'j', '~');
            helpers.assertCursorAt(1, 1);
            eq('hello\nwoRLd\naBCDe', cm.getValue());
            cm.setCursor(2, 0);
            helpers.doKeys('v', 'l', 'l', '~');
            helpers.assertCursorAt(2, 0);
            eq('hello\nwoRLd\nAbcDe', cm.getValue());
          },{value: 'hello\nwOrld\nabcde' });
          testVim('._swapCase_visualBlock', function(cm, vim, helpers) {
            helpers.doKeys('<C-v>', 'j', 'j', 'l', '~');
            cm.setCursor(0, 3);
            helpers.doKeys('.');
            eq('HelLO\nWorLd\nAbcdE', cm.getValue());
          },{value: 'hEllo\nwOrlD\naBcDe' });
          testVim('._delete_visualBlock', function(cm, vim, helpers) {
            helpers.doKeys('<C-v>', 'j', 'x');
            eq('ive\ne\nsome\nsugar', cm.getValue());
            helpers.doKeys('.');
            eq('ve\n\nsome\nsugar', cm.getValue());
            helpers.doKeys('j', 'j', '.');
            eq('ve\n\nome\nugar', cm.getValue());
            helpers.doKeys('u', '<C-r>', '.');
            eq('ve\n\nme\ngar', cm.getValue());
          },{value: 'give\nme\nsome\nsugar' });
          testVim('>{motion}', function(cm, vim, helpers) {
            cm.setCursor(1, 3);
            var expectedLineCount = cm.lineCount();
            var expectedValue = '   word1\n  word2\nword3 ';
            helpers.doKeys('>', 'k');
            eq(expectedValue, cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 3);
          }, { value: ' word1\nword2\nword3 ', indentUnit: 2 });
          testVim('>>', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedLineCount = cm.lineCount();
            var expectedValue = '   word1\n  word2\nword3 ';
            helpers.doKeys('2', '>', '>');
            eq(expectedValue, cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 3);
          }, { value: ' word1\nword2\nword3 ', indentUnit: 2 });
          testVim('<{motion}', function(cm, vim, helpers) {
            cm.setCursor(1, 3);
            var expectedLineCount = cm.lineCount();
            var expectedValue = ' word1\nword2\nword3 ';
            helpers.doKeys('<', 'k');
            eq(expectedValue, cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 1);
          }, { value: '   word1\n  word2\nword3 ', indentUnit: 2 });
          testVim('<<', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            var expectedLineCount = cm.lineCount();
            var expectedValue = ' word1\nword2\nword3 ';
            helpers.doKeys('2', '<', '<');
            eq(expectedValue, cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 1);
          }, { value: '   word1\n  word2\nword3 ', indentUnit: 2 });
          
          // Edit tests
          function testEdit(name, before, pos, edit, after) {
            return testVim(name, function(cm, vim, helpers) {
                       var ch = before.search(pos)
                       var line = before.substring(0, ch).split('\n').length - 1;
                       if (line) {
                         ch = before.substring(0, ch).split('\n').pop().length;
                       }
                       cm.setCursor(line, ch);
                       helpers.doKeys.apply(this, edit.split(''));
                       eq(after, cm.getValue());
                     }, {value: before});
          }
          
          // These Delete tests effectively cover word-wise Change, Visual & Yank.
          // Tabs are used as differentiated whitespace to catch edge cases.
          // Normal word:
          testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz');
          testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz');
          testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz');
          testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz');
          testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz');
          testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz');
          testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz');
          testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz');
          testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz');
          testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz');
          testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t');
          testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo');
          testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.');
          testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.');
          // Big word:
          testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz');
          testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz');
          testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz');
          testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz');
          testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz');
          testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz');
          testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz');
          testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz');
          testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz');
          testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz');
          testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t');
          testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo');
          testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t');
          testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo');
          // Deleting text objects
          //    Open and close on same line
          testEdit('di(_open_spc', 'foo (bAr) baz', /\(/, 'di(', 'foo () baz');
          testEdit('di)_open_spc', 'foo (bAr) baz', /\(/, 'di)', 'foo () baz');
          testEdit('dib_open_spc', 'foo (bAr) baz', /\(/, 'dib', 'foo () baz');
          testEdit('da(_open_spc', 'foo (bAr) baz', /\(/, 'da(', 'foo  baz');
          testEdit('da)_open_spc', 'foo (bAr) baz', /\(/, 'da)', 'foo  baz');
          
          testEdit('di(_middle_spc', 'foo (bAr) baz', /A/, 'di(', 'foo () baz');
          testEdit('di)_middle_spc', 'foo (bAr) baz', /A/, 'di)', 'foo () baz');
          testEdit('da(_middle_spc', 'foo (bAr) baz', /A/, 'da(', 'foo  baz');
          testEdit('da)_middle_spc', 'foo (bAr) baz', /A/, 'da)', 'foo  baz');
          
          testEdit('di(_close_spc', 'foo (bAr) baz', /\)/, 'di(', 'foo () baz');
          testEdit('di)_close_spc', 'foo (bAr) baz', /\)/, 'di)', 'foo () baz');
          testEdit('da(_close_spc', 'foo (bAr) baz', /\)/, 'da(', 'foo  baz');
          testEdit('da)_close_spc', 'foo (bAr) baz', /\)/, 'da)', 'foo  baz');
          
          //  delete around and inner b.
          testEdit('dab_on_(_should_delete_around_()block', 'o( in(abc) )', /\(a/, 'dab', 'o( in )');
          
          //  delete around and inner B.
          testEdit('daB_on_{_should_delete_around_{}block', 'o{ in{abc} }', /{a/, 'daB', 'o{ in }');
          testEdit('diB_on_{_should_delete_inner_{}block', 'o{ in{abc} }', /{a/, 'diB', 'o{ in{} }');
          
          testEdit('da{_on_{_should_delete_inner_block', 'o{ in{abc} }', /{a/, 'da{', 'o{ in }');
          testEdit('di[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'di[', 'foo (bAr) baz');
          testEdit('di[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'di[', 'foo (bAr) baz');
          testEdit('da[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'da[', 'foo (bAr) baz');
          testEdit('da[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'da[', 'foo (bAr) baz');
          testMotion('di(_outside_should_stay', ['d', 'i', '('], { line: 0, ch: 0}, { line: 0, ch: 0});
          
          //  Open and close on different lines, equally indented
          testEdit('di{_middle_spc', 'a{\n\tbar\n}b', /r/, 'di{', 'a{}b');
          testEdit('di}_middle_spc', 'a{\n\tbar\n}b', /r/, 'di}', 'a{}b');
          testEdit('da{_middle_spc', 'a{\n\tbar\n}b', /r/, 'da{', 'ab');
          testEdit('da}_middle_spc', 'a{\n\tbar\n}b', /r/, 'da}', 'ab');
          testEdit('daB_middle_spc', 'a{\n\tbar\n}b', /r/, 'daB', 'ab');
          
          // open and close on diff lines, open indented less than close
          testEdit('di{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di{', 'a{}b');
          testEdit('di}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di}', 'a{}b');
          testEdit('da{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da{', 'ab');
          testEdit('da}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da}', 'ab');
          
          // open and close on diff lines, open indented more than close
          testEdit('di[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di[', 'a\t[]b');
          testEdit('di]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di]', 'a\t[]b');
          testEdit('da[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da[', 'a\tb');
          testEdit('da]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da]', 'a\tb');
          
          function testSelection(name, before, pos, keys, sel) {
            return testVim(name, function(cm, vim, helpers) {
                       var ch = before.search(pos)
                       var line = before.substring(0, ch).split('\n').length - 1;
                       if (line) {
                         ch = before.substring(0, ch).split('\n').pop().length;
                       }
                       cm.setCursor(line, ch);
                       helpers.doKeys.apply(this, keys.split(''));
                       eq(sel, cm.getSelection());
                     }, {value: before});
          }
          testSelection('viw_middle_spc', 'foo \tbAr\t baz', /A/, 'viw', 'bAr');
          testSelection('vaw_middle_spc', 'foo \tbAr\t baz', /A/, 'vaw', 'bAr\t ');
          testSelection('viw_middle_punct', 'foo \tbAr,\t baz', /A/, 'viw', 'bAr');
          testSelection('vaW_middle_punct', 'foo \tbAr,\t baz', /A/, 'vaW', 'bAr,\t ');
          testSelection('viw_start_spc', 'foo \tbAr\t baz', /b/, 'viw', 'bAr');
          testSelection('viw_end_spc', 'foo \tbAr\t baz', /r/, 'viw', 'bAr');
          testSelection('viw_eol', 'foo \tbAr', /r/, 'viw', 'bAr');
          testSelection('vi{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'vi{', '\n\tbar\n\t');
          testSelection('va{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'va{', '{\n\tbar\n\t}');
          
          testVim('mouse_select', function(cm, vim, helpers) {
            cm.setSelection(Pos(0, 2), Pos(0, 4), {origin: '*mouse'});
            is(cm.state.vim.visualMode);
            is(!cm.state.vim.visualLine);
            is(!cm.state.vim.visualBlock);
            helpers.doKeys('<Esc>');
            is(!cm.somethingSelected());
            helpers.doKeys('g', 'v');
            eq('cd', cm.getSelection());
          }, {value: 'abcdef'});
          
          // Operator-motion tests
          testVim('D', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            helpers.doKeys('D');
            eq(' wo\nword2\n word3', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('rd1', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 2);
          }, { value: ' word1\nword2\n word3' });
          testVim('C', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            helpers.doKeys('C');
            eq(' wo\nword2\n word3', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('rd1', register.toString());
            is(!register.linewise);
            eqPos(curStart, cm.getCursor());
            eq('vim-insert', cm.getOption('keyMap'));
          }, { value: ' word1\nword2\n word3' });
          testVim('Y', function(cm, vim, helpers) {
            var curStart = makeCursor(0, 3);
            cm.setCursor(curStart);
            helpers.doKeys('Y');
            eq(' word1\nword2\n word3', cm.getValue());
            var register = helpers.getRegisterController().getRegister();
            eq('rd1', register.toString());
            is(!register.linewise);
            helpers.assertCursorAt(0, 3);
          }, { value: ' word1\nword2\n word3' });
          testVim('~', function(cm, vim, helpers) {
            helpers.doKeys('3', '~');
            eq('ABCdefg', cm.getValue());
            helpers.assertCursorAt(0, 3);
          }, { value: 'abcdefg' });
          
          // Action tests
          testVim('ctrl-a', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-a>');
            eq('-9', cm.getValue());
            helpers.assertCursorAt(0, 1);
            helpers.doKeys('2','<C-a>');
            eq('-7', cm.getValue());
          }, {value: '-10'});
          testVim('ctrl-x', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-x>');
            eq('-1', cm.getValue());
            helpers.assertCursorAt(0, 1);
            helpers.doKeys('2','<C-x>');
            eq('-3', cm.getValue());
          }, {value: '0'});
          testVim('<C-x>/<C-a> search forward', function(cm, vim, helpers) {
            forEach(['<C-x>', '<C-a>'], function(key) {
              cm.setCursor(0, 0);
              helpers.doKeys(key);
              helpers.assertCursorAt(0, 5);
              helpers.doKeys('l');
              helpers.doKeys(key);
              helpers.assertCursorAt(0, 10);
              cm.setCursor(0, 11);
              helpers.doKeys(key);
              helpers.assertCursorAt(0, 11);
            });
          }, {value: '__jmp1 jmp2 jmp'});
          testVim('a', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('a');
            helpers.assertCursorAt(0, 2);
            eq('vim-insert', cm.getOption('keyMap'));
          });
          testVim('a_eol', function(cm, vim, helpers) {
            cm.setCursor(0, lines[0].length - 1);
            helpers.doKeys('a');
            helpers.assertCursorAt(0, lines[0].length);
            eq('vim-insert', cm.getOption('keyMap'));
          });
          testVim('A_endOfSelectedArea', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('v', 'j', 'l');
            helpers.doKeys('A');
            helpers.assertCursorAt(1, 2);
            eq('vim-insert', cm.getOption('keyMap'));
          }, {value: 'foo\nbar'});
          testVim('i', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('i');
            helpers.assertCursorAt(0, 1);
            eq('vim-insert', cm.getOption('keyMap'));
          });
          testVim('i_repeat', function(cm, vim, helpers) {
            helpers.doKeys('3', 'i');
            cm.replaceRange('test', cm.getCursor());
            helpers.doKeys('<Esc>');
            eq('testtesttest', cm.getValue());
            helpers.assertCursorAt(0, 11);
          }, { value: '' });
          testVim('i_repeat_delete', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('2', 'i');
            cm.replaceRange('z', cm.getCursor());
            helpers.doInsertModeKeys('Backspace', 'Backspace');
            helpers.doKeys('<Esc>');
            eq('abe', cm.getValue());
            helpers.assertCursorAt(0, 1);
          }, { value: 'abcde' });
          testVim('A', function(cm, vim, helpers) {
            helpers.doKeys('A');
            helpers.assertCursorAt(0, lines[0].length);
            eq('vim-insert', cm.getOption('keyMap'));
          });
          testVim('A_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'A');
            var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' ');
            replacement.pop();
            cm.replaceSelections(replacement);
            eq('testhello\nmehello\npleahellose', cm.getValue());
            helpers.doKeys('<Esc>');
            cm.setCursor(0, 0);
            helpers.doKeys('.');
            // TODO this doesn't work yet
            // eq('teshellothello\nme hello hello\nplehelloahellose', cm.getValue());
          }, {value: 'test\nme\nplease'});
          testVim('I', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('I');
            helpers.assertCursorAt(0, lines[0].textStart);
            eq('vim-insert', cm.getOption('keyMap'));
          });
          testVim('I_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('3', 'I');
            cm.replaceRange('test', cm.getCursor());
            helpers.doKeys('<Esc>');
            eq('testtesttestblah', cm.getValue());
            helpers.assertCursorAt(0, 11);
          }, { value: 'blah' });
          testVim('I_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'I');
            var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' ');
            replacement.pop();
            cm.replaceSelections(replacement);
            eq('hellotest\nhellome\nhelloplease', cm.getValue());
          }, {value: 'test\nme\nplease'});
          testVim('o', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('o');
            eq('word1\n\nword2', cm.getValue());
            helpers.assertCursorAt(1, 0);
            eq('vim-insert', cm.getOption('keyMap'));
          }, { value: 'word1\nword2' });
          testVim('o_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('3', 'o');
            cm.replaceRange('test', cm.getCursor());
            helpers.doKeys('<Esc>');
            eq('\ntest\ntest\ntest', cm.getValue());
            helpers.assertCursorAt(3, 3);
          }, { value: '' });
          testVim('O', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('O');
            eq('\nword1\nword2', cm.getValue());
            helpers.assertCursorAt(0, 0);
            eq('vim-insert', cm.getOption('keyMap'));
          }, { value: 'word1\nword2' });
          testVim('J', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('J');
            var expectedValue = 'word1  word2\nword3\n word4';
            eq(expectedValue, cm.getValue());
            helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1);
          }, { value: 'word1 \n    word2\nword3\n word4' });
          testVim('J_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('3', 'J');
            var expectedValue = 'word1  word2 word3\n word4';
            eq(expectedValue, cm.getValue());
            helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1);
          }, { value: 'word1 \n    word2\nword3\n word4' });
          testVim('p', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);
            helpers.doKeys('p');
            eq('__abc\ndef_', cm.getValue());
            helpers.assertCursorAt(1, 2);
          }, { value: '___' });
          testVim('p_register', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().getRegister('a').setText('abc\ndef', false);
            helpers.doKeys('"', 'a', 'p');
            eq('__abc\ndef_', cm.getValue());
            helpers.assertCursorAt(1, 2);
          }, { value: '___' });
          testVim('p_wrong_register', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().getRegister('a').setText('abc\ndef', false);
            helpers.doKeys('p');
            eq('___', cm.getValue());
            helpers.assertCursorAt(0, 1);
          }, { value: '___' });
          testVim('p_line', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().pushText('"', 'yank', '  a\nd\n', true);
            helpers.doKeys('2', 'p');
            eq('___\n  a\nd\n  a\nd', cm.getValue());
            helpers.assertCursorAt(1, 2);
          }, { value: '___' });
          testVim('p_lastline', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().pushText('"', 'yank', '  a\nd', true);
            helpers.doKeys('2', 'p');
            eq('___\n  a\nd\n  a\nd', cm.getValue());
            helpers.assertCursorAt(1, 2);
          }, { value: '___' });
          testVim(']p_first_indent_is_smaller', function(cm, vim, helpers) {
            helpers.getRegisterController().pushText('"', 'yank', '  abc\n    def\n', true);
            helpers.doKeys(']', 'p');
            eq('  ___\n  abc\n    def', cm.getValue());
          }, { value: '  ___' });
          testVim(']p_first_indent_is_larger', function(cm, vim, helpers) {
            helpers.getRegisterController().pushText('"', 'yank', '    abc\n  def\n', true);
            helpers.doKeys(']', 'p');
            eq('  ___\n  abc\ndef', cm.getValue());
          }, { value: '  ___' });
          testVim(']p_with_tab_indents', function(cm, vim, helpers) {
            helpers.getRegisterController().pushText('"', 'yank', '\t\tabc\n\t\t\tdef\n', true);
            helpers.doKeys(']', 'p');
            eq('\t___\n\tabc\n\t\tdef', cm.getValue());
          }, { value: '\t___', indentWithTabs: true});
          testVim(']p_with_spaces_translated_to_tabs', function(cm, vim, helpers) {
            helpers.getRegisterController().pushText('"', 'yank', '  abc\n    def\n', true);
            helpers.doKeys(']', 'p');
            eq('\t___\n\tabc\n\t\tdef', cm.getValue());
          }, { value: '\t___', indentWithTabs: true, tabSize: 2 });
          testVim('[p', function(cm, vim, helpers) {
            helpers.getRegisterController().pushText('"', 'yank', '  abc\n    def\n', true);
            helpers.doKeys('[', 'p');
            eq('  abc\n    def\n  ___', cm.getValue());
          }, { value: '  ___' });
          testVim('P', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);
            helpers.doKeys('P');
            eq('_abc\ndef__', cm.getValue());
            helpers.assertCursorAt(1, 3);
          }, { value: '___' });
          testVim('P_line', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.getRegisterController().pushText('"', 'yank', '  a\nd\n', true);
            helpers.doKeys('2', 'P');
            eq('  a\nd\n  a\nd\n___', cm.getValue());
            helpers.assertCursorAt(0, 2);
          }, { value: '___' });
          testVim('r', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('3', 'r', 'u');
            eq('wuuuet\nanother', cm.getValue(),'3r failed');
            helpers.assertCursorAt(0, 3);
            cm.setCursor(0, 4);
            helpers.doKeys('v', 'j', 'h', 'r', '<Space>');
            eq('wuuu  \n    her', cm.getValue(),'Replacing selection by space-characters failed');
          }, { value: 'wordet\nanother' });
          testVim('r_visual_block', function(cm, vim, helpers) {
            cm.setCursor(2, 3);
            helpers.doKeys('<C-v>', 'k', 'k', 'h', 'h', 'r', 'l');
            eq('1lll\n5lll\nalllefg', cm.getValue());
            helpers.doKeys('<C-v>', 'l', 'j', 'r', '<Space>');
            eq('1  l\n5  l\nalllefg', cm.getValue());
            cm.setCursor(2, 0);
            helpers.doKeys('o');
            helpers.doKeys('<Esc>');
            cm.replaceRange('\t\t', cm.getCursor());
            helpers.doKeys('<C-v>', 'h', 'h', 'r', 'r');
            eq('1  l\n5  l\nalllefg\nrrrrrrrr', cm.getValue());
          }, {value: '1234\n5678\nabcdefg'});
          testVim('R', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('R');
            helpers.assertCursorAt(0, 1);
            eq('vim-replace', cm.getOption('keyMap'));
            is(cm.state.overwrite, 'Setting overwrite state failed');
          });
          testVim('mark', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 't');
            cm.setCursor(0, 0);
            helpers.doKeys('`', 't');
            helpers.assertCursorAt(2, 2);
            cm.setCursor(2, 0);
            cm.replaceRange('   h', cm.getCursor());
            cm.setCursor(0, 0);
            helpers.doKeys('\'', 't');
            helpers.assertCursorAt(2, 3);
          });
          testVim('jumpToMark_next', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 't');
            cm.setCursor(0, 0);
            helpers.doKeys(']', '`');
            helpers.assertCursorAt(2, 2);
            cm.setCursor(0, 0);
            helpers.doKeys(']', '\'');
            helpers.assertCursorAt(2, 0);
          });
          testVim('jumpToMark_next_repeat', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(3, 2);
            helpers.doKeys('m', 'b');
            cm.setCursor(4, 2);
            helpers.doKeys('m', 'c');
            cm.setCursor(0, 0);
            helpers.doKeys('2', ']', '`');
            helpers.assertCursorAt(3, 2);
            cm.setCursor(0, 0);
            helpers.doKeys('2', ']', '\'');
            helpers.assertCursorAt(3, 1);
          });
          testVim('jumpToMark_next_sameline', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 4);
            helpers.doKeys('m', 'b');
            cm.setCursor(2, 2);
            helpers.doKeys(']', '`');
            helpers.assertCursorAt(2, 4);
          });
          testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('m', 'a');
            cm.setCursor(4, 0);
            helpers.doKeys(']', '`');
            helpers.assertCursorAt(4, 0);
          });
          testVim('jumpToMark_next_nomark', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys(']', '`');
            helpers.assertCursorAt(2, 2);
            helpers.doKeys(']', '\'');
            helpers.assertCursorAt(2, 0);
          });
          testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(3, 4);
            helpers.doKeys('m', 'b');
            cm.setCursor(2, 1);
            helpers.doKeys(']', '\'');
            helpers.assertCursorAt(3, 1);
          });
          testVim('jumpToMark_next_action', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 't');
            cm.setCursor(0, 0);
            helpers.doKeys('d', ']', '`');
            helpers.assertCursorAt(0, 0);
            var actual = cm.getLine(0);
            var expected = 'pop pop 0 1 2 3 4';
            eq(actual, expected, "Deleting while jumping to the next mark failed.");
          });
          testVim('jumpToMark_next_line_action', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 't');
            cm.setCursor(0, 0);
            helpers.doKeys('d', ']', '\'');
            helpers.assertCursorAt(0, 1);
            var actual = cm.getLine(0);
            var expected = ' (a) [b] {c} '
            eq(actual, expected, "Deleting while jumping to the next mark line failed.");
          });
          testVim('jumpToMark_prev', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 't');
            cm.setCursor(4, 0);
            helpers.doKeys('[', '`');
            helpers.assertCursorAt(2, 2);
            cm.setCursor(4, 0);
            helpers.doKeys('[', '\'');
            helpers.assertCursorAt(2, 0);
          });
          testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(3, 2);
            helpers.doKeys('m', 'b');
            cm.setCursor(4, 2);
            helpers.doKeys('m', 'c');
            cm.setCursor(5, 0);
            helpers.doKeys('2', '[', '`');
            helpers.assertCursorAt(3, 2);
            cm.setCursor(5, 0);
            helpers.doKeys('2', '[', '\'');
            helpers.assertCursorAt(3, 1);
          });
          testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) {
            cm.setCursor(2, 0);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 4);
            helpers.doKeys('m', 'b');
            cm.setCursor(2, 2);
            helpers.doKeys('[', '`');
            helpers.assertCursorAt(2, 0);
          });
          testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) {
            cm.setCursor(4, 4);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 0);
            helpers.doKeys('[', '`');
            helpers.assertCursorAt(2, 0);
          });
          testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('[', '`');
            helpers.assertCursorAt(2, 2);
            helpers.doKeys('[', '\'');
            helpers.assertCursorAt(2, 0);
          });
          testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) {
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(3, 4);
            helpers.doKeys('m', 'b');
            cm.setCursor(3, 6);
            helpers.doKeys('[', '\'');
            helpers.assertCursorAt(2, 0);
          });
          testVim('delmark_single', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('m', 't');
            helpers.doEx('delmarks t');
            cm.setCursor(0, 0);
            helpers.doKeys('`', 't');
            helpers.assertCursorAt(0, 0);
          });
          testVim('delmark_range', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'b');
            cm.setCursor(3, 2);
            helpers.doKeys('m', 'c');
            cm.setCursor(4, 2);
            helpers.doKeys('m', 'd');
            cm.setCursor(5, 2);
            helpers.doKeys('m', 'e');
            helpers.doEx('delmarks b-d');
            cm.setCursor(0, 0);
            helpers.doKeys('`', 'a');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'b');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'c');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'd');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'e');
            helpers.assertCursorAt(5, 2);
          });
          testVim('delmark_multi', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'b');
            cm.setCursor(3, 2);
            helpers.doKeys('m', 'c');
            cm.setCursor(4, 2);
            helpers.doKeys('m', 'd');
            cm.setCursor(5, 2);
            helpers.doKeys('m', 'e');
            helpers.doEx('delmarks bcd');
            cm.setCursor(0, 0);
            helpers.doKeys('`', 'a');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'b');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'c');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'd');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'e');
            helpers.assertCursorAt(5, 2);
          });
          testVim('delmark_multi_space', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'b');
            cm.setCursor(3, 2);
            helpers.doKeys('m', 'c');
            cm.setCursor(4, 2);
            helpers.doKeys('m', 'd');
            cm.setCursor(5, 2);
            helpers.doKeys('m', 'e');
            helpers.doEx('delmarks b c d');
            cm.setCursor(0, 0);
            helpers.doKeys('`', 'a');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'b');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'c');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'd');
            helpers.assertCursorAt(1, 2);
            helpers.doKeys('`', 'e');
            helpers.assertCursorAt(5, 2);
          });
          testVim('delmark_all', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('m', 'a');
            cm.setCursor(2, 2);
            helpers.doKeys('m', 'b');
            cm.setCursor(3, 2);
            helpers.doKeys('m', 'c');
            cm.setCursor(4, 2);
            helpers.doKeys('m', 'd');
            cm.setCursor(5, 2);
            helpers.doKeys('m', 'e');
            helpers.doEx('delmarks a b-de');
            cm.setCursor(0, 0);
            helpers.doKeys('`', 'a');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('`', 'b');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('`', 'c');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('`', 'd');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('`', 'e');
            helpers.assertCursorAt(0, 0);
          });
          testVim('visual', function(cm, vim, helpers) {
            helpers.doKeys('l', 'v', 'l', 'l');
            helpers.assertCursorAt(0, 4);
            eqPos(makeCursor(0, 1), cm.getCursor('anchor'));
            helpers.doKeys('d');
            eq('15', cm.getValue());
          }, { value: '12345' });
          testVim('visual_yank', function(cm, vim, helpers) {
            helpers.doKeys('v', '3', 'l', 'y');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('p');
            eq('aa te test for yank', cm.getValue());
          }, { value: 'a test for yank' })
          testVim('visual_w', function(cm, vim, helpers) {
            helpers.doKeys('v', 'w');
            eq(cm.getSelection(), 'motion t');
          }, { value: 'motion test'});
          testVim('visual_initial_selection', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('v');
            cm.getSelection('n');
          }, { value: 'init'});
          testVim('visual_crossover_left', function(cm, vim, helpers) {
            cm.setCursor(0, 2);
            helpers.doKeys('v', 'l', 'h', 'h');
            cm.getSelection('ro');
          }, { value: 'cross'});
          testVim('visual_crossover_left', function(cm, vim, helpers) {
            cm.setCursor(0, 2);
            helpers.doKeys('v', 'h', 'l', 'l');
            cm.getSelection('os');
          }, { value: 'cross'});
          testVim('visual_crossover_up', function(cm, vim, helpers) {
            cm.setCursor(3, 2);
            helpers.doKeys('v', 'j', 'k', 'k');
            eqPos(Pos(2, 2), cm.getCursor('head'));
            eqPos(Pos(3, 3), cm.getCursor('anchor'));
            helpers.doKeys('k');
            eqPos(Pos(1, 2), cm.getCursor('head'));
            eqPos(Pos(3, 3), cm.getCursor('anchor'));
          }, { value: 'cross\ncross\ncross\ncross\ncross\n'});
          testVim('visual_crossover_down', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('v', 'k', 'j', 'j');
            eqPos(Pos(2, 3), cm.getCursor('head'));
            eqPos(Pos(1, 2), cm.getCursor('anchor'));
            helpers.doKeys('j');
            eqPos(Pos(3, 3), cm.getCursor('head'));
            eqPos(Pos(1, 2), cm.getCursor('anchor'));
          }, { value: 'cross\ncross\ncross\ncross\ncross\n'});
          testVim('visual_exit', function(cm, vim, helpers) {
            helpers.doKeys('<C-v>', 'l', 'j', 'j', '<Esc>');
            eqPos(cm.getCursor('anchor'), cm.getCursor('head'));
            eq(vim.visualMode, false);
          }, { value: 'hello\nworld\nfoo' });
          testVim('visual_line', function(cm, vim, helpers) {
            helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd');
            eq(' 4\n 5', cm.getValue());
          }, { value: ' 1\n 2\n 3\n 4\n 5' });
          testVim('visual_block_move_to_eol', function(cm, vim, helpers) {
            // moveToEol should move all block cursors to end of line
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', 'G', '$');
            var selections = cm.getSelections().join();
            eq('123,45,6', selections);
            // Checks that with cursor at Infinity, finding words backwards still works.
            helpers.doKeys('2', 'k', 'b');
            selections = cm.getSelections().join();
            eq('1', selections);
          }, {value: '123\n45\n6'});
          testVim('visual_block_different_line_lengths', function(cm, vim, helpers) {
            // test the block selection with lines of different length
            // i.e. extending the selection
            // till the end of the longest line.
            helpers.doKeys('<C-v>', 'l', 'j', 'j', '6', 'l', 'd');
            helpers.doKeys('d', 'd', 'd', 'd');
            eq('', cm.getValue());
          }, {value: '1234\n5678\nabcdefg'});
          testVim('visual_block_truncate_on_short_line', function(cm, vim, helpers) {
            // check for left side selection in case
            // of moving up to a shorter line.
            cm.replaceRange('', cm.getCursor());
            cm.setCursor(3, 4);
            helpers.doKeys('<C-v>', 'l', 'k', 'k', 'd');
            eq('hello world\n{\ntis\nsa!', cm.getValue());
          }, {value: 'hello world\n{\nthis is\nsparta!'});
          testVim('visual_block_corners', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('<C-v>', '2', 'l', 'k');
            // circle around the anchor
            // and check the selections
            var selections = cm.getSelections();
            eq('345891', selections.join(''));
            helpers.doKeys('4', 'h');
            selections = cm.getSelections();
            eq('123678', selections.join(''));
            helpers.doKeys('j', 'j');
            selections = cm.getSelections();
            eq('678abc', selections.join(''));
            helpers.doKeys('4', 'l');
            selections = cm.getSelections();
            eq('891cde', selections.join(''));
          }, {value: '12345\n67891\nabcde'});
          testVim('visual_block_mode_switch', function(cm, vim, helpers) {
            // switch between visual modes
            cm.setCursor(1, 1);
            // blockwise to characterwise visual
            helpers.doKeys('<C-v>', 'j', 'l', 'v');
            selections = cm.getSelections();
            eq('7891\nabc', selections.join(''));
            // characterwise to blockwise
            helpers.doKeys('<C-v>');
            selections = cm.getSelections();
            eq('78bc', selections.join(''));
            // blockwise to linewise visual
            helpers.doKeys('V');
            selections = cm.getSelections();
            eq('67891\nabcde', selections.join(''));
          }, {value: '12345\n67891\nabcde'});
          testVim('visual_block_crossing_short_line', function(cm, vim, helpers) {
            // visual block with long and short lines
            cm.setCursor(0, 3);
            helpers.doKeys('<C-v>', 'j', 'j', 'j');
            var selections = cm.getSelections().join();
            eq('4,,d,b', selections);
            helpers.doKeys('3', 'k');
            selections = cm.getSelections().join();
            eq('4', selections);
            helpers.doKeys('5', 'j', 'k');
            selections = cm.getSelections().join("");
            eq(10, selections.length);
          }, {value: '123456\n78\nabcdefg\nfoobar\n}\n'});
          testVim('visual_block_curPos_on_exit', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '3' , 'l', '<Esc>');
            eqPos(makeCursor(0, 3), cm.getCursor());
            helpers.doKeys('h', '<C-v>', '2' , 'j' ,'3' , 'l');
            eq(cm.getSelections().join(), "3456,,cdef");
            helpers.doKeys('4' , 'h');
            eq(cm.getSelections().join(), "23,8,bc");
            helpers.doKeys('2' , 'l');
            eq(cm.getSelections().join(), "34,,cd");
          }, {value: '123456\n78\nabcdefg\nfoobar'});
          
          testVim('visual_marks', function(cm, vim, helpers) {
            helpers.doKeys('l', 'v', 'l', 'l', 'j', 'j', 'v');
            // Test visual mode marks
            cm.setCursor(2, 1);
            helpers.doKeys('\'', '<');
            helpers.assertCursorAt(0, 1);
            helpers.doKeys('\'', '>');
            helpers.assertCursorAt(2, 0);
          });
          testVim('visual_join', function(cm, vim, helpers) {
            helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J');
            eq(' 1 2 3\n 4\n 5', cm.getValue());
            is(!vim.visualMode);
          }, { value: ' 1\n 2\n 3\n 4\n 5' });
          testVim('visual_join_2', function(cm, vim, helpers) {
            helpers.doKeys('G', 'V', 'g', 'g', 'J');
            eq('1 2 3 4 5 6 ', cm.getValue());
            is(!vim.visualMode);
          }, { value: '1\n2\n3\n4\n5\n6\n'});
          testVim('visual_blank', function(cm, vim, helpers) {
            helpers.doKeys('v', 'k');
            eq(vim.visualMode, true);
          }, { value: '\n' });
          testVim('reselect_visual', function(cm, vim, helpers) {
            helpers.doKeys('l', 'v', 'l', 'l', 'l', 'y', 'g', 'v');
            helpers.assertCursorAt(0, 5);
            eqPos(makeCursor(0, 1), cm.getCursor('anchor'));
            helpers.doKeys('v');
            cm.setCursor(1, 0);
            helpers.doKeys('v', 'l', 'l', 'p');
            eq('123456\n2345\nbar', cm.getValue());
            cm.setCursor(0, 0);
            helpers.doKeys('g', 'v');
            // here the fake cursor is at (1, 3)
            helpers.assertCursorAt(1, 4);
            eqPos(makeCursor(1, 0), cm.getCursor('anchor'));
            helpers.doKeys('v');
            cm.setCursor(2, 0);
            helpers.doKeys('v', 'l', 'l', 'g', 'v');
            helpers.assertCursorAt(1, 4);
            eqPos(makeCursor(1, 0), cm.getCursor('anchor'));
            helpers.doKeys('g', 'v');
            helpers.assertCursorAt(2, 3);
            eqPos(makeCursor(2, 0), cm.getCursor('anchor'));
            eq('123456\n2345\nbar', cm.getValue());
          }, { value: '123456\nfoo\nbar' });
          testVim('reselect_visual_line', function(cm, vim, helpers) {
            helpers.doKeys('l', 'V', 'j', 'j', 'V', 'g', 'v', 'd');
            eq('foo\nand\nbar', cm.getValue());
            cm.setCursor(1, 0);
            helpers.doKeys('V', 'y', 'j');
            helpers.doKeys('V', 'p' , 'g', 'v', 'd');
            eq('foo\nand', cm.getValue());
          }, { value: 'hello\nthis\nis\nfoo\nand\nbar' });
          testVim('reselect_visual_block', function(cm, vim, helpers) {
            cm.setCursor(1, 2);
            helpers.doKeys('<C-v>', 'k', 'h', '<C-v>');
            cm.setCursor(2, 1);
            helpers.doKeys('v', 'l', 'g', 'v');
            eqPos(Pos(1, 2), vim.sel.anchor);
            eqPos(Pos(0, 1), vim.sel.head);
            // Ensure selection is done with visual block mode rather than one
            // continuous range.
            eq(cm.getSelections().join(''), '23oo')
            helpers.doKeys('g', 'v');
            eqPos(Pos(2, 1), vim.sel.anchor);
            eqPos(Pos(2, 2), vim.sel.head);
            helpers.doKeys('<Esc>');
            // Ensure selection of deleted range
            cm.setCursor(1, 1);
            helpers.doKeys('v', '<C-v>', 'j', 'd', 'g', 'v');
            eq(cm.getSelections().join(''), 'or');
          }, { value: '123456\nfoo\nbar' });
          testVim('s_normal', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('s');
            helpers.doKeys('<Esc>');
            eq('ac', cm.getValue());
          }, { value: 'abc'});
          testVim('s_visual', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('v', 's');
            helpers.doKeys('<Esc>');
            helpers.assertCursorAt(0, 0);
            eq('ac', cm.getValue());
          }, { value: 'abc'});
          testVim('o_visual', function(cm, vim, helpers) {
            cm.setCursor(0,0);
            helpers.doKeys('v','l','l','l','o');
            helpers.assertCursorAt(0,0);
            helpers.doKeys('v','v','j','j','j','o');
            helpers.assertCursorAt(0,0);
            helpers.doKeys('O');
            helpers.doKeys('l','l')
            helpers.assertCursorAt(3, 3);
            helpers.doKeys('d');
            eq('p',cm.getValue());
          }, { value: 'abcd\nefgh\nijkl\nmnop'});
          testVim('o_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>','3','j','l','l', 'o');
            eqPos(Pos(3, 3), vim.sel.anchor);
            eqPos(Pos(0, 1), vim.sel.head);
            helpers.doKeys('O');
            eqPos(Pos(3, 1), vim.sel.anchor);
            eqPos(Pos(0, 3), vim.sel.head);
            helpers.doKeys('o');
            eqPos(Pos(0, 3), vim.sel.anchor);
            eqPos(Pos(3, 1), vim.sel.head);
          }, { value: 'abcd\nefgh\nijkl\nmnop'});
          testVim('changeCase_visual', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('v', 'l', 'l');
            helpers.doKeys('U');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('v', 'l', 'l');
            helpers.doKeys('u');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('l', 'l', 'l', '.');
            helpers.assertCursorAt(0, 3);
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', 'v', 'j', 'U', 'q');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('j', '@', 'a');
            helpers.assertCursorAt(1, 0);
            cm.setCursor(3, 0);
            helpers.doKeys('V', 'U', 'j', '.');
            eq('ABCDEF\nGHIJKL\nMnopq\nSHORT LINE\nLONG LINE OF TEXT', cm.getValue());
          }, { value: 'abcdef\nghijkl\nmnopq\nshort line\nlong line of text'});
          testVim('changeCase_visual_block', function(cm, vim, helpers) {
            cm.setCursor(2, 1);
            helpers.doKeys('<C-v>', 'k', 'k', 'h', 'U');
            eq('ABcdef\nGHijkl\nMNopq\nfoo', cm.getValue());
            cm.setCursor(0, 2);
            helpers.doKeys('.');
            eq('ABCDef\nGHIJkl\nMNOPq\nfoo', cm.getValue());
            // check when last line is shorter.
            cm.setCursor(2, 2);
            helpers.doKeys('.');
            eq('ABCDef\nGHIJkl\nMNOPq\nfoO', cm.getValue());
          }, { value: 'abcdef\nghijkl\nmnopq\nfoo'});
          testVim('visual_paste', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('v', 'l', 'l', 'y');
            helpers.assertCursorAt(0, 0);
            helpers.doKeys('3', 'l', 'j', 'v', 'l', 'p');
            helpers.assertCursorAt(1, 5);
            eq('this is a\nunithitest for visual paste', cm.getValue());
            cm.setCursor(0, 0);
            // in case of pasting whole line
            helpers.doKeys('y', 'y');
            cm.setCursor(1, 6);
            helpers.doKeys('v', 'l', 'l', 'l', 'p');
            helpers.assertCursorAt(2, 0);
            eq('this is a\nunithi\nthis is a\n for visual paste', cm.getValue());
          }, { value: 'this is a\nunit test for visual paste'});
          
          // This checks the contents of the register used to paste the text
          testVim('v_paste_from_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('"', 'a', 'y', 'w');
            cm.setCursor(1, 0);
            helpers.doKeys('v', 'p');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+register/.test(text));
            });
          }, { value: 'register contents\nare not erased'});
          testVim('S_normal', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('j', 'S');
            helpers.doKeys('<Esc>');
            helpers.assertCursorAt(1, 0);
            eq('aa\n\ncc', cm.getValue());
          }, { value: 'aa\nbb\ncc'});
          testVim('blockwise_paste', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '3', 'j', 'l', 'y');
            cm.setCursor(0, 2);
            // paste one char after the current cursor position
            helpers.doKeys('p');
            eq('helhelo\nworwold\nfoofo\nbarba', cm.getValue());
            cm.setCursor(0, 0);
            helpers.doKeys('v', '4', 'l', 'y');
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '3', 'j', 'p');
            eq('helheelhelo\norwold\noofo\narba', cm.getValue());
          }, { value: 'hello\nworld\nfoo\nbar'});
          testVim('blockwise_paste_long/short_line', function(cm, vim, helpers) {
            // extend short lines in case of different line lengths.
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', 'j', 'j', 'y');
            cm.setCursor(0, 3);
            helpers.doKeys('p');
            eq('hellho\nfoo f\nbar b', cm.getValue());
          }, { value: 'hello\nfoo\nbar'});
          testVim('blockwise_paste_cut_paste', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '2', 'j', 'x');
            cm.setCursor(0, 0);
            helpers.doKeys('P');
            eq('cut\nand\npaste\nme', cm.getValue());
          }, { value: 'cut\nand\npaste\nme'});
          testVim('blockwise_paste_from_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '2', 'j', '"', 'a', 'y');
            cm.setCursor(0, 3);
            helpers.doKeys('"', 'a', 'p');
            eq('foobfar\nhellho\nworlwd', cm.getValue());
          }, { value: 'foobar\nhello\nworld'});
          testVim('blockwise_paste_last_line', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<C-v>', '2', 'j', 'l', 'y');
            cm.setCursor(3, 0);
            helpers.doKeys('p');
            eq('cut\nand\npaste\nmcue\n an\n pa', cm.getValue());
          }, { value: 'cut\nand\npaste\nme'});
          
          testVim('S_visual', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('v', 'j', 'S');
            helpers.doKeys('<Esc>');
            helpers.assertCursorAt(0, 0);
            eq('\ncc', cm.getValue());
          }, { value: 'aa\nbb\ncc'});
          
          testVim('d_/', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('match');
            helpers.doKeys('2', 'd', '/');
            helpers.assertCursorAt(0, 0);
            eq('match \n next', cm.getValue());
            cm.openDialog = helpers.fakeOpenDialog('2');
            helpers.doKeys('d', ':');
            // TODO eq(' next', cm.getValue());
          }, { value: 'text match match \n next' });
          testVim('/ and n/N', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('match');
            helpers.doKeys('/');
            helpers.assertCursorAt(0, 11);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 6);
            helpers.doKeys('N');
            helpers.assertCursorAt(0, 11);
          
            cm.setCursor(0, 0);
            helpers.doKeys('2', '/');
            helpers.assertCursorAt(1, 6);
          }, { value: 'match nope match \n nope Match' });
          testVim('/_case', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('Match');
            helpers.doKeys('/');
            helpers.assertCursorAt(1, 6);
          }, { value: 'match nope match \n nope Match' });
          testVim('/_2_pcre', function(cm, vim, helpers) {
            CodeMirror.Vim.setOption('pcre', true);
            cm.openDialog = helpers.fakeOpenDialog('(word){2}');
            helpers.doKeys('/');
            helpers.assertCursorAt(1, 9);
            helpers.doKeys('n');
            helpers.assertCursorAt(2, 1);
          }, { value: 'word\n another wordword\n wordwordword\n' });
          testVim('/_2_nopcre', function(cm, vim, helpers) {
            CodeMirror.Vim.setOption('pcre', false);
            cm.openDialog = helpers.fakeOpenDialog('\\(word\\)\\{2}');
            helpers.doKeys('/');
            helpers.assertCursorAt(1, 9);
            helpers.doKeys('n');
            helpers.assertCursorAt(2, 1);
          }, { value: 'word\n another wordword\n wordwordword\n' });
          testVim('/_nongreedy', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('aa');
            helpers.doKeys('/');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 3);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 0);
          }, { value: 'aaa aa \n a aa'});
          testVim('?_nongreedy', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('aa');
            helpers.doKeys('?');
            helpers.assertCursorAt(1, 3);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 0);
          }, { value: 'aaa aa \n a aa'});
          testVim('/_greedy', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('a+');
            helpers.doKeys('/');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 1);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 3);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 0);
          }, { value: 'aaa aa \n a aa'});
          testVim('?_greedy', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('a+');
            helpers.doKeys('?');
            helpers.assertCursorAt(1, 3);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 1);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 0);
          }, { value: 'aaa aa \n a aa'});
          testVim('/_greedy_0_or_more', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('a*');
            helpers.doKeys('/');
            helpers.assertCursorAt(0, 3);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 5);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 0);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 1);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 0);
          }, { value: 'aaa  aa\n aa'});
          testVim('?_greedy_0_or_more', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('a*');
            helpers.doKeys('?');
            helpers.assertCursorAt(1, 1);
            helpers.doKeys('n');
            helpers.assertCursorAt(1, 0);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 5);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 3);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 0);
          }, { value: 'aaa  aa\n aa'});
          testVim('? and n/N', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('match');
            helpers.doKeys('?');
            helpers.assertCursorAt(1, 6);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 11);
            helpers.doKeys('N');
            helpers.assertCursorAt(1, 6);
          
            cm.setCursor(0, 0);
            helpers.doKeys('2', '?');
            helpers.assertCursorAt(0, 11);
          }, { value: 'match nope match \n nope Match' });
          testVim('*', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('*');
            helpers.assertCursorAt(0, 22);
          
            cm.setCursor(0, 9);
            helpers.doKeys('2', '*');
            helpers.assertCursorAt(1, 8);
          }, { value: 'nomatch match nomatch match \nnomatch Match' });
          testVim('*_no_word', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('*');
            helpers.assertCursorAt(0, 0);
          }, { value: ' \n match \n' });
          testVim('*_symbol', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('*');
            helpers.assertCursorAt(1, 0);
          }, { value: ' /}\n/} match \n' });
          testVim('#', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('#');
            helpers.assertCursorAt(1, 8);
          
            cm.setCursor(0, 9);
            helpers.doKeys('2', '#');
            helpers.assertCursorAt(0, 22);
          }, { value: 'nomatch match nomatch match \nnomatch Match' });
          testVim('*_seek', function(cm, vim, helpers) {
            // Should skip over space and symbols.
            cm.setCursor(0, 3);
            helpers.doKeys('*');
            helpers.assertCursorAt(0, 22);
          }, { value: '    :=  match nomatch match \nnomatch Match' });
          testVim('#', function(cm, vim, helpers) {
            // Should skip over space and symbols.
            cm.setCursor(0, 3);
            helpers.doKeys('#');
            helpers.assertCursorAt(1, 8);
          }, { value: '    :=  match nomatch match \nnomatch Match' });
          testVim('g*', function(cm, vim, helpers) {
            cm.setCursor(0, 8);
            helpers.doKeys('g', '*');
            helpers.assertCursorAt(0, 18);
            cm.setCursor(0, 8);
            helpers.doKeys('3', 'g', '*');
            helpers.assertCursorAt(1, 8);
          }, { value: 'matches match alsoMatch\nmatchme matching' });
          testVim('g#', function(cm, vim, helpers) {
            cm.setCursor(0, 8);
            helpers.doKeys('g', '#');
            helpers.assertCursorAt(0, 0);
            cm.setCursor(0, 8);
            helpers.doKeys('3', 'g', '#');
            helpers.assertCursorAt(1, 0);
          }, { value: 'matches match alsoMatch\nmatchme matching' });
          testVim('macro_insert', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', '0', 'i');
            cm.replaceRange('foo', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q', '@', 'a');
            eq('foofoo', cm.getValue());
          }, { value: ''});
          testVim('macro_insert_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', '$', 'a');
            cm.replaceRange('larry.', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('a');
            cm.replaceRange('curly.', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q');
            helpers.doKeys('a');
            cm.replaceRange('moe.', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('@', 'a');
            // At this point, the most recent edit should be the 2nd insert change
            // inside the macro, i.e. "curly.".
            helpers.doKeys('.');
            eq('larry.curly.moe.larry.curly.curly.', cm.getValue());
          }, { value: ''});
          testVim('macro_space', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('<Space>', '<Space>');
            helpers.assertCursorAt(0, 2);
            helpers.doKeys('q', 'a', '<Space>', '<Space>', 'q');
            helpers.assertCursorAt(0, 4);
            helpers.doKeys('@', 'a');
            helpers.assertCursorAt(0, 6);
            helpers.doKeys('@', 'a');
            helpers.assertCursorAt(0, 8);
          }, { value: 'one line of text.'});
          testVim('macro_t_search', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', 't', 'e', 'q');
            helpers.assertCursorAt(0, 1);
            helpers.doKeys('l', '@', 'a');
            helpers.assertCursorAt(0, 6);
            helpers.doKeys('l', ';');
            helpers.assertCursorAt(0, 12);
          }, { value: 'one line of text.'});
          testVim('macro_f_search', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'b', 'f', 'e', 'q');
            helpers.assertCursorAt(0, 2);
            helpers.doKeys('@', 'b');
            helpers.assertCursorAt(0, 7);
            helpers.doKeys(';');
            helpers.assertCursorAt(0, 13);
          }, { value: 'one line of text.'});
          testVim('macro_slash_search', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'c');
            cm.openDialog = helpers.fakeOpenDialog('e');
            helpers.doKeys('/', 'q');
            helpers.assertCursorAt(0, 2);
            helpers.doKeys('@', 'c');
            helpers.assertCursorAt(0, 7);
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 13);
          }, { value: 'one line of text.'});
          testVim('macro_multislash_search', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'd');
            cm.openDialog = helpers.fakeOpenDialog('e');
            helpers.doKeys('/');
            cm.openDialog = helpers.fakeOpenDialog('t');
            helpers.doKeys('/', 'q');
            helpers.assertCursorAt(0, 12);
            helpers.doKeys('@', 'd');
            helpers.assertCursorAt(0, 15);
          }, { value: 'one line of text to rule them all.'});
          testVim('macro_last_ex_command_register', function (cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doEx('s/a/b');
            helpers.doKeys('2', '@', ':');
            eq('bbbaa', cm.getValue());
            helpers.assertCursorAt(0, 2);
          }, { value: 'aaaaa'});
          testVim('macro_parens', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'z', 'i');
            cm.replaceRange('(', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('e', 'a');
            cm.replaceRange(')', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q');
            helpers.doKeys('w', '@', 'z');
            helpers.doKeys('w', '@', 'z');
            eq('(see) (spot) (run)', cm.getValue());
          }, { value: 'see spot run'});
          testVim('macro_overwrite', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'z', '0', 'i');
            cm.replaceRange('I ', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q');
            helpers.doKeys('e');
            // Now replace the macro with something else.
            helpers.doKeys('q', 'z', 'a');
            cm.replaceRange('.', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q');
            helpers.doKeys('e', '@', 'z');
            helpers.doKeys('e', '@', 'z');
            eq('I see. spot. run.', cm.getValue());
          }, { value: 'see spot run'});
          testVim('macro_search_f', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', 'f', ' ');
            helpers.assertCursorAt(0,3);
            helpers.doKeys('q', '0');
            helpers.assertCursorAt(0,0);
            helpers.doKeys('@', 'a');
            helpers.assertCursorAt(0,3);
          }, { value: 'The quick brown fox jumped over the lazy dog.'});
          testVim('macro_search_2f', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', '2', 'f', ' ');
            helpers.assertCursorAt(0,9);
            helpers.doKeys('q', '0');
            helpers.assertCursorAt(0,0);
            helpers.doKeys('@', 'a');
            helpers.assertCursorAt(0,9);
          }, { value: 'The quick brown fox jumped over the lazy dog.'});
          testVim('yank_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('"', 'a', 'y', 'y');
            helpers.doKeys('j', '"', 'b', 'y', 'y');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+foo/.test(text));
              is(/b\s+bar/.test(text));
            });
            helpers.doKeys(':');
          }, { value: 'foo\nbar'});
          testVim('yank_visual_block', function(cm, vim, helpers) {
            cm.setCursor(0, 1);
            helpers.doKeys('<C-v>', 'l', 'j', '"', 'a', 'y');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+oo\nar/.test(text));
            });
            helpers.doKeys(':');
          }, { value: 'foo\nbar'});
          testVim('yank_append_line_to_line_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('"', 'a', 'y', 'y');
            helpers.doKeys('j', '"', 'A', 'y', 'y');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+foo\nbar/.test(text));
              is(/"\s+foo\nbar/.test(text));
            });
            helpers.doKeys(':');
          }, { value: 'foo\nbar'});
          testVim('yank_append_word_to_word_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('"', 'a', 'y', 'w');
            helpers.doKeys('j', '"', 'A', 'y', 'w');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+foobar/.test(text));
              is(/"\s+foobar/.test(text));
            });
            helpers.doKeys(':');
          }, { value: 'foo\nbar'});
          testVim('yank_append_line_to_word_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('"', 'a', 'y', 'w');
            helpers.doKeys('j', '"', 'A', 'y', 'y');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+foo\nbar/.test(text));
              is(/"\s+foo\nbar/.test(text));
            });
            helpers.doKeys(':');
          }, { value: 'foo\nbar'});
          testVim('yank_append_word_to_line_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('"', 'a', 'y', 'y');
            helpers.doKeys('j', '"', 'A', 'y', 'w');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+foo\nbar/.test(text));
              is(/"\s+foo\nbar/.test(text));
            });
            helpers.doKeys(':');
          }, { value: 'foo\nbar'});
          testVim('macro_register', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('q', 'a', 'i');
            cm.replaceRange('gangnam', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q');
            helpers.doKeys('q', 'b', 'o');
            cm.replaceRange('style', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('q');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/a\s+i/.test(text));
              is(/b\s+o/.test(text));
            });
            helpers.doKeys(':');
          }, { value: ''});
          testVim('._register', function(cm,vim,helpers) {
            cm.setCursor(0,0);
            helpers.doKeys('i');
            cm.replaceRange('foo',cm.getCursor());
            helpers.doKeys('<Esc>');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/\.\s+foo/.test(text));
            });
            helpers.doKeys(':');
          }, {value: ''});
          testVim(':_register', function(cm,vim,helpers) {
            helpers.doEx('bar');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/:\s+bar/.test(text));
            });
            helpers.doKeys(':');
          }, {value: ''});
          testVim('search_register_escape', function(cm, vim, helpers) {
            // Check that the register is restored if the user escapes rather than confirms.
            cm.openDialog = helpers.fakeOpenDialog('waldo');
            helpers.doKeys('/');
            var onKeyDown;
            var onKeyUp;
            var KEYCODES = {
              f: 70,
              o: 79,
              Esc: 27
            };
            cm.openDialog = function(template, callback, options) {
              onKeyDown = options.onKeyDown;
              onKeyUp = options.onKeyUp;
            };
            var close = function() {};
            helpers.doKeys('/');
            // Fake some keyboard events coming in.
            onKeyDown({keyCode: KEYCODES.f}, '', close);
            onKeyUp({keyCode: KEYCODES.f}, '', close);
            onKeyDown({keyCode: KEYCODES.o}, 'f', close);
            onKeyUp({keyCode: KEYCODES.o}, 'f', close);
            onKeyDown({keyCode: KEYCODES.o}, 'fo', close);
            onKeyUp({keyCode: KEYCODES.o}, 'fo', close);
            onKeyDown({keyCode: KEYCODES.Esc}, 'foo', close);
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/waldo/.test(text));
              is(!/foo/.test(text));
            });
            helpers.doKeys(':');
          }, {value: ''});
          testVim('search_register', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('foo');
            helpers.doKeys('/');
            cm.openDialog = helpers.fakeOpenDialog('registers');
            cm.openNotification = helpers.fakeOpenNotification(function(text) {
              is(/\/\s+foo/.test(text));
            });
            helpers.doKeys(':');
          }, {value: ''});
          testVim('search_history', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('this');
            helpers.doKeys('/');
            cm.openDialog = helpers.fakeOpenDialog('checks');
            helpers.doKeys('/');
            cm.openDialog = helpers.fakeOpenDialog('search');
            helpers.doKeys('/');
            cm.openDialog = helpers.fakeOpenDialog('history');
            helpers.doKeys('/');
            cm.openDialog = helpers.fakeOpenDialog('checks');
            helpers.doKeys('/');
            var onKeyDown;
            var onKeyUp;
            var query = '';
            var keyCodes = {
              Up: 38,
              Down: 40
            };
            cm.openDialog = function(template, callback, options) {
              onKeyUp = options.onKeyUp;
              onKeyDown = options.onKeyDown;
            };
            var close = function(newVal) {
              if (typeof newVal == 'string') query = newVal;
            }
            helpers.doKeys('/');
            onKeyDown({keyCode: keyCodes.Up}, query, close);
            onKeyUp({keyCode: keyCodes.Up}, query, close);
            eq(query, 'checks');
            onKeyDown({keyCode: keyCodes.Up}, query, close);
            onKeyUp({keyCode: keyCodes.Up}, query, close);
            eq(query, 'history');
            onKeyDown({keyCode: keyCodes.Up}, query, close);
            onKeyUp({keyCode: keyCodes.Up}, query, close);
            eq(query, 'search');
            onKeyDown({keyCode: keyCodes.Up}, query, close);
            onKeyUp({keyCode: keyCodes.Up}, query, close);
            eq(query, 'this');
            onKeyDown({keyCode: keyCodes.Down}, query, close);
            onKeyUp({keyCode: keyCodes.Down}, query, close);
            eq(query, 'search');
          }, {value: ''});
          testVim('exCommand_history', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('registers');
            helpers.doKeys(':');
            cm.openDialog = helpers.fakeOpenDialog('sort');
            helpers.doKeys(':');
            cm.openDialog = helpers.fakeOpenDialog('map');
            helpers.doKeys(':');
            cm.openDialog = helpers.fakeOpenDialog('invalid');
            helpers.doKeys(':');
            var onKeyDown;
            var onKeyUp;
            var input = '';
            var keyCodes = {
              Up: 38,
              Down: 40,
              s: 115
            };
            cm.openDialog = function(template, callback, options) {
              onKeyUp = options.onKeyUp;
              onKeyDown = options.onKeyDown;
            };
            var close = function(newVal) {
              if (typeof newVal == 'string') input = newVal;
            }
            helpers.doKeys(':');
            onKeyDown({keyCode: keyCodes.Up}, input, close);
            eq(input, 'invalid');
            onKeyDown({keyCode: keyCodes.Up}, input, close);
            eq(input, 'map');
            onKeyDown({keyCode: keyCodes.Up}, input, close);
            eq(input, 'sort');
            onKeyDown({keyCode: keyCodes.Up}, input, close);
            eq(input, 'registers');
            onKeyDown({keyCode: keyCodes.s}, '', close);
            input = 's';
            onKeyDown({keyCode: keyCodes.Up}, input, close);
            eq(input, 'sort');
          }, {value: ''});
          testVim('search_clear', function(cm, vim, helpers) {
            var onKeyDown;
            var input = '';
            var keyCodes = {
              Ctrl: 17,
              u: 85
            };
            cm.openDialog = function(template, callback, options) {
              onKeyDown = options.onKeyDown;
            };
            var close = function(newVal) {
              if (typeof newVal == 'string') input = newVal;
            }
            helpers.doKeys('/');
            input = 'foo';
            onKeyDown({keyCode: keyCodes.Ctrl}, input, close);
            onKeyDown({keyCode: keyCodes.u, ctrlKey: true}, input, close);
            eq(input, '');
          });
          testVim('exCommand_clear', function(cm, vim, helpers) {
            var onKeyDown;
            var input = '';
            var keyCodes = {
              Ctrl: 17,
              u: 85
            };
            cm.openDialog = function(template, callback, options) {
              onKeyDown = options.onKeyDown;
            };
            var close = function(newVal) {
              if (typeof newVal == 'string') input = newVal;
            }
            helpers.doKeys(':');
            input = 'foo';
            onKeyDown({keyCode: keyCodes.Ctrl}, input, close);
            onKeyDown({keyCode: keyCodes.u, ctrlKey: true}, input, close);
            eq(input, '');
          });
          testVim('.', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('2', 'd', 'w');
            helpers.doKeys('.');
            eq('5 6', cm.getValue());
          }, { value: '1 2 3 4 5 6'});
          testVim('._repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('2', 'd', 'w');
            helpers.doKeys('3', '.');
            eq('6', cm.getValue());
          }, { value: '1 2 3 4 5 6'});
          testVim('._insert', function(cm, vim, helpers) {
            helpers.doKeys('i');
            cm.replaceRange('test', cm.getCursor());
            helpers.doKeys('<Esc>');
            helpers.doKeys('.');
            eq('testestt', cm.getValue());
            helpers.assertCursorAt(0, 6);
          }, { value: ''});
          testVim('._insert_repeat', function(cm, vim, helpers) {
            helpers.doKeys('i');
            cm.replaceRange('test', cm.getCursor());
            cm.setCursor(0, 4);
            helpers.doKeys('<Esc>');
            helpers.doKeys('2', '.');
            eq('testesttestt', cm.getValue());
            helpers.assertCursorAt(0, 10);
          }, { value: ''});
          testVim('._repeat_insert', function(cm, vim, helpers) {
            helpers.doKeys('3', 'i');
            cm.replaceRange('te', cm.getCursor());
            cm.setCursor(0, 2);
            helpers.doKeys('<Esc>');
            helpers.doKeys('.');
            eq('tetettetetee', cm.getValue());
            helpers.assertCursorAt(0, 10);
          }, { value: ''});
          testVim('._insert_o', function(cm, vim, helpers) {
            helpers.doKeys('o');
            cm.replaceRange('z', cm.getCursor());
            cm.setCursor(1, 1);
            helpers.doKeys('<Esc>');
            helpers.doKeys('.');
            eq('\nz\nz', cm.getValue());
            helpers.assertCursorAt(2, 0);
          }, { value: ''});
          testVim('._insert_o_repeat', function(cm, vim, helpers) {
            helpers.doKeys('o');
            cm.replaceRange('z', cm.getCursor());
            helpers.doKeys('<Esc>');
            cm.setCursor(1, 0);
            helpers.doKeys('2', '.');
            eq('\nz\nz\nz', cm.getValue());
            helpers.assertCursorAt(3, 0);
          }, { value: ''});
          testVim('._insert_o_indent', function(cm, vim, helpers) {
            helpers.doKeys('o');
            cm.replaceRange('z', cm.getCursor());
            helpers.doKeys('<Esc>');
            cm.setCursor(1, 2);
            helpers.doKeys('.');
            eq('{\n  z\n  z', cm.getValue());
            helpers.assertCursorAt(2, 2);
          }, { value: '{'});
          testVim('._insert_cw', function(cm, vim, helpers) {
            helpers.doKeys('c', 'w');
            cm.replaceRange('test', cm.getCursor());
            helpers.doKeys('<Esc>');
            cm.setCursor(0, 3);
            helpers.doKeys('2', 'l');
            helpers.doKeys('.');
            eq('test test word3', cm.getValue());
            helpers.assertCursorAt(0, 8);
          }, { value: 'word1 word2 word3' });
          testVim('._insert_cw_repeat', function(cm, vim, helpers) {
            // For some reason, repeat cw in desktop VIM will does not repeat insert mode
            // changes. Will conform to that behavior.
            helpers.doKeys('c', 'w');
            cm.replaceRange('test', cm.getCursor());
            helpers.doKeys('<Esc>');
            cm.setCursor(0, 4);
            helpers.doKeys('l');
            helpers.doKeys('2', '.');
            eq('test test', cm.getValue());
            helpers.assertCursorAt(0, 8);
          }, { value: 'word1 word2 word3' });
          testVim('._delete', function(cm, vim, helpers) {
            cm.setCursor(0, 5);
            helpers.doKeys('i');
            helpers.doInsertModeKeys('Backspace');
            helpers.doKeys('<Esc>');
            helpers.doKeys('.');
            eq('zace', cm.getValue());
            helpers.assertCursorAt(0, 1);
          }, { value: 'zabcde'});
          testVim('._delete_repeat', function(cm, vim, helpers) {
            cm.setCursor(0, 6);
            helpers.doKeys('i');
            helpers.doInsertModeKeys('Backspace');
            helpers.doKeys('<Esc>');
            helpers.doKeys('2', '.');
            eq('zzce', cm.getValue());
            helpers.assertCursorAt(0, 1);
          }, { value: 'zzabcde'});
          testVim('._visual_>', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('V', 'j', '>');
            cm.setCursor(2, 0)
            helpers.doKeys('.');
            eq('  1\n  2\n  3\n  4', cm.getValue());
            helpers.assertCursorAt(2, 2);
          }, { value: '1\n2\n3\n4'});
          testVim('f;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('f', 'x');
            helpers.doKeys(';');
            helpers.doKeys('2', ';');
            eq(9, cm.getCursor().ch);
          }, { value: '01x3xx678x'});
          testVim('F;', function(cm, vim, helpers) {
            cm.setCursor(0, 8);
            helpers.doKeys('F', 'x');
            helpers.doKeys(';');
            helpers.doKeys('2', ';');
            eq(2, cm.getCursor().ch);
          }, { value: '01x3xx6x8x'});
          testVim('t;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('t', 'x');
            helpers.doKeys(';');
            helpers.doKeys('2', ';');
            eq(8, cm.getCursor().ch);
          }, { value: '01x3xx678x'});
          testVim('T;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('T', 'x');
            helpers.doKeys(';');
            helpers.doKeys('2', ';');
            eq(2, cm.getCursor().ch);
          }, { value: '0xx3xx678x'});
          testVim('f,', function(cm, vim, helpers) {
            cm.setCursor(0, 6);
            helpers.doKeys('f', 'x');
            helpers.doKeys(',');
            helpers.doKeys('2', ',');
            eq(2, cm.getCursor().ch);
          }, { value: '01x3xx678x'});
          testVim('F,', function(cm, vim, helpers) {
            cm.setCursor(0, 3);
            helpers.doKeys('F', 'x');
            helpers.doKeys(',');
            helpers.doKeys('2', ',');
            eq(9, cm.getCursor().ch);
          }, { value: '01x3xx678x'});
          testVim('t,', function(cm, vim, helpers) {
            cm.setCursor(0, 6);
            helpers.doKeys('t', 'x');
            helpers.doKeys(',');
            helpers.doKeys('2', ',');
            eq(3, cm.getCursor().ch);
          }, { value: '01x3xx678x'});
          testVim('T,', function(cm, vim, helpers) {
            cm.setCursor(0, 4);
            helpers.doKeys('T', 'x');
            helpers.doKeys(',');
            helpers.doKeys('2', ',');
            eq(8, cm.getCursor().ch);
          }, { value: '01x3xx67xx'});
          testVim('fd,;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('f', '4');
            cm.setCursor(0, 0);
            helpers.doKeys('d', ';');
            eq('56789', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 9);
            helpers.doKeys('d', ',');
            eq('01239', cm.getValue());
          }, { value: '0123456789'});
          testVim('Fd,;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('F', '4');
            cm.setCursor(0, 9);
            helpers.doKeys('d', ';');
            eq('01239', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 0);
            helpers.doKeys('d', ',');
            eq('56789', cm.getValue());
          }, { value: '0123456789'});
          testVim('td,;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('t', '4');
            cm.setCursor(0, 0);
            helpers.doKeys('d', ';');
            eq('456789', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 9);
            helpers.doKeys('d', ',');
            eq('012349', cm.getValue());
          }, { value: '0123456789'});
          testVim('Td,;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('T', '4');
            cm.setCursor(0, 9);
            helpers.doKeys('d', ';');
            eq('012349', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 0);
            helpers.doKeys('d', ',');
            eq('456789', cm.getValue());
          }, { value: '0123456789'});
          testVim('fc,;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('f', '4');
            cm.setCursor(0, 0);
            helpers.doKeys('c', ';', '<Esc>');
            eq('56789', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 9);
            helpers.doKeys('c', ',');
            eq('01239', cm.getValue());
          }, { value: '0123456789'});
          testVim('Fc,;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('F', '4');
            cm.setCursor(0, 9);
            helpers.doKeys('c', ';', '<Esc>');
            eq('01239', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 0);
            helpers.doKeys('c', ',');
            eq('56789', cm.getValue());
          }, { value: '0123456789'});
          testVim('tc,;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('t', '4');
            cm.setCursor(0, 0);
            helpers.doKeys('c', ';', '<Esc>');
            eq('456789', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 9);
            helpers.doKeys('c', ',');
            eq('012349', cm.getValue());
          }, { value: '0123456789'});
          testVim('Tc,;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('T', '4');
            cm.setCursor(0, 9);
            helpers.doKeys('c', ';', '<Esc>');
            eq('012349', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 0);
            helpers.doKeys('c', ',');
            eq('456789', cm.getValue());
          }, { value: '0123456789'});
          testVim('fy,;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('f', '4');
            cm.setCursor(0, 0);
            helpers.doKeys('y', ';', 'P');
            eq('012340123456789', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 9);
            helpers.doKeys('y', ',', 'P');
            eq('012345678456789', cm.getValue());
          }, { value: '0123456789'});
          testVim('Fy,;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('F', '4');
            cm.setCursor(0, 9);
            helpers.doKeys('y', ';', 'p');
            eq('012345678945678', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 0);
            helpers.doKeys('y', ',', 'P');
            eq('012340123456789', cm.getValue());
          }, { value: '0123456789'});
          testVim('ty,;', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys('t', '4');
            cm.setCursor(0, 0);
            helpers.doKeys('y', ';', 'P');
            eq('01230123456789', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 9);
            helpers.doKeys('y', ',', 'p');
            eq('01234567895678', cm.getValue());
          }, { value: '0123456789'});
          testVim('Ty,;', function(cm, vim, helpers) {
            cm.setCursor(0, 9);
            helpers.doKeys('T', '4');
            cm.setCursor(0, 9);
            helpers.doKeys('y', ';', 'p');
            eq('01234567895678', cm.getValue());
            helpers.doKeys('u');
            cm.setCursor(0, 0);
            helpers.doKeys('y', ',', 'P');
            eq('01230123456789', cm.getValue());
          }, { value: '0123456789'});
          testVim('HML', function(cm, vim, helpers) {
            var lines = 35;
            var textHeight = cm.defaultTextHeight();
            cm.setSize(600, lines*textHeight);
            cm.setCursor(120, 0);
            helpers.doKeys('H');
            helpers.assertCursorAt(86, 2);
            helpers.doKeys('L');
            helpers.assertCursorAt(120, 4);
            helpers.doKeys('M');
            helpers.assertCursorAt(103,4);
          }, { value: (function(){
            var lines = new Array(100);
            var upper = '  xx\n';
            var lower = '    xx\n';
            upper = lines.join(upper);
            lower = lines.join(lower);
            return upper + lower;
          })()});
          
          var zVals = [];
          forEach(['zb','zz','zt','z-','z.','z<CR>'], function(e, idx){
            var lineNum = 250;
            var lines = 35;
            testVim(e, function(cm, vim, helpers) {
              var k1 = e[0];
              var k2 = e.substring(1);
              var textHeight = cm.defaultTextHeight();
              cm.setSize(600, lines*textHeight);
              cm.setCursor(lineNum, 0);
              helpers.doKeys(k1, k2);
              zVals[idx] = cm.getScrollInfo().top;
            }, { value: (function(){
              return new Array(500).join('\n');
            })()});
          });
          testVim('zb<zz', function(cm, vim, helpers){
            eq(zVals[0]<zVals[1], true);
          });
          testVim('zz<zt', function(cm, vim, helpers){
            eq(zVals[1]<zVals[2], true);
          });
          testVim('zb==z-', function(cm, vim, helpers){
            eq(zVals[0], zVals[3]);
          });
          testVim('zz==z.', function(cm, vim, helpers){
            eq(zVals[1], zVals[4]);
          });
          testVim('zt==z<CR>', function(cm, vim, helpers){
            eq(zVals[2], zVals[5]);
          });
          
          var moveTillCharacterSandbox =
            'The quick brown fox \n'
            'jumped over the lazy dog.'
          testVim('moveTillCharacter', function(cm, vim, helpers){
            cm.setCursor(0, 0);
            // Search for the 'q'.
            cm.openDialog = helpers.fakeOpenDialog('q');
            helpers.doKeys('/');
            eq(4, cm.getCursor().ch);
            // Jump to just before the first o in the list.
            helpers.doKeys('t');
            helpers.doKeys('o');
            eq('The quick brown fox \n', cm.getValue());
            // Delete that one character.
            helpers.doKeys('d');
            helpers.doKeys('t');
            helpers.doKeys('o');
            eq('The quick bown fox \n', cm.getValue());
            // Delete everything until the next 'o'.
            helpers.doKeys('.');
            eq('The quick box \n', cm.getValue());
            // An unmatched character should have no effect.
            helpers.doKeys('d');
            helpers.doKeys('t');
            helpers.doKeys('q');
            eq('The quick box \n', cm.getValue());
            // Matches should only be possible on single lines.
            helpers.doKeys('d');
            helpers.doKeys('t');
            helpers.doKeys('z');
            eq('The quick box \n', cm.getValue());
            // After all that, the search for 'q' should still be active, so the 'N' command
            // can run it again in reverse. Use that to delete everything back to the 'q'.
            helpers.doKeys('d');
            helpers.doKeys('N');
            eq('The ox \n', cm.getValue());
            eq(4, cm.getCursor().ch);
          }, { value: moveTillCharacterSandbox});
          testVim('searchForPipe', function(cm, vim, helpers){
            CodeMirror.Vim.setOption('pcre', false);
            cm.setCursor(0, 0);
            // Search for the '|'.
            cm.openDialog = helpers.fakeOpenDialog('|');
            helpers.doKeys('/');
            eq(4, cm.getCursor().ch);
          }, { value: 'this|that'});
          
          
          var scrollMotionSandbox =
            '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'
            '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'
            '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'
            '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n';
          testVim('scrollMotion', function(cm, vim, helpers){
            var prevCursor, prevScrollInfo;
            cm.setCursor(0, 0);
            // ctrl-y at the top of the file should have no effect.
            helpers.doKeys('<C-y>');
            eq(0, cm.getCursor().line);
            prevScrollInfo = cm.getScrollInfo();
            helpers.doKeys('<C-e>');
            eq(1, cm.getCursor().line);
            is(prevScrollInfo.top < cm.getScrollInfo().top);
            // Jump to the end of the sandbox.
            cm.setCursor(1000, 0);
            prevCursor = cm.getCursor();
            // ctrl-e at the bottom of the file should have no effect.
            helpers.doKeys('<C-e>');
            eq(prevCursor.line, cm.getCursor().line);
            prevScrollInfo = cm.getScrollInfo();
            helpers.doKeys('<C-y>');
            eq(prevCursor.line - 1, cm.getCursor().line, "Y");
            is(prevScrollInfo.top > cm.getScrollInfo().top);
          }, { value: scrollMotionSandbox});
          
          var squareBracketMotionSandbox = ''+
            '({\n'+//0
            '  ({\n'+//11
            '  /*comment {\n'+//2
            '            */(\n'+//3
            '#else                \n'+//4
            '  /*       )\n'+//5
            '#if        }\n'+//6
            '  )}*/\n'+//7
            ')}\n'+//8
            '{}\n'+//9
            '#else {{\n'+//10
            '{}\n'+//11
            '}\n'+//12
            '{\n'+//13
            '#endif\n'+//14
            '}\n'+//15
            '}\n'+//16
            '#else';//17
          testVim('[[, ]]', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys(']', ']');
            helpers.assertCursorAt(9,0);
            helpers.doKeys('2', ']', ']');
            helpers.assertCursorAt(13,0);
            helpers.doKeys(']', ']');
            helpers.assertCursorAt(17,0);
            helpers.doKeys('[', '[');
            helpers.assertCursorAt(13,0);
            helpers.doKeys('2', '[', '[');
            helpers.assertCursorAt(9,0);
            helpers.doKeys('[', '[');
            helpers.assertCursorAt(0,0);
          }, { value: squareBracketMotionSandbox});
          testVim('[], ][', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doKeys(']', '[');
            helpers.assertCursorAt(12,0);
            helpers.doKeys('2', ']', '[');
            helpers.assertCursorAt(16,0);
            helpers.doKeys(']', '[');
            helpers.assertCursorAt(17,0);
            helpers.doKeys('[', ']');
            helpers.assertCursorAt(16,0);
            helpers.doKeys('2', '[', ']');
            helpers.assertCursorAt(12,0);
            helpers.doKeys('[', ']');
            helpers.assertCursorAt(0,0);
          }, { value: squareBracketMotionSandbox});
          testVim('[{, ]}', function(cm, vim, helpers) {
            cm.setCursor(4, 10);
            helpers.doKeys('[', '{');
            helpers.assertCursorAt(2,12);
            helpers.doKeys('2', '[', '{');
            helpers.assertCursorAt(0,1);
            cm.setCursor(4, 10);
            helpers.doKeys(']', '}');
            helpers.assertCursorAt(6,11);
            helpers.doKeys('2', ']', '}');
            helpers.assertCursorAt(8,1);
            cm.setCursor(0,1);
            helpers.doKeys(']', '}');
            helpers.assertCursorAt(8,1);
            helpers.doKeys('[', '{');
            helpers.assertCursorAt(0,1);
          }, { value: squareBracketMotionSandbox});
          testVim('[(, ])', function(cm, vim, helpers) {
            cm.setCursor(4, 10);
            helpers.doKeys('[', '(');
            helpers.assertCursorAt(3,14);
            helpers.doKeys('2', '[', '(');
            helpers.assertCursorAt(0,0);
            cm.setCursor(4, 10);
            helpers.doKeys(']', ')');
            helpers.assertCursorAt(5,11);
            helpers.doKeys('2', ']', ')');
            helpers.assertCursorAt(8,0);
            helpers.doKeys('[', '(');
            helpers.assertCursorAt(0,0);
            helpers.doKeys(']', ')');
            helpers.assertCursorAt(8,0);
          }, { value: squareBracketMotionSandbox});
          testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) {
            forEach(['*', '/'], function(key){
              cm.setCursor(7, 0);
              helpers.doKeys('2', '[', key);
              helpers.assertCursorAt(2,2);
              helpers.doKeys('2', ']', key);
              helpers.assertCursorAt(7,5);
            });
          }, { value: squareBracketMotionSandbox});
          testVim('[#, ]#', function(cm, vim, helpers) {
            cm.setCursor(10, 3);
            helpers.doKeys('2', '[', '#');
            helpers.assertCursorAt(4,0);
            helpers.doKeys('5', ']', '#');
            helpers.assertCursorAt(17,0);
            cm.setCursor(10, 3);
            helpers.doKeys(']', '#');
            helpers.assertCursorAt(14,0);
          }, { value: squareBracketMotionSandbox});
          testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) {
            cm.setCursor(11, 0);
            helpers.doKeys('[', 'm');
            helpers.assertCursorAt(10,7);
            helpers.doKeys('4', '[', 'm');
            helpers.assertCursorAt(1,3);
            helpers.doKeys('5', ']', 'm');
            helpers.assertCursorAt(11,0);
            helpers.doKeys('[', 'M');
            helpers.assertCursorAt(9,1);
            helpers.doKeys('3', ']', 'M');
            helpers.assertCursorAt(15,0);
            helpers.doKeys('5', '[', 'M');
            helpers.assertCursorAt(7,3);
          }, { value: squareBracketMotionSandbox});
          
          // Ex mode tests
          testVim('ex_go_to_line', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doEx('4');
            helpers.assertCursorAt(3, 0);
          }, { value: 'a\nb\nc\nd\ne\n'});
          testVim('ex_write', function(cm, vim, helpers) {
            var tmp = CodeMirror.commands.save;
            var written;
            var actualCm;
            CodeMirror.commands.save = function(cm) {
              written = true;
              actualCm = cm;
            };
            // Test that w, wr, wri ... write all trigger :write.
            var command = 'write';
            for (var i = 1; i < command.length; i++) {
              written = false;
              actualCm = null;
              helpers.doEx(command.substring(0, i));
              eq(written, true);
              eq(actualCm, cm);
            }
            CodeMirror.commands.save = tmp;
          });
          testVim('ex_sort', function(cm, vim, helpers) {
            helpers.doEx('sort');
            eq('Z\na\nb\nc\nd', cm.getValue());
          }, { value: 'b\nZ\nd\nc\na'});
          testVim('ex_sort_reverse', function(cm, vim, helpers) {
            helpers.doEx('sort!');
            eq('d\nc\nb\na', cm.getValue());
          }, { value: 'b\nd\nc\na'});
          testVim('ex_sort_range', function(cm, vim, helpers) {
            helpers.doEx('2,3sort');
            eq('b\nc\nd\na', cm.getValue());
          }, { value: 'b\nd\nc\na'});
          testVim('ex_sort_oneline', function(cm, vim, helpers) {
            helpers.doEx('2sort');
            // Expect no change.
            eq('b\nd\nc\na', cm.getValue());
          }, { value: 'b\nd\nc\na'});
          testVim('ex_sort_ignoreCase', function(cm, vim, helpers) {
            helpers.doEx('sort i');
            eq('a\nb\nc\nd\nZ', cm.getValue());
          }, { value: 'b\nZ\nd\nc\na'});
          testVim('ex_sort_unique', function(cm, vim, helpers) {
            helpers.doEx('sort u');
            eq('Z\na\nb\nc\nd', cm.getValue());
          }, { value: 'b\nZ\na\na\nd\na\nc\na'});
          testVim('ex_sort_decimal', function(cm, vim, helpers) {
            helpers.doEx('sort d');
            eq('d3\n s5\n6\n.9', cm.getValue());
          }, { value: '6\nd3\n s5\n.9'});
          testVim('ex_sort_decimal_negative', function(cm, vim, helpers) {
            helpers.doEx('sort d');
            eq('z-9\nd3\n s5\n6\n.9', cm.getValue());
          }, { value: '6\nd3\n s5\n.9\nz-9'});
          testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) {
            helpers.doEx('sort! d');
            eq('.9\n6\n s5\nd3', cm.getValue());
          }, { value: '6\nd3\n s5\n.9'});
          testVim('ex_sort_hex', function(cm, vim, helpers) {
            helpers.doEx('sort x');
            eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue());
          }, { value: '6\nd3\n s5\n&0xB\n.9'});
          testVim('ex_sort_octal', function(cm, vim, helpers) {
            helpers.doEx('sort o');
            eq('.8\n.9\nd3\n s5\n6', cm.getValue());
          }, { value: '6\nd3\n s5\n.9\n.8'});
          testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) {
            helpers.doEx('sort d');
            eq('y\nz\nc1\nb2\na3', cm.getValue());
          }, { value: 'a3\nz\nc1\ny\nb2'});
          testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) {
            helpers.doEx('sort! d');
            eq('a3\nb2\nc1\nz\ny', cm.getValue());
          }, { value: 'a3\nz\nc1\ny\nb2'});
          // test for :global command
          testVim('ex_global', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            helpers.doEx('g/one/s//two');
            eq('two two\n two two\n two two', cm.getValue());
            helpers.doEx('1,2g/two/s//one');
            eq('one one\n one one\n two two', cm.getValue());
          }, {value: 'one one\n one one\n one one'});
          testVim('ex_global_confirm', function(cm, vim, helpers) {
            cm.setCursor(0, 0);
            var onKeyDown;
            var openDialogSave = cm.openDialog;
            var KEYCODES = {
              a: 65,
              n: 78,
              q: 81,
              y: 89
            };
            // Intercept the ex command, 'global'
            cm.openDialog = function(template, callback, options) {
              // Intercept the prompt for the embedded ex command, 'substitute'
              cm.openDialog = function(template, callback, options) {
                onKeyDown = options.onKeyDown;
              };
              callback('g/one/s//two/gc');
            };
            helpers.doKeys(':');
            var close = function() {};
            onKeyDown({keyCode: KEYCODES.n}, '', close);
            onKeyDown({keyCode: KEYCODES.y}, '', close);
            onKeyDown({keyCode: KEYCODES.a}, '', close);
            onKeyDown({keyCode: KEYCODES.q}, '', close);
            onKeyDown({keyCode: KEYCODES.y}, '', close);
            eq('one two\n two two\n one one\n two one\n one one', cm.getValue());
          }, {value: 'one one\n one one\n one one\n one one\n one one'});
          // Basic substitute tests.
          testVim('ex_substitute_same_line', function(cm, vim, helpers) {
            cm.setCursor(1, 0);
            helpers.doEx('s/one/two/g');
            eq('one one\n two two', cm.getValue());
          }, { value: 'one one\n one one'});
          testVim('ex_substitute_full_file', function(cm, vim, helpers) {
            cm.setCursor(1, 0);
            helpers.doEx('%s/one/two/g');
            eq('two two\n two two', cm.getValue());
          }, { value: 'one one\n one one'});
          testVim('ex_substitute_input_range', function(cm, vim, helpers) {
            cm.setCursor(1, 0);
            helpers.doEx('1,3s/\\d/0/g');
            eq('0\n0\n0\n4', cm.getValue());
          }, { value: '1\n2\n3\n4' });
          testVim('ex_substitute_visual_range', function(cm, vim, helpers) {
            cm.setCursor(1, 0);
            // Set last visual mode selection marks '< and '> at lines 2 and 4
            helpers.doKeys('V', '2', 'j', 'v');
            helpers.doEx('\'<,\'>s/\\d/0/g');
            eq('1\n0\n0\n0\n5', cm.getValue());
          }, { value: '1\n2\n3\n4\n5' });
          testVim('ex_substitute_empty_query', function(cm, vim, helpers) {
            // If the query is empty, use last query.
            cm.setCursor(1, 0);
            cm.openDialog = helpers.fakeOpenDialog('1');
            helpers.doKeys('/');
            helpers.doEx('s//b/g');
            eq('abb ab2 ab3', cm.getValue());
          }, { value: 'a11 a12 a13' });
          testVim('ex_substitute_javascript', function(cm, vim, helpers) {
            CodeMirror.Vim.setOption('pcre', false);
            cm.setCursor(1, 0);
            // Throw all the things that javascript likes to treat as special values
            // into the replace part. All should be literal (this is VIM).
            helpers.doEx('s/\\(\\d+\\)/$$ $\' $` $& \\1/g')
            eq('a $$ $\' $` $& 0 b', cm.getValue());
          }, { value: 'a 0 b' });
          testVim('ex_substitute_empty_arguments', function(cm,vim,helpers) {
            cm.setCursor(0, 0);
            helpers.doEx('s/a/b/g');
            cm.setCursor(1, 0);
            helpers.doEx('s');
            eq('b b\nb a', cm.getValue());
          }, {value: 'a a\na a'});
          
          // More complex substitute tests that test both pcre and nopcre options.
          function testSubstitute(name, options) {
            testVim(name + '_pcre', function(cm, vim, helpers) {
              cm.setCursor(1, 0);
              CodeMirror.Vim.setOption('pcre', true);
              helpers.doEx(options.expr);
              eq(options.expectedValue, cm.getValue());
            }, options);
            // If no noPcreExpr is defined, assume that it's the same as the expr.
            var noPcreExpr = options.noPcreExpr ? options.noPcreExpr : options.expr;
            testVim(name + '_nopcre', function(cm, vim, helpers) {
              cm.setCursor(1, 0);
              CodeMirror.Vim.setOption('pcre', false);
              helpers.doEx(noPcreExpr);
              eq(options.expectedValue, cm.getValue());
            }, options);
          }
          testSubstitute('ex_substitute_capture', {
            value: 'a11 a12 a13',
            expectedValue: 'a1111 a1212 a1313',
            // $n is a backreference
            expr: 's/(\\d+)/$1$1/g',
            // \n is a backreference.
            noPcreExpr: 's/\\(\\d+\\)/\\1\\1/g'});
          testSubstitute('ex_substitute_capture2', {
            value: 'a 0 b',
            expectedValue: 'a $00 b',
            expr: 's/(\\d+)/$$$1$1/g',
            noPcreExpr: 's/\\(\\d+\\)/$\\1\\1/g'});
          testSubstitute('ex_substitute_nocapture', {
            value: 'a11 a12 a13',
            expectedValue: 'a$1$1 a$1$1 a$1$1',
            expr: 's/(\\d+)/$$1$$1/g',
            noPcreExpr: 's/\\(\\d+\\)/$1$1/g'});
          testSubstitute('ex_substitute_nocapture2', {
            value: 'a 0 b',
            expectedValue: 'a $10 b',
            expr: 's/(\\d+)/$$1$1/g',
            noPcreExpr: 's/\\(\\d+\\)/\\$1\\1/g'});
          testSubstitute('ex_substitute_nocapture', {
            value: 'a b c',
            expectedValue: 'a $ c',
            expr: 's/b/$$/',
            noPcreExpr: 's/b/$/'});
          testSubstitute('ex_substitute_slash_regex', {
            value: 'one/two \n three/four',
            expectedValue: 'one|two \n three|four',
            expr: '%s/\\//|'});
          testSubstitute('ex_substitute_pipe_regex', {
            value: 'one|two \n three|four',
            expectedValue: 'one,two \n three,four',
            expr: '%s/\\|/,/',
            noPcreExpr: '%s/|/,/'});
          testSubstitute('ex_substitute_or_regex', {
            value: 'one|two \n three|four',
            expectedValue: 'ana|twa \n thraa|faar',
            expr: '%s/o|e|u/a/g',
            noPcreExpr: '%s/o\\|e\\|u/a/g'});
          testSubstitute('ex_substitute_or_word_regex', {
            value: 'one|two \n three|four',
            expectedValue: 'five|five \n three|four',
            expr: '%s/(one|two)/five/g',
            noPcreExpr: '%s/\\(one\\|two\\)/five/g'});
          testSubstitute('ex_substitute_backslashslash_regex', {
            value: 'one\\two \n three\\four',
            expectedValue: 'one,two \n three,four',
            expr: '%s/\\\\/,'});
          testSubstitute('ex_substitute_slash_replacement', {
            value: 'one,two \n three,four',
            expectedValue: 'one/two \n three/four',
            expr: '%s/,/\\/'});
          testSubstitute('ex_substitute_backslash_replacement', {
            value: 'one,two \n three,four',
            expectedValue: 'one\\two \n three\\four',
            expr: '%s/,/\\\\/g'});
          testSubstitute('ex_substitute_multibackslash_replacement', {
            value: 'one,two \n three,four',
            expectedValue: 'one\\\\\\\\two \n three\\\\\\\\four', // 2*8 backslashes.
            expr: '%s/,/\\\\\\\\\\\\\\\\/g'}); // 16 backslashes.
          testSubstitute('ex_substitute_braces_word', {
            value: 'ababab abb ab{2}',
            expectedValue: 'ab abb ab{2}',
            expr: '%s/(ab){2}//g',
            noPcreExpr: '%s/\\(ab\\)\\{2\\}//g'});
          testSubstitute('ex_substitute_braces_range', {
            value: 'a aa aaa aaaa',
            expectedValue: 'a   a',
            expr: '%s/a{2,3}//g',
            noPcreExpr: '%s/a\\{2,3\\}//g'});
          testSubstitute('ex_substitute_braces_literal', {
            value: 'ababab abb ab{2}',
            expectedValue: 'ababab abb ',
            expr: '%s/ab\\{2\\}//g',
            noPcreExpr: '%s/ab{2}//g'});
          testSubstitute('ex_substitute_braces_char', {
            value: 'ababab abb ab{2}',
            expectedValue: 'ababab  ab{2}',
            expr: '%s/ab{2}//g',
            noPcreExpr: '%s/ab\\{2\\}//g'});
          testSubstitute('ex_substitute_braces_no_escape', {
            value: 'ababab abb ab{2}',
            expectedValue: 'ababab  ab{2}',
            expr: '%s/ab{2}//g',
            noPcreExpr: '%s/ab\\{2}//g'});
          testSubstitute('ex_substitute_count', {
            value: '1\n2\n3\n4',
            expectedValue: '1\n0\n0\n4',
            expr: 's/\\d/0/i 2'});
          testSubstitute('ex_substitute_count_with_range', {
            value: '1\n2\n3\n4',
            expectedValue: '1\n2\n0\n0',
            expr: '1,3s/\\d/0/ 3'});
          testSubstitute('ex_substitute_not_global', {
            value: 'aaa\nbaa\ncaa',
            expectedValue: 'xaa\nbxa\ncxa',
            expr: '%s/a/x/'});
          function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) {
            testVim(name, function(cm, vim, helpers) {
              var savedOpenDialog = cm.openDialog;
              var savedKeyName = CodeMirror.keyName;
              var onKeyDown;
              var recordedCallback;
              var closed = true; // Start out closed, set false on second openDialog.
              function close() {
                closed = true;
              }
              // First openDialog should save callback.
              cm.openDialog = function(template, callback, options) {
                recordedCallback = callback;
              }
              // Do first openDialog.
              helpers.doKeys(':');
              // Second openDialog should save keyDown handler.
              cm.openDialog = function(template, callback, options) {
                onKeyDown = options.onKeyDown;
                closed = false;
              };
              // Return the command to Vim and trigger second openDialog.
              recordedCallback(command);
              // The event should really use keyCode, but here just mock it out and use
              // key and replace keyName to just return key.
              CodeMirror.keyName = function (e) { return e.key; }
              keys = keys.toUpperCase();
              for (var i = 0; i < keys.length; i++) {
                is(!closed);
                onKeyDown({ key: keys.charAt(i) }, '', close);
              }
              try {
                eq(expectedValue, cm.getValue());
                helpers.assertCursorAt(finalPos);
                is(closed);
              } catch(e) {
                throw e
              } finally {
                // Restore overriden functions.
                CodeMirror.keyName = savedKeyName;
                cm.openDialog = savedOpenDialog;
              }
            }, { value: initialValue });
          };
          testSubstituteConfirm('ex_substitute_confirm_emptydoc',
              '%s/x/b/c', '', '', '', makeCursor(0, 0));
          testSubstituteConfirm('ex_substitute_confirm_nomatch',
              '%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0));
          testSubstituteConfirm('ex_substitute_confirm_accept',
              '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1));
          testSubstituteConfirm('ex_substitute_confirm_random_keys',
              '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1));
          testSubstituteConfirm('ex_substitute_confirm_some',
              '%s/a/b/cg', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1));
          testSubstituteConfirm('ex_substitute_confirm_all',
              '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1));
          testSubstituteConfirm('ex_substitute_confirm_accept_then_all',
              '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1));
          testSubstituteConfirm('ex_substitute_confirm_quit',
              '%s/a/b/cg', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3));
          testSubstituteConfirm('ex_substitute_confirm_last',
              '%s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3));
          testSubstituteConfirm('ex_substitute_confirm_oneline',
              '1s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3));
          testSubstituteConfirm('ex_substitute_confirm_range_accept',
              '1,2s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0));
          testSubstituteConfirm('ex_substitute_confirm_range_some',
              '1,3s/a/b/cg', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0));
          testSubstituteConfirm('ex_substitute_confirm_range_all',
              '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0));
          testSubstituteConfirm('ex_substitute_confirm_range_last',
              '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0));
          //:noh should clear highlighting of search-results but allow to resume search through n
          testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) {
            cm.openDialog = helpers.fakeOpenDialog('match');
            helpers.doKeys('?');
            helpers.doEx('noh');
            eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared');
            helpers.doKeys('n');
            helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting');
          }, { value: 'match nope match \n nope Match' });
          testVim('set_boolean', function(cm, vim, helpers) {
            CodeMirror.Vim.defineOption('testoption', true, 'boolean');
            // Test default value is set.
            is(CodeMirror.Vim.getOption('testoption'));
            try {
              // Test fail to set to non-boolean
              CodeMirror.Vim.setOption('testoption', '5');
              fail();
            } catch (expected) {};
            // Test setOption
            CodeMirror.Vim.setOption('testoption', false);
            is(!CodeMirror.Vim.getOption('testoption'));
          });
          testVim('ex_set_boolean', function(cm, vim, helpers) {
            CodeMirror.Vim.defineOption('testoption', true, 'boolean');
            // Test default value is set.
            is(CodeMirror.Vim.getOption('testoption'));
            try {
              // Test fail to set to non-boolean
              helpers.doEx('set testoption=22');
              fail();
            } catch (expected) {};
            // Test setOption
            helpers.doEx('set notestoption');
            is(!CodeMirror.Vim.getOption('testoption'));
          });
          testVim('set_string', function(cm, vim, helpers) {
            CodeMirror.Vim.defineOption('testoption', 'a', 'string');
            // Test default value is set.
            eq('a', CodeMirror.Vim.getOption('testoption'));
            try {
              // Test fail to set non-string.
              CodeMirror.Vim.setOption('testoption', true);
              fail();
            } catch (expected) {};
            try {
              // Test fail to set 'notestoption'
              CodeMirror.Vim.setOption('notestoption', 'b');
              fail();
            } catch (expected) {};
            // Test setOption
            CodeMirror.Vim.setOption('testoption', 'c');
            eq('c', CodeMirror.Vim.getOption('testoption'));
          });
          testVim('ex_set_string', function(cm, vim, helpers) {
            CodeMirror.Vim.defineOption('testopt', 'a', 'string');
            // Test default value is set.
            eq('a', CodeMirror.Vim.getOption('testopt'));
            try {
              // Test fail to set 'notestopt'
              helpers.doEx('set notestopt=b');
              fail();
            } catch (expected) {};
            // Test setOption
            helpers.doEx('set testopt=c')
            eq('c', CodeMirror.Vim.getOption('testopt'));
            helpers.doEx('set testopt=c')
            eq('c', CodeMirror.Vim.getOption('testopt', cm)); //local || global
            eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); // local
            eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); // global
            eq('c', CodeMirror.Vim.getOption('testopt')); // global
            // Test setOption global
            helpers.doEx('setg testopt=d')
            eq('c', CodeMirror.Vim.getOption('testopt', cm));
            eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'}));
            eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'}));
            eq('d', CodeMirror.Vim.getOption('testopt'));
            // Test setOption local
            helpers.doEx('setl testopt=e')
            eq('e', CodeMirror.Vim.getOption('testopt', cm));
            eq('e', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'}));
            eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'}));
            eq('d', CodeMirror.Vim.getOption('testopt'));
          });
          testVim('ex_set_callback', function(cm, vim, helpers) {
            var global;
          
            function cb(val, cm, cfg) {
              if (val === undefined) {
                // Getter
                if (cm) {
                  return cm._local;
                } else {
                  return global;
                }
              } else {
                // Setter
                if (cm) {
                  cm._local = val;
                } else {
                  global = val;
                }
              }
            }
          
            CodeMirror.Vim.defineOption('testopt', 'a', 'string', cb);
            // Test default value is set.
            eq('a', CodeMirror.Vim.getOption('testopt'));
            try {
              // Test fail to set 'notestopt'
              helpers.doEx('set notestopt=b');
              fail();
            } catch (expected) {};
            // Test setOption (Identical to the string tests, but via callback instead)
            helpers.doEx('set testopt=c')
            eq('c', CodeMirror.Vim.getOption('testopt', cm)); //local || global
            eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); // local
            eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); // global
            eq('c', CodeMirror.Vim.getOption('testopt')); // global
            // Test setOption global
            helpers.doEx('setg testopt=d')
            eq('c', CodeMirror.Vim.getOption('testopt', cm));
            eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'}));
            eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'}));
            eq('d', CodeMirror.Vim.getOption('testopt'));
            // Test setOption local
            helpers.doEx('setl testopt=e')
            eq('e', CodeMirror.Vim.getOption('testopt', cm));
            eq('e', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'}));
            eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'}));
            eq('d', CodeMirror.Vim.getOption('testopt'));
          })
          testVim('ex_set_filetype', function(cm, vim, helpers) {
            CodeMirror.defineMode('test_mode', function() {
              return {token: function(stream) {
                stream.match(/^\s+|^\S+/);
              }};
            });
            CodeMirror.defineMode('test_mode_2', function() {
              return {token: function(stream) {
                stream.match(/^\s+|^\S+/);
              }};
            });
            // Test mode is set.
            helpers.doEx('set filetype=test_mode');
            eq('test_mode', cm.getMode().name);
            // Test 'ft' alias also sets mode.
            helpers.doEx('set ft=test_mode_2');
            eq('test_mode_2', cm.getMode().name);
          });
          testVim('ex_set_filetype_null', function(cm, vim, helpers) {
            CodeMirror.defineMode('test_mode', function() {
              return {token: function(stream) {
                stream.match(/^\s+|^\S+/);
              }};
            });
            cm.setOption('mode', 'test_mode');
            // Test mode is set to null.
            helpers.doEx('set filetype=');
            eq('null', cm.getMode().name);
          });
          // TODO: Reset key maps after each test.
          testVim('ex_map_key2key', function(cm, vim, helpers) {
            helpers.doEx('map a x');
            helpers.doKeys('a');
            helpers.assertCursorAt(0, 0);
            eq('bc', cm.getValue());
          }, { value: 'abc' });
          testVim('ex_unmap_key2key', function(cm, vim, helpers) {
            helpers.doEx('unmap a');
            helpers.doKeys('a');
            eq('vim-insert', cm.getOption('keyMap'));
          }, { value: 'abc' });
          testVim('ex_unmap_key2key_does_not_remove_default', function(cm, vim, helpers) {
            try {
              helpers.doEx('unmap a');
              fail();
            } catch (expected) {}
            helpers.doKeys('a');
            eq('vim-insert', cm.getOption('keyMap'));
          }, { value: 'abc' });
          testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) {
            helpers.doEx('map ; :');
            var dialogOpened = false;
            cm.openDialog = function() {
              dialogOpened = true;
            }
            helpers.doKeys(';');
            eq(dialogOpened, true);
          });
          testVim('ex_map_ex2key:', function(cm, vim, helpers) {
            helpers.doEx('map :del x');
            helpers.doEx('del');
            helpers.assertCursorAt(0, 0);
            eq('bc', cm.getValue());
          }, { value: 'abc' });
          testVim('ex_map_ex2ex', function(cm, vim, helpers) {
            helpers.doEx('map :del :w');
            var tmp = CodeMirror.commands.save;
            var written = false;
            var actualCm;
            CodeMirror.commands.save = function(cm) {
              written = true;
              actualCm = cm;
            };
            helpers.doEx('del');
            CodeMirror.commands.save = tmp;
            eq(written, true);
            eq(actualCm, cm);
          });
          testVim('ex_map_key2ex', function(cm, vim, helpers) {
            helpers.doEx('map a :w');
            var tmp = CodeMirror.commands.save;
            var written = false;
            var actualCm;
            CodeMirror.commands.save = function(cm) {
              written = true;
              actualCm = cm;
            };
            helpers.doKeys('a');
            CodeMirror.commands.save = tmp;
            eq(written, true);
            eq(actualCm, cm);
          });
          testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) {
            CodeMirror.Vim.map('b', ':w', 'visual');
            var tmp = CodeMirror.commands.save;
            var written = false;
            var actualCm;
            CodeMirror.commands.save = function(cm) {
              written = true;
              actualCm = cm;
            };
            // Mapping should not work in normal mode.
            helpers.doKeys('b');
            eq(written, false);
            // Mapping should work in visual mode.
            helpers.doKeys('v', 'b');
            eq(written, true);
            eq(actualCm, cm);
          
            CodeMirror.commands.save = tmp;
          });
          testVim('ex_imap', function(cm, vim, helpers) {
            CodeMirror.Vim.map('jk', '<Esc>', 'insert');
            helpers.doKeys('i');
            is(vim.insertMode);
            helpers.doKeys('j', 'k');
            is(!vim.insertMode);
          })
          
          // Testing registration of functions as ex-commands and mapping to <Key>-keys
          testVim('ex_api_test', function(cm, vim, helpers) {
            var res=false;
            var val='from';
            CodeMirror.Vim.defineEx('extest','ext',function(cm,params){
              if(params.args)val=params.args[0];
              else res=true;
            });
            helpers.doEx(':ext to');
            eq(val,'to','Defining ex-command failed');
            CodeMirror.Vim.map('<C-CR><Space>',':ext');
            helpers.doKeys('<C-CR>','<Space>');
            is(res,'Mapping to key failed');
          });
          // For now, this test needs to be last because it messes up : for future tests.
          testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) {
            helpers.doEx('map : x');
            helpers.doKeys(':');
            helpers.assertCursorAt(0, 0);
            eq('bc', cm.getValue());
          }, { value: 'abc' });
          
          // Test event handlers
          testVim('beforeSelectionChange', function(cm, vim, helpers) {
            cm.setCursor(0, 100);
            eqPos(cm.getCursor('head'), cm.getCursor('anchor'));
          }, { value: 'abc' });
          
          
          
      • theme
        • 3024-day.css
          /*
          
              Name:       3024 day
              Author:     Jan T. Sott (http://github.com/idleberg)
          
              CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
              Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
          
          */
          
          .cm-s-3024-day.CodeMirror {background: #f7f7f7; color: #3a3432;}
          .cm-s-3024-day div.CodeMirror-selected {background: #d6d5d4 !important;}
          .cm-s-3024-day.CodeMirror ::selection { background: #d6d5d4; }
          .cm-s-3024-day.CodeMirror ::-moz-selection { background: #d9d9d9; }
          
          .cm-s-3024-day .CodeMirror-gutters {background: #f7f7f7; border-right: 0px;}
          .cm-s-3024-day .CodeMirror-guttermarker { color: #db2d20; }
          .cm-s-3024-day .CodeMirror-guttermarker-subtle { color: #807d7c; }
          .cm-s-3024-day .CodeMirror-linenumber {color: #807d7c;}
          
          .cm-s-3024-day .CodeMirror-cursor {border-left: 1px solid #5c5855 !important;}
          
          .cm-s-3024-day span.cm-comment {color: #cdab53;}
          .cm-s-3024-day span.cm-atom {color: #a16a94;}
          .cm-s-3024-day span.cm-number {color: #a16a94;}
          
          .cm-s-3024-day span.cm-property, .cm-s-3024-day span.cm-attribute {color: #01a252;}
          .cm-s-3024-day span.cm-keyword {color: #db2d20;}
          .cm-s-3024-day span.cm-string {color: #fded02;}
          
          .cm-s-3024-day span.cm-variable {color: #01a252;}
          .cm-s-3024-day span.cm-variable-2 {color: #01a0e4;}
          .cm-s-3024-day span.cm-def {color: #e8bbd0;}
          .cm-s-3024-day span.cm-bracket {color: #3a3432;}
          .cm-s-3024-day span.cm-tag {color: #db2d20;}
          .cm-s-3024-day span.cm-link {color: #a16a94;}
          .cm-s-3024-day span.cm-error {background: #db2d20; color: #5c5855;}
          
          .cm-s-3024-day .CodeMirror-activeline-background {background: #e8f2ff !important;}
          .cm-s-3024-day .CodeMirror-matchingbracket { text-decoration: underline; color: #a16a94 !important;}
          
        • 3024-night.css
          /*
          
              Name:       3024 night
              Author:     Jan T. Sott (http://github.com/idleberg)
          
              CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
              Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
          
          */
          
          .cm-s-3024-night.CodeMirror {background: #090300; color: #d6d5d4;}
          .cm-s-3024-night div.CodeMirror-selected {background: #3a3432 !important;}
          .cm-s-3024-night.CodeMirror ::selection { background: rgba(58, 52, 50, .99); }
          .cm-s-3024-night.CodeMirror ::-moz-selection { background: rgba(58, 52, 50, .99); }
          .cm-s-3024-night .CodeMirror-gutters {background: #090300; border-right: 0px;}
          .cm-s-3024-night .CodeMirror-guttermarker { color: #db2d20; }
          .cm-s-3024-night .CodeMirror-guttermarker-subtle { color: #5c5855; }
          .cm-s-3024-night .CodeMirror-linenumber {color: #5c5855;}
          
          .cm-s-3024-night .CodeMirror-cursor {border-left: 1px solid #807d7c !important;}
          
          .cm-s-3024-night span.cm-comment {color: #cdab53;}
          .cm-s-3024-night span.cm-atom {color: #a16a94;}
          .cm-s-3024-night span.cm-number {color: #a16a94;}
          
          .cm-s-3024-night span.cm-property, .cm-s-3024-night span.cm-attribute {color: #01a252;}
          .cm-s-3024-night span.cm-keyword {color: #db2d20;}
          .cm-s-3024-night span.cm-string {color: #fded02;}
          
          .cm-s-3024-night span.cm-variable {color: #01a252;}
          .cm-s-3024-night span.cm-variable-2 {color: #01a0e4;}
          .cm-s-3024-night span.cm-def {color: #e8bbd0;}
          .cm-s-3024-night span.cm-bracket {color: #d6d5d4;}
          .cm-s-3024-night span.cm-tag {color: #db2d20;}
          .cm-s-3024-night span.cm-link {color: #a16a94;}
          .cm-s-3024-night span.cm-error {background: #db2d20; color: #807d7c;}
          
          .cm-s-3024-night .CodeMirror-activeline-background {background: #2F2F2F !important;}
          .cm-s-3024-night .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • ambiance-mobile.css
          .cm-s-ambiance.CodeMirror {
            -webkit-box-shadow: none;
            -moz-box-shadow: none;
            box-shadow: none;
          }
          
        • ambiance.css
          /* ambiance theme for codemirror */
          
          /* Color scheme */
          
          .cm-s-ambiance .cm-keyword { color: #cda869; }
          .cm-s-ambiance .cm-atom { color: #CF7EA9; }
          .cm-s-ambiance .cm-number { color: #78CF8A; }
          .cm-s-ambiance .cm-def { color: #aac6e3; }
          .cm-s-ambiance .cm-variable { color: #ffb795; }
          .cm-s-ambiance .cm-variable-2 { color: #eed1b3; }
          .cm-s-ambiance .cm-variable-3 { color: #faded3; }
          .cm-s-ambiance .cm-property { color: #eed1b3; }
          .cm-s-ambiance .cm-operator {color: #fa8d6a;}
          .cm-s-ambiance .cm-comment { color: #555; font-style:italic; }
          .cm-s-ambiance .cm-string { color: #8f9d6a; }
          .cm-s-ambiance .cm-string-2 { color: #9d937c; }
          .cm-s-ambiance .cm-meta { color: #D2A8A1; }
          .cm-s-ambiance .cm-qualifier { color: yellow; }
          .cm-s-ambiance .cm-builtin { color: #9999cc; }
          .cm-s-ambiance .cm-bracket { color: #24C2C7; }
          .cm-s-ambiance .cm-tag { color: #fee4ff }
          .cm-s-ambiance .cm-attribute {  color: #9B859D; }
          .cm-s-ambiance .cm-header {color: blue;}
          .cm-s-ambiance .cm-quote { color: #24C2C7; }
          .cm-s-ambiance .cm-hr { color: pink; }
          .cm-s-ambiance .cm-link { color: #F4C20B; }
          .cm-s-ambiance .cm-special { color: #FF9D00; }
          .cm-s-ambiance .cm-error { color: #AF2018; }
          
          .cm-s-ambiance .CodeMirror-matchingbracket { color: #0f0; }
          .cm-s-ambiance .CodeMirror-nonmatchingbracket { color: #f22; }
          
          .cm-s-ambiance .CodeMirror-selected { background: rgba(255, 255, 255, 0.15); }
          .cm-s-ambiance.CodeMirror-focused .CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }
          .cm-s-ambiance.CodeMirror ::selection { background: rgba(255, 255, 255, 0.10); }
          .cm-s-ambiance.CodeMirror ::-moz-selection { background: rgba(255, 255, 255, 0.10); }
          
          /* Editor styling */
          
          .cm-s-ambiance.CodeMirror {
            line-height: 1.40em;
            color: #E6E1DC;
            background-color: #202020;
            -webkit-box-shadow: inset 0 0 10px black;
            -moz-box-shadow: inset 0 0 10px black;
            box-shadow: inset 0 0 10px black;
          }
          
          .cm-s-ambiance .CodeMirror-gutters {
            background: #3D3D3D;
            border-right: 1px solid #4D4D4D;
            box-shadow: 0 10px 20px black;
          }
          
          .cm-s-ambiance .CodeMirror-linenumber {
            text-shadow: 0px 1px 1px #4d4d4d;
            color: #111;
            padding: 0 5px;
          }
          
          .cm-s-ambiance .CodeMirror-guttermarker { color: #aaa; }
          .cm-s-ambiance .CodeMirror-guttermarker-subtle { color: #111; }
          
          .cm-s-ambiance .CodeMirror-lines .CodeMirror-cursor {
            border-left: 1px solid #7991E8;
          }
          
          .cm-s-ambiance .CodeMirror-activeline-background {
            background: none repeat scroll 0% 0% rgba(255, 255, 255, 0.031);
          }
          
          .cm-s-ambiance.CodeMirror,
          .cm-s-ambiance .CodeMirror-gutters {
            background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAQAAAAHUWYVAABFFUlEQVQYGbzBCeDVU/74/6fj9HIcx/FRHx9JCFmzMyGRURhLZIkUsoeRfUjS2FNDtr6WkMhO9sm+S8maJfu+Jcsg+/o/c+Z4z/t97/vezy3z+z8ekGlnYICG/o7gdk+wmSHZ1z4pJItqapjoKXWahm8NmV6eOTbWUOp6/6a/XIg6GQqmenJ2lDHyvCFZ2cBDbmtHA043VFhHwXxClWmeYAdLhV00Bd85go8VmaFCkbVkzlQENzfBDZ5gtN7HwF0KDrTwJ0dypSOzpaKCMwQHKTIreYIxlmhXTzTWkVm+LTynZhiSBT3RZQ7aGfjGEd3qyXQ1FDymqbKxpspERQN2MiRjNZlFFQXfCNFm9nM1zpAsoYjmtRTc5ajwuaXc5xrWskT97RaKzAGe5ARHhVUsDbjKklziiX5WROcJwSNCNI+9w1Jwv4Zb2r7lCMZ4oq5C0EdTx+2GzNuKpJ+iFf38JEWkHJn9DNF7mmBDITrWEg0VWL3pHU20tSZnuqWu+R3BtYa8XxV1HO7GyD32UkOpL/yDloINFTmvtId+nmAjxRw40VMwVKiwrKLE4bK5UOVntYwhOcSSXKrJHKPJedocpGjVz/ZMIbnYUPB10/eKCrs5apqpgVmWzBYWpmtKHecJPjaUuEgRDDaU0oZghCJ6zNMQ5ZhDYx05r5v2muQdM0EILtXUsaKiQX9WMEUotagQzFbUNN6NUPC2nm5pxEWGCjMc3GdJHjSU2kORLK/JGSrkfGEIjncU/CYUnOipoYemwj8tST9NsJmB7TUVXtbUtXATJVZXBMvYeTXJfobgJUPmGMP/yFaWonaa6BcFO3nqcIqCozSZoZoSr1g4zJOzuyGnxTEX3lUEJ7WcZgme8ddaWvWJo2AJR9DZU3CUIbhCSG6ybSwN6qtJVnCU2svDTP2ZInOw2cBTrqtQahtNZn9NcJ4l2NaSmSkkP1noZWnVwkLmdUPOwLZEwy2Z3S3R+4rIG9hcbpPXHFVWcQdZkn2FOta3cKWQnNRC5g1LsJah4GCzSVsKnCOY5OAFRTBekyyryeyilhFKva75r4Mc0aWanGEaThcy31s439KKxTzJYY5WTHPU1FtIHjQU3Oip4xlNzj/lBw23dYZVliQa7WAXf4shetcQfatI+jWRDBPmyNeW6A1P5kdDgyYJlba0BIM8BZu1JfrFwItyjcAMR3K0BWOIrtMEXyhyrlVEx3ui5dUBjmB/Q3CXW85R4mBD0s7B+4q5tKUjOlb9qqmhi5AZ6GFIC5HXtOobdYGlVdMVbNJ8toNTFcHxnoL+muBagcctjWnbNMuR00uI7nQESwg5q2qqrKWIfrNUmeQocY6HuyxJV02wj36w00yhpmUFenv4p6fUkZYqLyuinx2RGOjhCXYyJF84oiU00YMOOhhquNdfbOB7gU88pY4xJO8LVdp6/q2voeB4R04vIdhSE40xZObx1HGGJ/ja0LBthFInKaLPPFzuCaYaoj8JjPME8yoyxo6zlBqkiUZYgq00OYMswbWO5NGmq+xhipxHLRW29ARjNKXO0wRnear8XSg4XFPLKEPUS1GqvyLwiuBUoa7zpZ0l5xxFwWmWZC1H5h5FwU8eQ7K+g8UcVY6TMQreVQT/8uQ8Z+ALIXnSEa2pYZQneE9RZbSBNYXfWYJzW/h/4j4Dp1tYVcFIC5019Vyi4ThPqSFCzjGWaHQTBU8q6vrVwgxP9Lkm840imWKpcLCjYTtrKuwvsKSnrvHCXGkSMk9p6lhckfRpIeis+N2PiszT+mFLspyGleUhDwcLrZqmyeylxwjBcKHEapqkmyangyLZRVOijwOtCY5SsG5zL0OwlCJ4y5KznF3EUNDDrinwiyLZRzOXtlBbK5ITHFGLp8Q0R6ab6mS7enI2cFrxOyHvOCFaT1HThS1krjCwqWeurCkk+willhCC+RSZnRXBiZaC5RXRIZYKp2lyfrHwiKPKR0JDzrdU2EFgpidawlFDR6FgXUMNa+g1FY3bUQh2cLCwosRdnuQTS/S+JVrGLeWIvtQUvONJxlqSQYYKpwoN2kaocLjdVsis4Mk80ESF2YpSkzwldjHkjFCUutI/r+EHDU8oCs6yzL3PhWiEooZdFMkymlas4AcI3KmoMMNSQ3tHzjGWCrcJJdYyZC7QFGwjRL9p+MrRkAGWzIaWCn9W0F3TsK01c2ZvQw0byvxuQU0r1lM0qJO7wW0kRIMdDTtXEdzi4VIh+EoIHm0mWtAtpCixlabgn83fKTI7anJe9ST7WIK1DMGpQmYeA58ImV6ezOGOzK2Kgq01pd60cKWiUi9Lievb/0vIDPHQ05Kzt4ddPckQBQtoaurjyHnek/nKzpQLrVgKPjIkh2v4uyezpv+Xoo7fPFXaGFp1vaLKxQ4uUpQQS5VuQs7BCq4xRJv7fwpVvvFEB3j+620haOuocqMhWd6TTPAEx+mdFNGHdranFe95WrWmIvlY4F1Dle2ECgc6cto7SryuqGGGha0tFQ5V53migUKmg6XKAo4qS3mik+0OZpAhOLeZKicacgaYcyx5hypYQE02ZA4xi/pNhOQxR4klNKyqacj+mpxnLTnnGSo85++3ZCZq6lrZkXlGEX3o+C9FieccJbZWVFjC0Yo1FZnJhoYMFoI1hEZ9r6hwg75HwzBNhbZCdJEfJwTPGzJvaKImw1yYX1HDAmpXR+ZJQ/SmgqMNVQb5vgamGwLtt7VwvP7Qk1xpiM5x5Cyv93E06MZmgs0Nya2azIKOYKCGBQQW97RmhKNKF02JZqHEJ4o58qp7X5EcZmc56trXEqzjCBZ1MFGR87Ql2tSTs6CGxS05PTzRQorkbw7aKoKXFDXsYW42VJih/q+FP2BdTzDTwVqOYB13liM50vG7wy28qagyuIXMeQI/Oqq8bcn5wJI50xH00CRntyfpL1T4hydYpoXgNiFzoIUTDZnLNRzh4TBHwbYGDvZkxmlyJloyr6tRihpeUG94GnKtIznREF0tzJG/OOr73JBcrSh1k6WuTprgLU+mnSGnv6Zge0NNz+kTDdH8nuAuTdJDCNb21LCiIuqlYbqGzT3RAoZofQfjFazkqeNWdYaGvYTM001EW2oKPvVk1ldUGSgUtHFwjKM1h9jnFcmy5lChoLNaQMGGDsYbKixlaMBmmsx1QjCfflwTfO/gckW0ruZ3jugKR3R5W9hGUWqCgxuFgsuaCHorotGKzGaeZB9DMsaTnKCpMtwTvOzhYk0rdrArKCqcaWmVk1+F372ur1YkKxgatI8Qfe1gIX9wE9FgS8ESmuABIXnRUbCapcKe+nO7slClSZFzpV/LkLncEb1qiO42fS3R855Su2mCLh62t1SYZZYVmKwIHjREF2uihTzB20JOkz7dkxzYQnK0UOU494wh+VWRc6Un2kpTaVgLDFEkJ/uhzRcI0YKGgpGWOlocBU/a4fKoJ/pEaNV6jip3+Es9VXY078rGnmAdf7t9ylPXS34RBSuYPs1UecZTU78WanhBCHpZ5sAoTz0LGZKjPf9TRypqWEiTvOFglL1fCEY3wY/++rbk7C8bWebA6p6om6PgOL2kp44TFJlVNBXae2rqqdZztOJpT87GQsE9jqCPIe9VReZuQ/CIgacsyZdCpIScSYqcZk8r+nsyCzhyfhOqHGOIvrLknC8wTpFcaYiGC/RU1NRbUeUpocQOnkRpGOrIOcNRx+1uA0UrzhSSt+VyS3SJpnFWkzNDqOFGIWcfR86DnmARTQ1HKIL33ExPiemeOhYSSjzlSUZZuE4TveoJLnBUOFof6KiysCbnAEcZgcUNTDOwkqWu3RWtmGpZwlHhJENdZ3miGz0lJlsKnjbwqSHQjpxnFDlTLLwqJPMZMjd7KrzkSG7VsxXBZE+F8YZkb01Oe00yyRK9psh5SYh29ySPKBo2ylNht7ZkZnsKenjKNJu9PNEyZpaCHv4Kt6RQsLvAVp7M9kIimmCUwGeWqLMmGuIotYMmWNpSahkhZw9FqZsVnKJhsjAHvtHMsTM9fCI06Dx/u3vfUXCqfsKRc4oFY2jMsoo/7DJDwZ1CsIKnJu+J9ldkpmiCxQx1rWjI+T9FwcWWzOuaYH0Hj7klNRVWEQpmaqosakiGNTFHdjS/qnUdmf0NJW5xsL0HhimCCZZSRzmSPTXJQ4aaztAwtZnoabebJ+htCaZ7Cm535ByoqXKbX1WRc4Eh2MkRXWzImVc96Cj4VdOKVxR84VdQsIUM8Psoou2byVHyZFuq7O8otbSQ2UAoeEWTudATLGSpZzVLlXVkPU2Jc+27lsw2jmg5T5VhbeE3BT083K9WsTTkFU/Osi0rC5lRlpwRHUiesNS0sOvmqGML1aRbPAxTJD9ZKtxuob+hhl8cwYGWpJ8nub7t5p6coYbMovZ1BTdaKn1jYD6h4GFDNFyT/Kqe1XCXphXHOKLZmuRSRdBPEfVUXQzJm5YGPGGJdvAEr7hHNdGZnuBvrpciGmopOLf5N0uVMy0FfYToJk90uUCbJupaVpO53UJXR2bVpoU00V2KOo4zMFrBd0Jtz2pa0clT5Q5L8IpQ177mWQejPMEJhuQjS10ref6HHjdEhy1P1EYR7GtO0uSsKJQYLiTnG1rVScj5lyazpqWGl5uBbRWl7m6ixGOOnEsMJR7z8J0n6KMnCdxhiNYQCoZ6CmYLnO8omC3MkW3bktlPmEt/VQQHejL3+dOE5FlPdK/Mq8hZxxJtLyRrepLThYKbLZxkSb5W52vYxNOaOxUF0yxMUPwBTYqCzy01XayYK0sJyWBLqX0MwU5CzoymRzV0EjjeUeLgDpTo6ij42ZAzvD01dHUUTPLU96MdLbBME8nFBn7zJCMtJcZokn8YoqU0FS5WFKyniHobguMcmW8N0XkWZjkyN3hqOMtS08r+/xTBwpZSZ3qiVRX8SzMHHjfUNFjgHEPmY9PL3ykEzxkSre/1ZD6z/NuznuB0RcE1TWTm9zRgfUWVJiG6yrzgmWPXC8EAR4Wxhlad0ZbgQyEz3pG5RVEwwDJH2mgKpjcTiCOzn1lfUWANFbZ2BA8balnEweJC9J0iuaeZoI+ippFCztEKVvckR2iice1JvhVytrQwUAZpgsubCPaU7xUe9vWnaOpaSBEspalykhC9bUlOMpT42ZHca6hyrqKmw/wMR8H5ZmdFoBVJb03O4UL0tSNnvIeRmkrLWqrs78gcrEn2tpcboh0UPOW3UUR9PMk4T4nnNKWmCjlrefhCwxRNztfmIQVdDElvS4m1/WuOujoZCs5XVOjtKPGokJzsYCtFYoWonSPT21DheU/wWhM19FcElwqNGOsp9Q8N/cwXaiND1MmeL1Q5XROtYYgGeFq1aTMsoMmcrKjQrOFQTQ1fmBYhmW6o8Jkjc7iDJRTBIo5kgJD5yMEYA3srCg7VFKwiVJkmRCc5ohGOKhsYMn/XBLdo5taZjlb9YAlGWRimqbCsoY7HFAXLa5I1HPRxMMsQDHFkWtRNniqT9UEeNjcE7RUlrCJ4R2CSJuqlKHWvJXjAUNcITYkenuBRB84TbeepcqTj3zZyFJzgYQdHnqfgI0ddUwS6GqWpsKWhjq9cV0vBAEMN2znq+EBfIWT+pClYw5xsTlJU6GeIBsjGmmANTzJZiIYpgrM0Oa8ZMjd7NP87jxhqGOhJlnQtjuQpB+8aEE00wZFznSJPyHxgH3HkPOsJFvYk8zqCHzTs1BYOa4J3PFU+UVRZxlHDM4YavlNUuMoRveiZA2d7grMNc2g+RbSCEKzmgYsUmWmazFJyoiOZ4KnyhKOGRzWJa0+moyV4TVHDzn51Awtqaphfk/lRQ08FX1iiqxTB/kLwd0VynKfEvI6cd4XMV5bMhZ7gZUWVzYQ6Nm2BYzxJbw3bGthEUUMfgbGeorae6DxHtJoZ6alhZ0+ytiVoK1R4z5PTrOECT/SugseEOlb1MMNR4VRNcJy+V1Hg9ONClSZFZjdHlc6W6FBLdJja2MC5hhpu0DBYEY1TFGwiFAxRRCsYkiM9JRb0JNMVkW6CZYT/2EiTGWmo8k+h4FhDNE7BvppoTSFnmCV5xZKzvcCdDo7VVPnIU+I+Rc68juApC90MwcFCsJ5hDqxgScYKreruyQwTqrzoqDCmhWi4IbhB0Yrt3RGa6GfDv52rKXWhh28dyZaWUvcZeMTBaZoSGyiCtRU5J8iviioHaErs7Jkj61syVzTTgOcUOQ8buFBTYWdL5g3T4qlpe0+wvD63heAXRfCCIed9RbCsp2CiI7raUOYOTU13N8PNHvpaGvayo4a3LLT1lDrVEPT2zLUlheB1R+ZTRfKWJ+dcocLJfi11vyJ51lLqJ0WD7tRwryezjiV5W28uJO9qykzX8JDe2lHl/9oyBwa2UMfOngpXCixvKdXTk3wrsKmiVYdZIqsoWEERjbcUNDuiaQomGoIbFdEHmsyWnuR+IeriKDVLnlawlyNHKwKlSU631PKep8J4Q+ayjkSLKYLhalNHlYvttb6fHm0p6OApsZ4l2VfdqZkjuysy6ysKLlckf1KUutCTs39bmCgEyyoasIWlVaMF7mgmWtBT8Kol5xpH9IGllo8cJdopcvZ2sImlDmMIbtDk3KIpeNiS08lQw11NFPTwVFlPP6pJ2gvRfI7gQUfmNAtf6Gs0wQxDsKGlVBdF8rCa3jzdwMaGHOsItrZk7hAyOzpK9VS06j5F49b0VNGOOfKs3lDToMsMBe9ZWtHFEgxTJLs7qrygKZjUnmCYoeAqeU6jqWuLJup4WghOdvCYJnrSkSzoyRkm5M2StQwVltPkfCAk58tET/CSg+8MUecmotMEnhBKfWBIZsg2ihruMJQaoIm+tkTLKEqspMh00w95gvFCQRtDwTT1gVDDSEVdlwqZfxoQRbK0g+tbiBZxzKlpnpypejdDwTaeOvorMk/IJE10h9CqRe28hhLbe0pMsdSwv4ZbhKivo2BjDWfL8UKJgeavwlwb5KlwhyE4u4XkGE2ytZCznKLCDZZq42VzT8HLCrpruFbIfOIINmh/qCdZ1ZBc65kLHR1Bkyf5zn6pN3SvGKIlFNGplhrO9QSXanLOMQTLCa0YJCRrCZm/CZmrLTm7WzCK4GJDiWUdFeYx1LCFg3NMd0XmCuF3Y5rITLDUsYS9zoHVzwnJoYpSTQoObyEzr4cFBNqYTopoaU/wkyLZ2lPhX/5Y95ulxGTV7KjhWrOZgl8MyUUafjYraNjNU1N3IWcjT5WzWqjwtoarHSUObGYO3GCJZpsBlnJGPd6ZYLyl1GdCA2625IwwJDP8GUKymbzuyPlZlvTUsaUh5zFDhRWFzPKKZLAlWdcQbObgF9tOqOsmB1dqcqYJmWstFbZRRI9poolmqiLnU0POvxScpah2iSL5UJNzgScY5+AuIbpO0YD3NCW+dLMszFSdFCWGqG6eVq2uYVNDdICGD6W7EPRWZEY5gpsE9rUkS3mijzzJnm6UpUFXG1hCUeVoS5WfNcFpblELL2qqrCvMvRfd45oalvKU2tiQ6ePJOVMRXase9iTtLJztPxJKLWpo2CRDcJwn2sWSLKIO1WQWNTCvpVUvOZhgSC40JD0dOctaSqzkCRbXsKlb11Oip6PCJ0IwSJM31j3akRxlP7Rwn6aGaUL0qiLnJkvB3xWZ2+Q1TfCwpQH3G0o92UzmX4o/oJNQMMSQc547wVHhdk+VCw01DFYEnTxzZKAm74QmeNNR1w6WzEhNK15VJzuCdxQ53dRUDws5KvwgBMOEgpcVNe0hZI6RXT1Jd0cyj5nsaEAHgVmGaJIlWdsc5Ui2ElrRR6jrRAttNMEAIWrTDFubkZaok7/AkzfIwfuWVq0jHzuCK4QabtLUMVPB3kJ0oyHTSVFlqMALilJf2Rf8k5aaHtMfayocLBS8L89oKoxpJvnAkDPa0qp5DAUTHKWmCcnthlou8iCKaFFLHWcINd1nyIwXqrSxMNmSs6KmoL2QrKuWtlQ5V0120xQ5vRyZS1rgFkWwhiOwiuQbR0OOVhQM9iS3tiXp4RawRPMp5tDletOOBL95MpM01dZTBM9pkn5qF010rIeHFcFZhmSGpYpTsI6nwhqe5C9ynhlpp5ophuRb6WcJFldkVnVEwwxVfrVkvnWUuNLCg5bgboFHPDlDPDmnK7hUrWiIbjadDclujlZcaokOFup4Ri1kacV6jmrrK1hN9bGwpKEBQ4Q6DvIUXOmo6U5LqQM6EPyiKNjVkPnJkDPNEaxhiFay5ExW1NXVUGqcpYYdPcGiCq7z/TSlbhL4pplWXKd7NZO5QQFrefhRQW/NHOsqcIglc4UhWklR8K0QzbAw08CBDnpbgqXdeD/QUsM4RZXDFBW6WJKe/mFPdH0LtBgiq57wFLzlyQzz82qYx5D5WJP5yVJDW01BfyHnS6HKO/reZqId1WGa4Hkh2kWodJ8i6KoIPlAj2hPt76CzXsVR6koPRzWTfKqIentatYpQw2me4AA3y1Kind3SwoOKZDcFXTwl9tWU6mfgRk9d71sKtlNwrjnYw5tC5n5LdKiGry3JKNlHEd3oaMCFHrazBPMp/uNJ+V7IudcSbeOIdjUEdwl0VHCOZo5t6YluEuaC9mQeMgSfOyKnYGFHcIeQ84yQWbuJYJpZw5CzglDH7gKnWqqM9ZTaXcN0TeYhR84eQtJT76JJ1lREe7WnnvsMmRc9FQ7SBBM9mV3lCUdmHk/S2RAMt0QjFNFqQpWjDPQ01DXWUdDBkXziKPjGEP3VP+zIWU2t7im41FOloyWzn/L6dkUy3VLDaZ6appgDLHPjJEsyvJngWEPUyVBiAaHCTEXwrLvSEbV1e1gKJniicWorC1MUrVjB3uDhJE/wgSOzk1DXpk0k73qCM8xw2UvD5kJmDUfOomqMpWCkJRlvKXGmoeBm18USjVIk04SClxTB6YrgLAPLWYK9HLUt5cmc0vYES8GnTeRc6skZbQkWdxRsIcyBRzx1DbTk9FbU0caTPOgJHhJKnOGIVhQqvKmo0llRw9sabrZkDtdg3PqaKi9oatjY8B+G371paMg6+mZFNNtQ04mWBq3rYLOmtWWQp8KJnpy9DdFensyjdqZ+yY40VJlH8wcdLzC8PZnvHMFUTZUrDTkLyQaGus5X5LzpYAf3i+e/ZlhqGqWhh6Ou6xTR9Z6oi5AZZtp7Mj2EEm8oSpxiYZCHU/1fbGdNNNRRoZMhmilEb2gqHOEJDtXkHK/JnG6IrvbPCwV3NhONVdS1thBMs1T4QOBcTWa2IzhMk2nW5Kyn9tXUtpv9RsG2msxk+ZsQzRQacJncpgke0+T8y5Fzj8BiGo7XlJjaTIlpQs7KFjpqGnKuoyEPeIKnFMkZHvopgh81ySxNFWvJWcKRs70j2FOT012IllEEO1n4pD1513Yg2ssQPOThOkvyrqHUdEXOSEsihmBbTbKX1kLBPWqWkLOqJbjB3GBIZmoa8qWl4CG/iZ7oiA72ZL7TJNeZUY7kFQftDcHHluBzRbCegzMtrRjVQpX2lgoPKKLJAkcbMl01XK2p7yhL8pCBbQ3BN2avJgKvttcrWDK3CiUOVxQ8ZP+pqXKyIxnmBymCg5vJjNfkPK4+c8cIfK8ocVt7kmfd/I5SR1hKvCzUtb+lhgc00ZaO6CyhIQP1Uv4yIZjload72PXX0OIJvnFU+0Zf6MhsJwTfW0r0UwQfW4LNLZl5HK261JCZ4qnBaAreVAS3WrjV0LBnNDUNNDToCEeFfwgcb4gOEqLRhirWkexrCEYKVV711DLYEE1XBEsp5tpTGjorkomKYF9FDXv7fR3BGwbettSxnyL53MBPjsxDZjMh+VUW9NRxq1DhVk+FSxQcaGjV9Pawv6eGByw5qzoy7xk4RsOShqjJwWKe/1pEEfzkobeD/dQJmpqedcyBTy2sr4nGNRH0c0SPWTLrqAc0OQcb/gemKgqucQT7ySWKCn2EUotoCvpZct7RO2sy/QW0IWcXd7pQRQyZVwT2USRO87uhjioTLKV2brpMUcMQRbKH/N2T+UlTpaMls6cmc6CCNy3JdYYSUzzJQ4oSD3oKLncULOiJvjBEC2oqnCJkJluCYy2ZQ5so9YYlZ1VLlQU1mXEW1jZERwj/MUSRc24TdexlqLKfQBtDTScJUV8FszXBEY5ktpD5Ur9hYB4Nb1iikw3JoYpkKX+RodRKFt53MMuRnKSpY31PwYaGaILh3wxJGz9TkTPEETxoCWZrgvOlmyMzxFEwVJE5xZKzvyJ4WxEc16Gd4Xe3Weq4XH2jKRikqOkGQ87hQnC7wBmGYLAnesX3M+S87eFATauuN+Qcrh7xIxXJbUIdMw3JGE3ylCWzrieaqCn4zhGM19TQ3z1oH1AX+pWEqIc7wNGAkULBo/ZxRaV9NNyh4Br3rCHZzbzmSfawBL0dNRwpW1kK9mxPXR9povcdrGSZK9c2k0xwFGzjuniCtRSZCZ6ccZ7gaktmgAOtKbG/JnOkJrjcQTdFMsxRQ2cLY3WTIrlCw1eWKn8R6pvt4GFDso3QoL4a3nLk3G6JrtME3dSenpx7PNFTmga0EaJTLQ061sEeQoWXhSo9LTXsaSjoJQRXeZLtDclbCrYzfzHHeaKjHCVOUkQHO3JeEepr56mhiyaYYKjjNU+Fed1wS5VlhWSqI/hYUdDOkaxiKehoyOnrCV5yBHtbWFqTHCCwtpDcYolesVR5yUzTZBb3RNMd0d6WP+SvhuBmRcGxnuQzT95IC285cr41cLGQ6aJJhmi4TMGempxeimBRQw1tFKV+8jd6KuzoSTqqDxzRtpZkurvKEHxlqXKRIjjfUNNXQsNOsRScoWFLT+YeRZVD3GRN0MdQcKqQjHDMrdGGVu3iYJpQx3WGUvfbmxwFfR20WBq0oYY7LMFhhgYtr8jpaEnaOzjawWWaTP8mMr0t/EPDPoqcnxTBI5o58L7uoWnMrpoqPwgVrlAUWE+V+TQl9rawoyP6QGAlQw2TPRX+YSkxyBC8Z6jhHkXBgQL7WII3DVFnRfCrBfxewv9D6xsyjys4VkhWb9pUU627JllV0YDNHMku/ldNMMXDEo4aFnAkk4U6frNEU4XgZUPmEKHUl44KrzmYamjAbh0JFvGnaTLPu1s9jPCwjFpYiN7z1DTOk/nc07CfDFzmCf7i+bfNHXhDtLeBXzTBT5rkMvWOIxpl4EMh2LGJBu2syDnAEx2naEhHDWMMzPZEhygyS1mS5RTJr5ZkoKbEUoYqr2kqdDUE8ztK7OaIntJkFrIECwv8LJTaVx5XJE86go8dFeZ3FN3rjabCAYpoYEeC9zzJVULBbmZhDyd7ko09ydpNZ3nm2Kee4FPPXHnYEF1nqOFEC08LUVcDvYXkJHW8gTaKCk9YGOeIJhqiE4ToPEepdp7IWFjdwnWaufGMwJJCMtUTTBBK9BGCOy2tGGrJTHIwyEOzp6aPzNMOtlZkDvcEWpP5SVNhfkvDxhmSazTJXYrM9U1E0xwFVwqZQwzJxw6+kGGGUj2FglGGmnb1/G51udRSMNlTw6GGnCcUwVcOpmsqTHa06o72sw1RL02p9z0VbnMLOaIX3QKaYKSCFQzBKEUNHTSc48k53RH9wxGMtpQa5KjjW0W0n6XCCCG4yxNNdhQ4R4l1Ff+2sSd6UFHiIEOyqqFgT01mEUMD+joy75jPhOA+oVVLm309FR4yVOlp4RhLiScNmSmaYF5Pw0STrOIoWMSR2UkRXOMp+M4SHW8o8Zoi6OZgjKOaFar8zZDzkWzvKOjkKBjmCXby8JahhjXULY4KlzgKLvAwxVGhvyd4zxB1d9T0piazmKLCVZY5sKiD0y2ZSYrkUEPUbIk+dlQ4SJHTR50k1DPaUWIdTZW9NJwnJMOECgd7ou/MnppMJ02O1VT4Wsh85MnZzcFTngpXGKo84qmwgKbCL/orR/SzJ2crA+t6Mp94KvxJUeIbT3CQu1uIdlQEOzlKfS3UMcrTiFmOuroocrZrT2AcmamOKg8YomeEKm/rlT2sociMaybaUlFhuqHCM2qIJ+rg4EcDFymiDSxzaHdPcpE62pD5kyM5SBMoA1PaUtfIthS85ig1VPiPPYXgYEMNk4Qq7TXBgo7oT57gPUdwgCHzhIVFPFU6OYJzHAX9m5oNrVjeE61miDrqQ4VSa1oiURTsKHC0IfjNwU2WzK6eqK8jWln4g15TVBnqmDteCJ501PGAocJhhqjZdtBEB6lnhLreFJKxmlKbeGrqLiSThVIbCdGzloasa6lpMQXHCME2boLpJgT7yWaemu6wBONbqGNVRS0PKIL7LckbjmQtR7K8I5qtqel+T/ChJTNIKLjdUMNIRyvOEko9YYl2cwQveBikCNawJKcLBbc7+JM92mysNvd/Fqp8a0k6CNEe7cnZrxlW0wQXaXjaktnRwNOGZKYiONwS7a1JVheq3WgJHlQUGKHKmp4KAxXR/ULURcNgoa4zhKSLpZR3kxRRb0NmD0OFn+UCS7CzI1nbP6+o4x47QZE5xRCt3ZagnYcvmpYQktXdk5YKXTzBC57kKEe0VVuiSYqapssMS3C9p2CKkHOg8B8Pa8p5atrIw3qezIWanMGa5HRDNF6RM9wcacl0N+Q8Z8hsIkSnaIIdHRUOEebAPy1zbCkhM062FCJtif7PU+UtoVXzWKqM1PxXO8cfdruhFQ/a6x3JKYagvVDhQEtNiyiiSQ7OsuRsZUku0CRNDs4Sog6KKjsZgk2bYJqijgsEenoKeniinRXBn/U3lgpPdyDZynQx8IiioMnCep5Ky8mjGs6Wty0l1hUQTcNWswS3WRp2kCNZwJG8omG8JphPUaFbC8lEfabwP7VtM9yoaNCAjpR41VNhrD9LkbN722v0CoZMByFzhaW+MyzRYEWFDQwN2M4/JiT76PuljT3VU/A36eaIThb+R9oZGOAJ9tewkgGvqOMNRWYjT/Cwu99Q8LqDE4TgbLWxJ1jaDDAERsFOFrobgjUsBScaguXU8kKm2RL19tRypSHnHNlHiIZqgufs4opgQdVdwxBNNFBR6kVFqb8ogimOzB6a6HTzrlDHEpYaxjiiA4TMQobkDg2vejjfwJGWmnbVFAw3H3hq2NyQfG7hz4aC+w3BbwbesG0swYayvpAs6++Ri1Vfzx93mFChvyN5xVHTS+0p9aqCAxyZ6ZacZyw5+7uuQkFPR9DDk9NOiE7X1PCYJVjVUqq7JlrHwWALF5nfHNGjApdpqgzx5OwilDhCiDYTgnc9waGW4BdLNNUQvOtpzDOWHDH8D7TR/A/85KljEQu3NREc4Pl/6B1Hhc8Umb5CsKMmGC9EPcxoT2amwHNCmeOEnOPbklnMkbOgIvO5UMOpQrS9UGVdt6iH/fURjhI/WOpaW9OKLYRod6HCUEdOX000wpDZQ6hwg6LgZfOqo1RfT/CrJzjekXOGhpc1VW71ZLbXyyp+93ILbC1kPtIEYx0FIx1VDrLoVzXRKRYWk809yYlC9ImcrinxtabKnzRJk3lAU1OLEN1j2zrYzr2myHRXJFf4h4QKT1qSTzTB5+ZNTzTRkAxX8FcLV2uS8eoQQ2aAkFzvCM72sJIcJET3WPjRk5wi32uSS9rfZajpWEvj9hW42F4o5NytSXYy8IKHay10VYdrcl4SkqscrXpMwyGOgtkajheSxdQqmpxP1L3t4R5PqasFnrQEjytq6qgp9Y09Qx9o4S1FzhUCn1kyHSzBWLemoSGvOqLNhZyBjmCaAUYpMgt4Ck7wBBMMwWKWgjsUwTaGVsxWC1mYoKiyqqeGKYqonSIRQ3KIkHO0pmAxTdBHkbOvfllfr+AA+7gnc50huVKYK393FOyg7rbPO/izI7hE4CnHHHnJ0ogNPRUGeUpsrZZTBJcrovUcJe51BPsr6GkJdhCCsZ6aTtMEb2pqWkqeVtDXE/QVggsU/Nl86d9RMF3DxvZTA58agu810RWawCiSzzXBeU3MMW9oyJUedvNEvQyNu1f10BSMddR1vaLCYpYa/mGocLSiYDcLbQz8aMn5iyF4xBNMs1P0QEOV7o5gaWGuzSeLue4tt3ro7y4Tgm4G/mopdZgl6q0o6KzJWE3mMksNr3r+a6CbT8g5wZNzT9O7fi/zpaOmnz3BRoqos+tv9zMbdpxsqDBOEewtJLt7cg5wtKKbvldpSzRRCD43VFheCI7yZLppggMVBS/KMAdHODJvOwq2NQSbKKKPLdFWQs7Fqo+mpl01JXYRgq8dnGLhTiFzqmWsUMdpllZdbKlyvSdYxhI9YghOtxR8LgSLWHK62mGGVoxzBE8LNWzqH9CUesQzFy5RQzTc56mhi6fgXEWwpKfE5Z7M05ZgZUPmo6auiv8YKzDYwWBLMErIbKHJvOwIrvEdhOBcQ9JdU1NHQ7CXn2XIDFBKU2WAgcX9UAUzDXWd5alwuyJ41Z9rjKLCL4aCp4WarhPm2rH+SaHUYE001JDZ2ZAzXPjdMpZWvC9wmqIB2lLhQ01D5jO06hghWMndbM7yRJMsoCj1vYbnFQVrW9jak3OlEJ3s/96+p33dEPRV5GxiqaGjIthUU6FFEZyqCa5qJrpBdzSw95IUnOPIrCUUjRZQFrbw5PR0R1qiYx3cb6nrWUMrBmmiBQxVHtTew5ICP/ip6g4hed/Akob/32wvBHsIOX83cI8hGeNeNPCIkPmXe8fPKx84OMSRM1MTdXSwjCZ4S30jVGhvqTRak/OVhgGazHuOCud5onEO1lJr6ecVyaOK6H7zqlBlIaHE0oroCgfvGJIdPcmfLNGLjpz7hZwZQpUbFME0A1cIJa7VNORkgfsMBatbKgwwJM9bSvQXeNOvbIjelg6WWvo5kvbKaJJNHexkKNHL9xRyFlH8Ti2riB5wVPhUk7nGkJnoCe428LR/wRGdYIlmWebCyxou1rCk4g/ShugBDX0V0ZQWkh0dOVsagkM0yV6OoLd5ye+pRlsCr0n+KiQrGuq5yJDzrTAXHtLUMduTDBVKrSm3eHL+6ijxhFDX9Z5gVU/wliHYTMiMFpKLNMEywu80wd3meoFmt6VbRMPenhrOc6DVe4pgXU8DnnHakLOIIrlF4FZPIw6R+zxBP0dyq6OOZ4Q5sLKCcz084ok+VsMMyQhNZmmBgX5xIXOEJTmi7VsGTvMTNdHHhpzdbE8Du2oKxgvBqQKdDDnTFOylCFaxR1syz2iqrOI/FEpNc3C6f11/7+ASS6l2inq2ciTrCCzgyemrCL5SVPjQkdPZUmGy2c9Sw9FtR1sS30RmsKPCS4rkIC/2U0MduwucYolGaPjKEyhzmiPYXagyWbYz8LWBDdzRimAXzxx4z8K9hpzlhLq+NiQ97HuKorMUfK/OVvC2JfiHUPCQI/q7J2gjK+tTDNxkCc4TMssqCs4TGtLVwQihyoAWgj9bosU80XGW6Ac9TJGziaUh5+hnFcHOnlaM1iRn29NaqGENTTTSUHCH2tWTeV0osUhH6psuVLjRUmGWhm6OZEshGeNowABHcJ2Bpy2ZszRcKkRXd2QuKVEeXnbfaEq825FguqfgfE2whlChSRMdron+LATTPQ2Z369t4B9C5gs/ylzv+CMmepIDPclFQl13W0rspPd1JOcbghGOEutqCv5qacURQl3dDKyvyJlqKXGPgcM9FfawJAMVmdcspcYKOZc4GjDYkFlK05olNMHyHn4zFNykyOxt99RkHlfwmiHo60l2EKI+mhreEKp080Tbug08BVPcgoqC5zWt+NLDTZ7oNSF51N1qie7Va3uCCwyZbkINf/NED6jzOsBdZjFN8oqG3wxVunqCSYYKf3EdhJyf9YWGf7tRU2oH3VHgPr1fe5J9hOgHd7xQ0y7qBwXr23aGErP0cm64JVjZwsOGqL+mhNgZmhJLW2oY4UhedsyBgzrCKrq7BmcpNVhR6jBPq64Vgi+kn6XE68pp8J5/+0wRHGOpsKenQn9DZntPzjRLZpDAdD2fnSgkG9tmIXnUwQ6WVighs7Yi2MxQ0N3CqYaCXkJ0oyOztMDJjmSSpcpvlrk0RMMOjmArQ04PRV1DO1FwhCVaUVPpKUM03JK5SxPsIWRu8/CGHi8UHChiqGFDTbSRJWeYUDDcH6vJWUxR4k1FXbMUwV6e4AJFXS8oMqsZKqzvYQ9DDQdZckY4aGsIhtlubbd2r3j4QBMoTamdPZk7O/Bf62lacZwneNjQoGcdVU7zJOd7ghsUHOkosagic6cnWc8+4gg285R6zZP5s1/LUbCKIznTwK36PkdwlOrl4U1LwfdCCa+IrvFkmgw1PCAUXKWo0sURXWcI2muKJlgyFzhynCY4RBOsqCjoI1R5zREco0n2Vt09BQtYSizgKNHfUmUrQ5UOCh51BFcLmY7umhYqXKQomOop8bUnWNNQcIiBcYaC6xzMNOS8JQQfeqKBmmglB+97ok/lfk3ygaHSyZaCRTzRxQo6GzLfa2jWBPepw+UmT7SQEJyiyRkhBLMVOfcoMjcK0eZChfUNzFAUzCsEN5vP/X1uP/n/aoMX+K+nw/Hjr/9xOo7j7Pju61tLcgvJpTWXNbfN5jLpi6VfCOviTktKlFusQixdEKWmEBUKNaIpjZRSSOXSgzaaKLdabrm1/9nZ+/f+vd/vz/v9+Xy+zZ7PRorYoZqyLrCwQdEAixxVOEXNNnjX2nUSRlkqGmWowk8lxR50JPy9Bo6qJXaXwNvREBvnThPEPrewryLhcAnj5WE15Fqi8W7R1sAuEu86S4ENikItFN4xkv9Af4nXSnUVcLiA9xzesFpivRRVeFKtsMRaKBhuSbjOELnAUtlSQUpXgdfB4Z1oSbnFEetbQ0IrAe+Y+pqnDcEJFj6S8LDZzZHwY4e3XONNlARraomNEt2bkvGsosA3ioyHm+6jCMbI59wqt4eeara28IzEmyPgoRaUOEDhTVdEJhmCoTWfC0p8aNkCp0oYqih2iqGi4yXeMkOsn4LdLLnmKfh/YogjNsPebeFGR4m9BJHLzB61XQ3BtpISfS2FugsK9FAtLWX1dCRcrCnUp44CNzuCowUZmxSRgYaE6Za0W2u/E7CVXCiI/UOR8aAm1+OSyE3mOUcwyc1zBBeoX1kiKy0Zfxck1Gsyulti11i83QTBF5Kg3pDQThFMVHiPSlK+0cSedng/VaS8bOZbtsBcTcZAR8JP5KeqQ1OYKAi20njdNNRpgnsU//K+JnaXJaGTomr7aYIphoRn9aeShJWKEq9LcozSF7QleEfDI5LYm5bgVkFkRwVDBCVu0DDIkGupo8TZBq+/pMQURYErJQmPKGKjNDkWOLx7Jd5QizdUweIaKrlP7SwJDhZvONjLkOsBBX9UpGxnydhXkfBLQ8IxgojQbLFnJf81JytSljclYYyEFyx0kVBvKWOFJmONpshGAcsduQY5giVNCV51eOdJYo/pLhbvM0uDHSevNKRcrKZIqnCtJeEsO95RoqcgGK4ocZcho1tTYtcZvH41pNQ7vA0WrhIfOSraIIntIAi+NXWCErdbkvrWwjRLrt0NKUdL6KSOscTOdMSOUtBHwL6OLA0vNSdynaWQEnCpIvKaIrJJEbvHkmuNhn6OjM8VkSGSqn1uYJCGHnq9I3aLhNME3t6GjIkO7xrNFumpyTNX/NrwX7CrIRiqqWijI9JO4d1iieykyfiposQIQ8YjjsjlBh6oHWbwRjgYJQn2NgSnNycmJAk3NiXhx44Sxykihxm8ybUwT1OVKySc7vi3OXVkdBJ4AyXBeksDXG0IhgtYY0lY5ahCD0ehborIk5aUWRJviMA7Xt5kyRjonrXENkm8yYqgs8VzgrJmClK20uMM3jRJ0FiQICQF9hdETlLQWRIb5ki6WDfWRPobvO6a4GP5mcOrNzDFELtTkONLh9dXE8xypEg7z8A9jkhrQ6Fhjlg/QVktJXxt4WXzT/03Q8IaQWSqIuEvloQ2mqC9Jfi7wRul4RX3pSPlzpoVlmCtI2jvKHCFhjcM3sN6lqF6HxnKelLjXWbwrpR4xzuCrTUZx2qq9oAh8p6ixCUGr78g8oyjRAtB5CZFwi80VerVpI0h+IeBxa6Zg6kWvpDHaioYYuEsRbDC3eOmC2JvGYLeioxGknL2UATNJN6hmtj1DlpLvDVmocYbrGCVJKOrg4X6DgddLA203BKMFngdJJFtFd7vJLm6KEpc5yjQrkk7M80SGe34X24nSex1Ra5Omgb71JKyg8SrU3i/kARKwWpH0kOGhKkObyfd0ZGjvyXlAkVZ4xRbYJ2irFMkFY1SwyWxr2oo4zlNiV+7zmaweFpT4kR3kaDAFW6xpSqzJay05FtYR4HmZhc9UxKbbfF2V8RG1MBmSaE+kmC6JnaRXK9gsiXhJHl/U0qM0WTcbyhwkYIvFGwjSbjfwhiJt8ZSQU+Bd5+marPMOkVkD0muxYLIfEuhh60x/J92itguihJSEMySVPQnTewnEm+620rTQEMsOfo4/kP/0ARvWjitlpSX7GxBgcMEsd3EEeYWvdytd+Saawi6aCIj1CkGb6Aj9rwhx16Cf3vAwFy5pyLhVonXzy51FDpdEblbkdJbUcEPDEFzQ8qNmhzzLTmmKWKbFCXeEuRabp6rxbvAtLF442QjQ+wEA9eL1xSR7Q0JXzlSHjJ4exq89yR0laScJ/FW6z4a73pFMEfDiRZvuvijIt86RaSFOl01riV2mD1UEvxGk/Geg5aWwGki1zgKPG9J2U8PEg8qYvMsZeytiTRXBMslCU8JSlxi8EabjwUldlDNLfzTUmCgxWsjqWCOHavYAqsknKFIO0yQ61VL5AVFxk6WhEaCAkdJgt9aSkzXlKNX2jEa79waYuc7gq0N3GDJGCBhoiTXUEPsdknCUE1CK0fwsiaylSF2uiDyO4XX3pFhNd7R4itFGc0k/ElBZwWvq+GC6szVeEoS/MZ+qylwpKNKv9Z469UOjqCjwlusicyTxG6VpNxcQ8IncoR4RhLbR+NdpGGmJWOcIzJGUuKPGpQg8rrG21dOMqQssJQ4RxH5jaUqnZuQ0F4Q+cjxLwPtpZbIAk3QTJHQWBE5S1BokoVtDd6lhqr9UpHSUxMcIYl9pojsb8h4SBOsMQcqvOWC2E8EVehqiJ1hrrAEbQxeK0NGZ0Gkq+guSRgniM23bIHVkqwx4hiHd7smaOyglyIyQuM978j4VS08J/A2G1KeMBRo4fBaSNhKUEZfQewVQ/C1I+MgfbEleEzCUw7mKXI0M3hd1EESVji8x5uQ41nxs1q4RMJCCXs7Iq9acpxn22oSDnQ/sJTxsCbHIYZiLyhY05TY0ZLIOQrGaSJDDN4t8pVaIrsqqFdEegtizc1iTew5Q4ayBDMUsQMkXocaYkc0hZua412siZ1rSXlR460zRJ5SlHGe5j801RLMlJTxtaOM3Q1pvxJ45zUlWFD7rsAbpfEm1JHxG0eh8w2R7QQVzBUw28FhFp5QZzq8t2rx2joqulYTWSuJdTYfWwqMFMcovFmSyJPNyLhE4E10pHzYjOC3huArRa571ZsGajQpQx38SBP5pyZB6lMU3khDnp0MBV51BE9o2E+TY5Ml2E8S7C0o6w1xvCZjf0HkVEHCzFoyNmqC+9wdcqN+Tp7jSDheE9ws8Y5V0NJCn2bk2tqSY4okdrEhx1iDN8cSudwepWmAGXKcJXK65H9to8jYQRH7SBF01ESUJdd0TayVInaWhLkOjlXE5irKGOnI6GSWGCJa482zBI9rCr0jyTVcEuzriC1vcr6mwFGSiqy5zMwxBH/TJHwjSPhL8+01kaaSUuMFKTcLEvaUePcrSmwn8DZrgikWb7CGPxkSjhQwrRk57tctmxLsb9sZvL9LSlyuSLlWkqOjwduo8b6Uv1DkmudIeFF2dHCgxVtk8dpIvHpBxhEOdhKk7OLIUSdJ+cSRY57B+0DgGUUlNfpthTfGkauzxrvTsUUaCVhlKeteTXCoJDCa2NOKhOmC4G1H8JBd4OBZReSRGkqcb/CO1PyLJTLB4j1q8JYaIutEjSLX8YKM+a6phdMsdLFUoV5RTm9JSkuDN8WcIon0NZMNZWh1q8C7SJEwV5HxrmnnTrf3KoJBlmCYI2ilSLlfEvlE4011NNgjgthzEua0oKK7JLE7HZHlEl60BLMVFewg4EWNt0ThrVNEVkkiTwpKXSWJzdRENgvKGq4IhjsiezgSFtsfCUq8qki5S1LRQeYQQ4nemmCkImWMw3tFUoUBZk4NOeZYEp4XRKTGa6wJjrWNHBVJR4m3FCnbuD6aak2WsMTh3SZImGCIPKNgsDpVwnsa70K31lCFJZYcwwSMFcQulGTsZuEaSdBXkPGZhu0FsdUO73RHjq8MPGGIfaGIbVTk6iuI3GFgucHrIQkmWSJdBd7BBu+uOryWAhY7+Lki9rK5wtEQzWwvtbqGhIMFwWRJsElsY4m9IIg9L6lCX0VklaPAYkfkZEGDnOWowlBJjtMUkcGK4Lg6EtoZInMUBVYLgn0UsdmCyCz7gIGHFfk+k1QwTh5We7A9x+IdJ6CvIkEagms0hR50eH9UnTQJ+2oiKyVlLFUE+8gBGu8MQ3CppUHesnjTHN4QB/UGPhCTHLFPHMFrCqa73gqObUJGa03wgbhHkrCfpEpzNLE7JDS25FMKhlhKKWKfCgqstLCPu1zBXy0J2ztwjtixBu8UTRn9LVtkmCN2iyFhtME70JHRQ1KVZXqKI/KNIKYMCYs1GUMEKbM1bKOI9LDXC7zbHS+bt+1MTWS9odA9DtrYtpbImQJ2VHh/lisEwaHqUk1kjKTAKknkBEXkbkdMGwq0dnhzLJF3NJH3JVwrqOB4Sca2hti75nmJN0WzxS6UxDYoEpxpa4htVlRjkYE7DZGzJVU72uC9IyhQL4i8YfGWSYLLNcHXloyz7QhNifmKSE9JgfGmuyLhc403Xm9vqcp6gXe3xuuv8F6VJNxkyTHEkHG2g0aKXL0MsXc1bGfgas2//dCONXiNLCX+5mB7eZIl1kHh7ajwpikyzlUUWOVOsjSQlsS+M0R+pPje/dzBXRZGO0rMtgQrLLG9VSu9n6CMXS3BhwYmSoIBhsjNBmZbgusE9BCPCP5triU4VhNbJfE+swSP27aayE8tuTpYYjtrYjMVGZdp2NpS1s6aBnKSHDsbKuplKbHM4a0wMFd/5/DmGyKrJSUaW4IBrqUhx0vyfzTBBLPIUcnZdrAkNsKR0sWRspumSns6Ch0v/qqIbBYUWKvPU/CFoyrDJGwSNFhbA/MlzKqjrO80hRbpKx0Jewsi/STftwGSlKc1JZyAzx05dhLEdnfQvhZOqiHWWEAHC7+30FuRcZUgaO5gpaIK+xsiHRUsqaPElTV40xQZQ107Q9BZE1nryDVGU9ZSQ47bmhBpLcYpUt7S+xuK/FiT8qKjwXYw5ypS2iuCv7q1gtgjhuBuB8LCFY5cUuCNtsQOFcT+4Ih9JX+k8Ea6v0iCIRZOtCT0Et00JW5UeC85Cg0ScK0k411HcG1zKtre3SeITBRk7WfwDhEvaYLTHP9le0m8By0JDwn4TlLW/aJOvGHxdjYUes+ScZigCkYQdNdEOhkiezgShqkx8ueKjI8lDfK2oNiOFvrZH1hS+tk7NV7nOmLHicGWEgubkXKdwdtZknCLJXaCpkrjZBtLZFsDP9CdxWsSr05Sxl6CMmoFbCOgryX40uDtamB7SVmXW4Ihlgpmq+00tBKUUa83WbjLUNkzDmY7cow1JDygyPGlhgGKYKz4vcV7QBNbJIgM11TUqZaMdwTeSguH6rOaw1JRKzaaGyxVm2EJ/uCIrVWUcZUkcp2grMsEjK+DMwS59jQk3Kd6SEq1d0S6uVmO4Bc1lDXTUcHjluCXEq+1OlBDj1pi9zgiXxnKuE0SqTXwhqbETW6RggMEnGl/q49UT2iCzgJvRwVXS2K/d6+ZkyUl7jawSVLit46EwxVljDZwoSQ20sDBihztHfk2yA8NVZghiXwrYHQdfKAOtzsayjhY9bY0yE2CWEeJ9xfzO423xhL5syS2TFJofO2pboHob0nY4GiAgRrvGQEDa/FWSsoaaYl0syRsEt3kWoH3B01shCXhTUWe9w3Bt44SC9QCh3eShQctwbaK2ApLroGCMlZrYqvlY3qYhM0aXpFkPOuoqJ3Dm6fxXrGwVF9gCWZagjPqznfkuMKQ8DPTQRO8ZqG1hPGKEm9IgpGW4DZDgTNriTxvFiq+Lz+0cKfp4wj6OCK9JSnzNSn9LFU7UhKZZMnYwcJ8s8yRsECScK4j5UOB95HFO0CzhY4xJxuCix0lDlEUeMdS6EZBkTsUkZ4K74dugyTXS7aNgL8aqjDfkCE0ZbwkCXpaWCKhl8P7VD5jxykivSyxyZrYERbe168LYu9ZYh86IkscgVLE7tWPKmJv11CgoyJltMEbrohtVAQfO4ImltiHEroYEs7RxAarVpY8AwXMcMReFOTYWe5iiLRQxJ5Q8DtJ8LQhWOhIeFESPGsILhbNDRljNbHzNRlTFbk2S3L0NOS6V1KFJYKUbSTcIIhM0wQ/s2TM0SRMNcQmSap3jCH4yhJZKSkwyRHpYYgsFeQ4U7xoCB7VVOExhXepo9ABBsYbvGWKXPME3lyH95YioZ0gssQRWWbI+FaSMkXijZXwgiTlYdPdkNLaETxlyDVIwqeaEus0aTcYcg0RVOkpR3CSJqIddK+90JCxzsDVloyrFd5ZAr4TBKfaWa6boEA7C7s6EpYaeFPjveooY72mjIccLHJ9HUwVlDhKkmutJDJBwnp1rvulJZggKDRfbXAkvC/4l3ozQOG9a8lxjx0i7nV4jSXc7vhe3OwIxjgSHjdEhhsif9YkPGlus3iLFDnWOFhtCZbJg0UbQcIaR67JjthoCyMEZRwhiXWyxO5QxI6w5NhT4U1WsJvDO60J34fW9hwzwlKij6ZAW9ne4L0s8C6XeBMEkd/LQy1VucBRot6QMlbivaBhoBgjqGiCJNhsqVp/S2SsG6DIONCR0dXhvWbJ+MRRZJkkuEjgDXJjFQW6SSL7GXK8Z2CZg7cVsbWGoKmEpzQ5elpiy8Ryg7dMkLLUEauzeO86CuwlSOlgYLojZWeJ9xM3S1PWfEfKl5ISLQ0MEKR8YOB2QfCxJBjrKPCN4f9MkaSsqoVXJBmP7EpFZ9UQfOoOFwSzBN4MQ8LsGrymlipcJQhmy0GaQjPqCHaXRwuCZwRbqK2Fg9wlClZqYicrIgMdZfxTQ0c7TBIbrChxmuzoKG8XRaSrIhhiyNFJkrC7oIAWMEOQa5aBekPCRknCo4IKPrYkvCDI8aYmY7WFtprgekcJZ3oLIqssCSMtFbQTJKwXYy3BY5oCh2iKPCpJOE+zRdpYgi6O2KmOAgvVCYaU4ySRek1sgyFhJ403QFHiVEmJHwtybO1gs8Hr5+BETQX3War0qZngYGgtVZtoqd6vFSk/UwdZElYqyjrF4HXUeFspIi9IGKf4j92pKGAdCYMVsbcV3kRF0N+R8LUd5PCsIGWoxDtBkCI0nKofdJQxT+LtZflvuc8Q3CjwWkq8KwUpHzkK/NmSsclCL0nseQdj5FRH5CNHSgtLiW80Of5HU9Hhlsga9bnBq3fEVltKfO5IaSTmGjjc4J0otcP7QsJUSQM8pEj5/wCuUuC2DWz8AAAAAElFTkSuQmCC");
          }
          
        • base16-dark.css
          /*
          
              Name:       Base16 Default Dark
              Author:     Chris Kempson (http://chriskempson.com)
          
              CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools)
              Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
          
          */
          
          .cm-s-base16-dark.CodeMirror {background: #151515; color: #e0e0e0;}
          .cm-s-base16-dark div.CodeMirror-selected {background: #303030 !important;}
          .cm-s-base16-dark.CodeMirror ::selection { background: rgba(48, 48, 48, .99); }
          .cm-s-base16-dark.CodeMirror ::-moz-selection { background: rgba(48, 48, 48, .99); }
          .cm-s-base16-dark .CodeMirror-gutters {background: #151515; border-right: 0px;}
          .cm-s-base16-dark .CodeMirror-guttermarker { color: #ac4142; }
          .cm-s-base16-dark .CodeMirror-guttermarker-subtle { color: #505050; }
          .cm-s-base16-dark .CodeMirror-linenumber {color: #505050;}
          .cm-s-base16-dark .CodeMirror-cursor {border-left: 1px solid #b0b0b0 !important;}
          
          .cm-s-base16-dark span.cm-comment {color: #8f5536;}
          .cm-s-base16-dark span.cm-atom {color: #aa759f;}
          .cm-s-base16-dark span.cm-number {color: #aa759f;}
          
          .cm-s-base16-dark span.cm-property, .cm-s-base16-dark span.cm-attribute {color: #90a959;}
          .cm-s-base16-dark span.cm-keyword {color: #ac4142;}
          .cm-s-base16-dark span.cm-string {color: #f4bf75;}
          
          .cm-s-base16-dark span.cm-variable {color: #90a959;}
          .cm-s-base16-dark span.cm-variable-2 {color: #6a9fb5;}
          .cm-s-base16-dark span.cm-def {color: #d28445;}
          .cm-s-base16-dark span.cm-bracket {color: #e0e0e0;}
          .cm-s-base16-dark span.cm-tag {color: #ac4142;}
          .cm-s-base16-dark span.cm-link {color: #aa759f;}
          .cm-s-base16-dark span.cm-error {background: #ac4142; color: #b0b0b0;}
          
          .cm-s-base16-dark .CodeMirror-activeline-background {background: #202020 !important;}
          .cm-s-base16-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • base16-light.css
          /*
          
              Name:       Base16 Default Light
              Author:     Chris Kempson (http://chriskempson.com)
          
              CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools)
              Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
          
          */
          
          .cm-s-base16-light.CodeMirror {background: #f5f5f5; color: #202020;}
          .cm-s-base16-light div.CodeMirror-selected {background: #e0e0e0 !important;}
          .cm-s-base16-light.CodeMirror ::selection { background: #e0e0e0; }
          .cm-s-base16-light.CodeMirror ::-moz-selection { background: #e0e0e0; }
          .cm-s-base16-light .CodeMirror-gutters {background: #f5f5f5; border-right: 0px;}
          .cm-s-base16-light .CodeMirror-guttermarker { color: #ac4142; }
          .cm-s-base16-light .CodeMirror-guttermarker-subtle { color: #b0b0b0; }
          .cm-s-base16-light .CodeMirror-linenumber {color: #b0b0b0;}
          .cm-s-base16-light .CodeMirror-cursor {border-left: 1px solid #505050 !important;}
          
          .cm-s-base16-light span.cm-comment {color: #8f5536;}
          .cm-s-base16-light span.cm-atom {color: #aa759f;}
          .cm-s-base16-light span.cm-number {color: #aa759f;}
          
          .cm-s-base16-light span.cm-property, .cm-s-base16-light span.cm-attribute {color: #90a959;}
          .cm-s-base16-light span.cm-keyword {color: #ac4142;}
          .cm-s-base16-light span.cm-string {color: #f4bf75;}
          
          .cm-s-base16-light span.cm-variable {color: #90a959;}
          .cm-s-base16-light span.cm-variable-2 {color: #6a9fb5;}
          .cm-s-base16-light span.cm-def {color: #d28445;}
          .cm-s-base16-light span.cm-bracket {color: #202020;}
          .cm-s-base16-light span.cm-tag {color: #ac4142;}
          .cm-s-base16-light span.cm-link {color: #aa759f;}
          .cm-s-base16-light span.cm-error {background: #ac4142; color: #505050;}
          
          .cm-s-base16-light .CodeMirror-activeline-background {background: #DDDCDC !important;}
          .cm-s-base16-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • blackboard.css
          /* Port of TextMate's Blackboard theme */
          
          .cm-s-blackboard.CodeMirror { background: #0C1021; color: #F8F8F8; }
          .cm-s-blackboard .CodeMirror-selected { background: #253B76 !important; }
          .cm-s-blackboard.CodeMirror ::selection { background: rgba(37, 59, 118, .99); }
          .cm-s-blackboard.CodeMirror ::-moz-selection { background: rgba(37, 59, 118, .99); }
          .cm-s-blackboard .CodeMirror-gutters { background: #0C1021; border-right: 0; }
          .cm-s-blackboard .CodeMirror-guttermarker { color: #FBDE2D; }
          .cm-s-blackboard .CodeMirror-guttermarker-subtle { color: #888; }
          .cm-s-blackboard .CodeMirror-linenumber { color: #888; }
          .cm-s-blackboard .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; }
          
          .cm-s-blackboard .cm-keyword { color: #FBDE2D; }
          .cm-s-blackboard .cm-atom { color: #D8FA3C; }
          .cm-s-blackboard .cm-number { color: #D8FA3C; }
          .cm-s-blackboard .cm-def { color: #8DA6CE; }
          .cm-s-blackboard .cm-variable { color: #FF6400; }
          .cm-s-blackboard .cm-operator { color: #FBDE2D;}
          .cm-s-blackboard .cm-comment { color: #AEAEAE; }
          .cm-s-blackboard .cm-string { color: #61CE3C; }
          .cm-s-blackboard .cm-string-2 { color: #61CE3C; }
          .cm-s-blackboard .cm-meta { color: #D8FA3C; }
          .cm-s-blackboard .cm-builtin { color: #8DA6CE; }
          .cm-s-blackboard .cm-tag { color: #8DA6CE; }
          .cm-s-blackboard .cm-attribute { color: #8DA6CE; }
          .cm-s-blackboard .cm-header { color: #FF6400; }
          .cm-s-blackboard .cm-hr { color: #AEAEAE; }
          .cm-s-blackboard .cm-link { color: #8DA6CE; }
          .cm-s-blackboard .cm-error { background: #9D1E15; color: #F8F8F8; }
          
          .cm-s-blackboard .CodeMirror-activeline-background {background: #3C3636 !important;}
          .cm-s-blackboard .CodeMirror-matchingbracket {outline:1px solid grey;color:white !important}
        • cobalt.css
          .cm-s-cobalt.CodeMirror { background: #002240; color: white; }
          .cm-s-cobalt div.CodeMirror-selected { background: #b36539 !important; }
          .cm-s-cobalt.CodeMirror ::selection { background: rgba(179, 101, 57, .99); }
          .cm-s-cobalt.CodeMirror ::-moz-selection { background: rgba(179, 101, 57, .99); }
          .cm-s-cobalt .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }
          .cm-s-cobalt .CodeMirror-guttermarker { color: #ffee80; }
          .cm-s-cobalt .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
          .cm-s-cobalt .CodeMirror-linenumber { color: #d0d0d0; }
          .cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-cobalt span.cm-comment { color: #08f; }
          .cm-s-cobalt span.cm-atom { color: #845dc4; }
          .cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; }
          .cm-s-cobalt span.cm-keyword { color: #ffee80; }
          .cm-s-cobalt span.cm-string { color: #3ad900; }
          .cm-s-cobalt span.cm-meta { color: #ff9d00; }
          .cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; }
          .cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; }
          .cm-s-cobalt span.cm-bracket { color: #d8d8d8; }
          .cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; }
          .cm-s-cobalt span.cm-link { color: #845dc4; }
          .cm-s-cobalt span.cm-error { color: #9d1e15; }
          
          .cm-s-cobalt .CodeMirror-activeline-background {background: #002D57 !important;}
          .cm-s-cobalt .CodeMirror-matchingbracket {outline:1px solid grey;color:white !important}
          
        • colorforth.css
          .cm-s-colorforth.CodeMirror { background: #000000; color: #f8f8f8; }
          .cm-s-colorforth .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; }
          .cm-s-colorforth .CodeMirror-guttermarker { color: #FFBD40; }
          .cm-s-colorforth .CodeMirror-guttermarker-subtle { color: #78846f; }
          .cm-s-colorforth .CodeMirror-linenumber { color: #bababa; }
          .cm-s-colorforth .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-colorforth span.cm-comment     { color: #ededed; }
          .cm-s-colorforth span.cm-def         { color: #ff1c1c; font-weight:bold; }
          .cm-s-colorforth span.cm-keyword     { color: #ffd900; }
          .cm-s-colorforth span.cm-builtin     { color: #00d95a; }
          .cm-s-colorforth span.cm-variable    { color: #73ff00; }
          .cm-s-colorforth span.cm-string      { color: #007bff; }
          .cm-s-colorforth span.cm-number      { color: #00c4ff; }
          .cm-s-colorforth span.cm-atom        { color: #606060; }
          
          .cm-s-colorforth span.cm-variable-2  { color: #EEE; }
          .cm-s-colorforth span.cm-variable-3  { color: #DDD; }
          .cm-s-colorforth span.cm-property    {}
          .cm-s-colorforth span.cm-operator    {}
          
          .cm-s-colorforth span.cm-meta        { color: yellow; }
          .cm-s-colorforth span.cm-qualifier   { color: #FFF700; }
          .cm-s-colorforth span.cm-bracket     { color: #cc7; }
          .cm-s-colorforth span.cm-tag         { color: #FFBD40; }
          .cm-s-colorforth span.cm-attribute   { color: #FFF700; }
          .cm-s-colorforth span.cm-error       { color: #f00; }
          
          .cm-s-colorforth .CodeMirror-selected { background: #333d53 !important; }
          
          .cm-s-colorforth span.cm-compilation { background: rgba(255, 255, 255, 0.12); }
          
          .cm-s-colorforth .CodeMirror-activeline-background {background: #253540 !important;}
          
        • eclipse.css
          .cm-s-eclipse span.cm-meta {color: #FF1717;}
          .cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; }
          .cm-s-eclipse span.cm-atom {color: #219;}
          .cm-s-eclipse span.cm-number {color: #164;}
          .cm-s-eclipse span.cm-def {color: #00f;}
          .cm-s-eclipse span.cm-variable {color: black;}
          .cm-s-eclipse span.cm-variable-2 {color: #0000C0;}
          .cm-s-eclipse span.cm-variable-3 {color: #0000C0;}
          .cm-s-eclipse span.cm-property {color: black;}
          .cm-s-eclipse span.cm-operator {color: black;}
          .cm-s-eclipse span.cm-comment {color: #3F7F5F;}
          .cm-s-eclipse span.cm-string {color: #2A00FF;}
          .cm-s-eclipse span.cm-string-2 {color: #f50;}
          .cm-s-eclipse span.cm-qualifier {color: #555;}
          .cm-s-eclipse span.cm-builtin {color: #30a;}
          .cm-s-eclipse span.cm-bracket {color: #cc7;}
          .cm-s-eclipse span.cm-tag {color: #170;}
          .cm-s-eclipse span.cm-attribute {color: #00c;}
          .cm-s-eclipse span.cm-link {color: #219;}
          .cm-s-eclipse span.cm-error {color: #f00;}
          
          .cm-s-eclipse .CodeMirror-activeline-background {background: #e8f2ff !important;}
          .cm-s-eclipse .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;}
          
        • elegant.css
          .cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom {color: #762;}
          .cm-s-elegant span.cm-comment {color: #262; font-style: italic; line-height: 1em;}
          .cm-s-elegant span.cm-meta {color: #555; font-style: italic; line-height: 1em;}
          .cm-s-elegant span.cm-variable {color: black;}
          .cm-s-elegant span.cm-variable-2 {color: #b11;}
          .cm-s-elegant span.cm-qualifier {color: #555;}
          .cm-s-elegant span.cm-keyword {color: #730;}
          .cm-s-elegant span.cm-builtin {color: #30a;}
          .cm-s-elegant span.cm-link {color: #762;}
          .cm-s-elegant span.cm-error {background-color: #fdd;}
          
          .cm-s-elegant .CodeMirror-activeline-background {background: #e8f2ff !important;}
          .cm-s-elegant .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;}
          
        • erlang-dark.css
          .cm-s-erlang-dark.CodeMirror { background: #002240; color: white; }
          .cm-s-erlang-dark div.CodeMirror-selected { background: #b36539 !important; }
          .cm-s-erlang-dark.CodeMirror ::selection { background: rgba(179, 101, 57, .99); }
          .cm-s-erlang-dark.CodeMirror ::-moz-selection { background: rgba(179, 101, 57, .99); }
          .cm-s-erlang-dark .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }
          .cm-s-erlang-dark .CodeMirror-guttermarker { color: white; }
          .cm-s-erlang-dark .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
          .cm-s-erlang-dark .CodeMirror-linenumber { color: #d0d0d0; }
          .cm-s-erlang-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-erlang-dark span.cm-atom       { color: #f133f1; }
          .cm-s-erlang-dark span.cm-attribute  { color: #ff80e1; }
          .cm-s-erlang-dark span.cm-bracket    { color: #ff9d00; }
          .cm-s-erlang-dark span.cm-builtin    { color: #eaa; }
          .cm-s-erlang-dark span.cm-comment    { color: #77f; }
          .cm-s-erlang-dark span.cm-def        { color: #e7a; }
          .cm-s-erlang-dark span.cm-keyword    { color: #ffee80; }
          .cm-s-erlang-dark span.cm-meta       { color: #50fefe; }
          .cm-s-erlang-dark span.cm-number     { color: #ffd0d0; }
          .cm-s-erlang-dark span.cm-operator   { color: #d55; }
          .cm-s-erlang-dark span.cm-property   { color: #ccc; }
          .cm-s-erlang-dark span.cm-qualifier  { color: #ccc; }
          .cm-s-erlang-dark span.cm-quote      { color: #ccc; }
          .cm-s-erlang-dark span.cm-special    { color: #ffbbbb; }
          .cm-s-erlang-dark span.cm-string     { color: #3ad900; }
          .cm-s-erlang-dark span.cm-string-2   { color: #ccc; }
          .cm-s-erlang-dark span.cm-tag        { color: #9effff; }
          .cm-s-erlang-dark span.cm-variable   { color: #50fe50; }
          .cm-s-erlang-dark span.cm-variable-2 { color: #e0e; }
          .cm-s-erlang-dark span.cm-variable-3 { color: #ccc; }
          .cm-s-erlang-dark span.cm-error      { color: #9d1e15; }
          
          .cm-s-erlang-dark .CodeMirror-activeline-background {background: #013461 !important;}
          .cm-s-erlang-dark .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;}
          
        • lesser-dark.css
          /*
          http://lesscss.org/ dark theme
          Ported to CodeMirror by Peter Kroon
          */
          .cm-s-lesser-dark {
            line-height: 1.3em;
          }
          .cm-s-lesser-dark.CodeMirror { background: #262626; color: #EBEFE7; text-shadow: 0 -1px 1px #262626; }
          .cm-s-lesser-dark div.CodeMirror-selected {background: #45443B !important;} /* 33322B*/
          .cm-s-lesser-dark.CodeMirror ::selection { background: rgba(69, 68, 59, .99); }
          .cm-s-lesser-dark.CodeMirror ::-moz-selection { background: rgba(69, 68, 59, .99); }
          .cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
          .cm-s-lesser-dark pre { padding: 0 8px; }/*editable code holder*/
          
          .cm-s-lesser-dark.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/
          
          .cm-s-lesser-dark .CodeMirror-gutters { background: #262626; border-right:1px solid #aaa; }
          .cm-s-lesser-dark .CodeMirror-guttermarker { color: #599eff; }
          .cm-s-lesser-dark .CodeMirror-guttermarker-subtle { color: #777; }
          .cm-s-lesser-dark .CodeMirror-linenumber { color: #777; }
          
          .cm-s-lesser-dark span.cm-keyword { color: #599eff; }
          .cm-s-lesser-dark span.cm-atom { color: #C2B470; }
          .cm-s-lesser-dark span.cm-number { color: #B35E4D; }
          .cm-s-lesser-dark span.cm-def {color: white;}
          .cm-s-lesser-dark span.cm-variable { color:#D9BF8C; }
          .cm-s-lesser-dark span.cm-variable-2 { color: #669199; }
          .cm-s-lesser-dark span.cm-variable-3 { color: white; }
          .cm-s-lesser-dark span.cm-property {color: #92A75C;}
          .cm-s-lesser-dark span.cm-operator {color: #92A75C;}
          .cm-s-lesser-dark span.cm-comment { color: #666; }
          .cm-s-lesser-dark span.cm-string { color: #BCD279; }
          .cm-s-lesser-dark span.cm-string-2 {color: #f50;}
          .cm-s-lesser-dark span.cm-meta { color: #738C73; }
          .cm-s-lesser-dark span.cm-qualifier {color: #555;}
          .cm-s-lesser-dark span.cm-builtin { color: #ff9e59; }
          .cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; }
          .cm-s-lesser-dark span.cm-tag { color: #669199; }
          .cm-s-lesser-dark span.cm-attribute {color: #00c;}
          .cm-s-lesser-dark span.cm-header {color: #a0a;}
          .cm-s-lesser-dark span.cm-quote {color: #090;}
          .cm-s-lesser-dark span.cm-hr {color: #999;}
          .cm-s-lesser-dark span.cm-link {color: #00c;}
          .cm-s-lesser-dark span.cm-error { color: #9d1e15; }
          
          .cm-s-lesser-dark .CodeMirror-activeline-background {background: #3C3A3A !important;}
          .cm-s-lesser-dark .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;}
          
        • liquibyte.css
          .cm-s-liquibyte.CodeMirror {
          	background-color: #000;
          	color: #fff;
          	line-height: 1.2em;
          	font-size: 1em;
          }
          .CodeMirror-focused .cm-matchhighlight {
          	text-decoration: underline;
          	text-decoration-color: #0f0;
          	text-decoration-style: wavy;
          }
          .cm-trailingspace {
          	text-decoration: line-through;
          	text-decoration-color: #f00;
          	text-decoration-style: dotted;
          }
          .cm-tab {
          	text-decoration: line-through;
          	text-decoration-color: #404040;
          	text-decoration-style: dotted;
          }
          .cm-s-liquibyte .CodeMirror-gutters { background-color: #262626; border-right: 1px solid #505050; padding-right: 0.8em; }
          .cm-s-liquibyte .CodeMirror-gutter-elt div{ font-size: 1.2em; }
          .cm-s-liquibyte .CodeMirror-guttermarker {  }
          .cm-s-liquibyte .CodeMirror-guttermarker-subtle {  }
          .cm-s-liquibyte .CodeMirror-linenumber { color: #606060; padding-left: 0;}
          .cm-s-liquibyte .CodeMirror-cursor { border-left: 1px solid #eee !important; }
          
          .cm-s-liquibyte span.cm-comment     { color: #008000; }
          .cm-s-liquibyte span.cm-def         { color: #ffaf40; font-weight: bold; }
          .cm-s-liquibyte span.cm-keyword     { color: #c080ff; font-weight: bold; }
          .cm-s-liquibyte span.cm-builtin     { color: #ffaf40; font-weight: bold; }
          .cm-s-liquibyte span.cm-variable    { color: #5967ff; font-weight: bold; }
          .cm-s-liquibyte span.cm-string      { color: #ff8000; }
          .cm-s-liquibyte span.cm-number      { color: #0f0; font-weight: bold; }
          .cm-s-liquibyte span.cm-atom        { color: #bf3030; font-weight: bold; }
          
          .cm-s-liquibyte span.cm-variable-2  { color: #007f7f; font-weight: bold; }
          .cm-s-liquibyte span.cm-variable-3  { color: #c080ff; font-weight: bold; }
          .cm-s-liquibyte span.cm-property    { color: #999; font-weight: bold; }
          .cm-s-liquibyte span.cm-operator    { color: #fff; }
          
          .cm-s-liquibyte span.cm-meta        { color: #0f0; }
          .cm-s-liquibyte span.cm-qualifier   { color: #fff700; font-weight: bold; }
          .cm-s-liquibyte span.cm-bracket     { color: #cc7; }
          .cm-s-liquibyte span.cm-tag         { color: #ff0; font-weight: bold; }
          .cm-s-liquibyte span.cm-attribute   { color: #c080ff; font-weight: bold; }
          .cm-s-liquibyte span.cm-error       { color: #f00; }
          
          .cm-s-liquibyte .CodeMirror-selected { background-color: rgba(255, 0, 0, 0.25) !important; }
          
          .cm-s-liquibyte span.cm-compilation { background-color: rgba(255, 255, 255, 0.12); }
          
          .cm-s-liquibyte .CodeMirror-activeline-background {background-color: rgba(0, 255, 0, 0.15) !important;}
          
          /* Default styles for common addons */
          div.CodeMirror span.CodeMirror-matchingbracket { color: #0f0; font-weight: bold; }
          div.CodeMirror span.CodeMirror-nonmatchingbracket { color: #f00; font-weight: bold; }
          .CodeMirror-matchingtag { background-color: rgba(150, 255, 0, .3); }
          /* Scrollbars */
          /* Simple */
          div.CodeMirror-simplescroll-horizontal div:hover, div.CodeMirror-simplescroll-vertical div:hover {
          	background-color: rgba(80, 80, 80, .7);
          }
          div.CodeMirror-simplescroll-horizontal div, div.CodeMirror-simplescroll-vertical div {
          	background-color: rgba(80, 80, 80, .3);
          	border: 1px solid #404040;
          	border-radius: 5px;
          }
          div.CodeMirror-simplescroll-vertical div {
          	border-top: 1px solid #404040;
          	border-bottom: 1px solid #404040;
          }
          div.CodeMirror-simplescroll-horizontal div {
          	border-left: 1px solid #404040;
          	border-right: 1px solid #404040;
          }
          div.CodeMirror-simplescroll-vertical {
          	background-color: #262626;
          }
          div.CodeMirror-simplescroll-horizontal {
          	background-color: #262626;
          	border-top: 1px solid #404040;
          }
          /* Overlay */
          div.CodeMirror-overlayscroll-horizontal div, div.CodeMirror-overlayscroll-vertical div {
          	background-color: #404040;
          	border-radius: 5px;
          }
          div.CodeMirror-overlayscroll-vertical div {
          	border: 1px solid #404040;
          }
          div.CodeMirror-overlayscroll-horizontal div {
          	border: 1px solid #404040;
          }
          
        • mbo.css
          /****************************************************************/
          /*   Based on mbonaci's Brackets mbo theme                      */
          /*   https://github.com/mbonaci/global/blob/master/Mbo.tmTheme  */
          /*   Create your own: http://tmtheme-editor.herokuapp.com       */
          /****************************************************************/
          
          .cm-s-mbo.CodeMirror {background: #2c2c2c; color: #ffffec;}
          .cm-s-mbo div.CodeMirror-selected {background: #716C62 !important;}
          .cm-s-mbo.CodeMirror ::selection { background: rgba(113, 108, 98, .99); }
          .cm-s-mbo.CodeMirror ::-moz-selection { background: rgba(113, 108, 98, .99); }
          .cm-s-mbo .CodeMirror-gutters {background: #4e4e4e; border-right: 0px;}
          .cm-s-mbo .CodeMirror-guttermarker { color: white; }
          .cm-s-mbo .CodeMirror-guttermarker-subtle { color: grey; }
          .cm-s-mbo .CodeMirror-linenumber {color: #dadada;}
          .cm-s-mbo .CodeMirror-cursor {border-left: 1px solid #ffffec !important;}
          
          .cm-s-mbo span.cm-comment {color: #95958a;}
          .cm-s-mbo span.cm-atom {color: #00a8c6;}
          .cm-s-mbo span.cm-number {color: #00a8c6;}
          
          .cm-s-mbo span.cm-property, .cm-s-mbo span.cm-attribute {color: #9ddfe9;}
          .cm-s-mbo span.cm-keyword {color: #ffb928;}
          .cm-s-mbo span.cm-string {color: #ffcf6c;}
          .cm-s-mbo span.cm-string.cm-property {color: #ffffec;}
          
          .cm-s-mbo span.cm-variable {color: #ffffec;}
          .cm-s-mbo span.cm-variable-2 {color: #00a8c6;}
          .cm-s-mbo span.cm-def {color: #ffffec;}
          .cm-s-mbo span.cm-bracket {color: #fffffc; font-weight: bold;}
          .cm-s-mbo span.cm-tag {color: #9ddfe9;}
          .cm-s-mbo span.cm-link {color: #f54b07;}
          .cm-s-mbo span.cm-error {border-bottom: #636363; color: #ffffec;}
          .cm-s-mbo span.cm-qualifier {color: #ffffec;}
          
          .cm-s-mbo .CodeMirror-activeline-background {background: #494b41 !important;}
          .cm-s-mbo .CodeMirror-matchingbracket {color: #222 !important;}
          .cm-s-mbo .CodeMirror-matchingtag {background: rgba(255, 255, 255, .37);}
          
        • mdn-like.css
          /*
            MDN-LIKE Theme - Mozilla
            Ported to CodeMirror by Peter Kroon <plakroon@gmail.com>
            Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues
            GitHub: @peterkroon
          
            The mdn-like theme is inspired on the displayed code examples at: https://developer.mozilla.org/en-US/docs/Web/CSS/animation
          
          */
          .cm-s-mdn-like.CodeMirror { color: #999; background-color: #fff; }
          .cm-s-mdn-like .CodeMirror-selected { background: #cfc !important; }
          .cm-s-mdn-like.CodeMirror ::selection { background: #cfc; }
          .cm-s-mdn-like.CodeMirror ::-moz-selection { background: #cfc; }
          
          .cm-s-mdn-like .CodeMirror-gutters { background: #f8f8f8; border-left: 6px solid rgba(0,83,159,0.65); color: #333; }
          .cm-s-mdn-like .CodeMirror-linenumber { color: #aaa; padding-left: 8px; }
          div.cm-s-mdn-like .CodeMirror-cursor { border-left: 2px solid #222; }
          
          .cm-s-mdn-like .cm-keyword {  color: #6262FF; }
          .cm-s-mdn-like .cm-atom { color: #F90; }
          .cm-s-mdn-like .cm-number { color:  #ca7841; }
          .cm-s-mdn-like .cm-def { color: #8DA6CE; }
          .cm-s-mdn-like span.cm-variable-2, .cm-s-mdn-like span.cm-tag { color: #690; }
          .cm-s-mdn-like span.cm-variable-3, .cm-s-mdn-like span.cm-def { color: #07a; }
          
          .cm-s-mdn-like .cm-variable { color: #07a; }
          .cm-s-mdn-like .cm-property { color: #905; }
          .cm-s-mdn-like .cm-qualifier { color: #690; }
          
          .cm-s-mdn-like .cm-operator { color: #cda869; }
          .cm-s-mdn-like .cm-comment { color:#777; font-weight:normal; }
          .cm-s-mdn-like .cm-string { color:#07a; font-style:italic; }
          .cm-s-mdn-like .cm-string-2 { color:#bd6b18; } /*?*/
          .cm-s-mdn-like .cm-meta { color: #000; } /*?*/
          .cm-s-mdn-like .cm-builtin { color: #9B7536; } /*?*/
          .cm-s-mdn-like .cm-tag { color: #997643; }
          .cm-s-mdn-like .cm-attribute { color: #d6bb6d; } /*?*/
          .cm-s-mdn-like .cm-header { color: #FF6400; }
          .cm-s-mdn-like .cm-hr { color: #AEAEAE; }
          .cm-s-mdn-like .cm-link {   color:#ad9361; font-style:italic; text-decoration:none; }
          .cm-s-mdn-like .cm-error { border-bottom: 1px solid red; }
          
          div.cm-s-mdn-like .CodeMirror-activeline-background {background: #efefff;}
          div.cm-s-mdn-like span.CodeMirror-matchingbracket {outline:1px solid grey; color: inherit;}
          
          .cm-s-mdn-like.CodeMirror { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFcAAAAyCAYAAAAp8UeFAAAHvklEQVR42s2b63bcNgyEQZCSHCdt2vd/0tWF7I+Q6XgMXiTtuvU5Pl57ZQKkKHzEAOtF5KeIJBGJ8uvL599FRFREZhFx8DeXv8trn68RuGaC8TRfo3SNp9dlDDHedyLyTUTeRWStXKPZrjtpZxaRw5hPqozRs1N8/enzIiQRWcCgy4MUA0f+XWliDhyL8Lfyvx7ei/Ae3iQFHyw7U/59pQVIMEEPEz0G7XiwdRjzSfC3UTtz9vchIntxvry5iMgfIhJoEflOz2CQr3F5h/HfeFe+GTdLaKcu9L8LTeQb/R/7GgbsfKedyNdoHsN31uRPWrfZ5wsj/NzzRQHuToIdU3ahwnsKPxXCjJITuOsi7XLc7SG/v5GdALs7wf8JjTFiB5+QvTEfRyGOfX3Lrx8wxyQi3sNq46O7QahQiCsRFgqddjBouVEHOKDgXAQHD9gJCr5sMKkEdjwsarG/ww3BMHBU7OBjXnzdyY7SfCxf5/z6ATccrwlKuwC/jhznnPF4CgVzhhVf4xp2EixcBActO75iZ8/fM9zAs2OMzKdslgXWJ9XG8PQoOAMA5fGcsvORgv0doBXyHrCwfLJAOwo71QLNkb8n2Pl6EWiR7OCibtkPaz4Kc/0NNAze2gju3zOwekALDaCFPI5vjPFmgGY5AZqyGEvH1x7QfIb8YtxMnA/b+QQ0aQDAwc6JMFg8CbQZ4qoYEEHbRwNojuK3EHwd7VALSgq+MNDKzfT58T8qdpADrgW0GmgcAS1lhzztJmkAzcPNOQbsWEALBDSlMKUG0Eq4CLAQWvEVQ9WU57gZJwZtgPO3r9oBTQ9WO8TjqXINx8R0EYpiZEUWOF3FxkbJkgU9B2f41YBrIj5ZfsQa0M5kTgiAAqM3ShXLgu8XMqcrQBvJ0CL5pnTsfMB13oB8athpAq2XOQmcGmoACCLydx7nToa23ATaSIY2ichfOdPTGxlasXMLaL0MLZAOwAKIM+y8CmicobGdCcbbK9DzN+yYGVoNNI5iUKTMyYOjPse4A8SM1MmcXgU0toOq1yO/v8FOxlASyc7TgeYaAMBJHcY1CcCwGI/TK4AmDbDyKYBBtFUkRwto8gygiQEaByFgJ00BH2M8JWwQS1nafDXQCidWyOI8AcjDCSjCLk8ngObuAm3JAHAdubAmOaK06V8MNEsKPJOhobSprwQa6gD7DclRQdqcwL4zxqgBrQcabUiBLclRDKAlWp+etPkBaNMA0AKlrHwTdEByZAA4GM+SNluSY6wAzcMNewxmgig5Ks0nkrSpBvSaQHMdKTBAnLojOdYyGpQ254602ZILPdTD1hdlggdIm74jbTp8vDwF5ZYUeLWGJpWsh6XNyXgcYwVoJQTEhhTYkxzZjiU5npU2TaB979TQehlaAVq4kaGpiPwwwLkYUuBbQwocyQTv1tA0+1UFWoJF3iv1oq+qoSk8EQdJmwHkziIF7oOZk14EGitibAdjLYYK78H5vZOhtWpoI0ATGHs0Q8OMb4Ey+2bU2UYztCtA0wFAs7TplGLRVQCcqaFdGSPCeTI1QNIC52iWNzof6Uib7xjEp07mNNoUYmVosVItHrHzRlLgBn9LFyRHaQCtVUMbtTNhoXWiTOO9k/V8BdAc1Oq0ArSQs6/5SU0hckNy9NnXqQY0PGYo5dWJ7nINaN6o958FWin27aBaWRka1r5myvLOAm0j30eBJqCxHLReVclxhxOEN2JfDWjxBtAC7MIH1fVaGdoOp4qJYDgKtKPSFNID2gSnGldrCqkFZ+5UeQXQBIRrSwocbdZYQT/2LwRahBPBXoHrB8nxaGROST62DKUbQOMMzZIC9abkuELfQzQALWTnDNAm8KHWFOJgJ5+SHIvTPcmx1xQyZRhNL5Qci689aXMEaN/uNIWkEwDAvFpOZmgsBaaGnbs1NPa1Jm32gBZAIh1pCtG7TSH4aE0y1uVY4uqoFPisGlpP2rSA5qTecWn5agK6BzSpgAyD+wFaqhnYoSZ1Vwr8CmlTQbrcO3ZaX0NAEyMbYaAlyquFoLKK3SPby9CeVUPThrSJmkCAE0CrKUQadi4DrdSlWhmah0YL9z9vClH59YGbHx1J8VZTyAjQepJjmXwAKTDQI3omc3p1U4gDUf6RfcdYfrUp5ClAi2J3Ba6UOXGo+K+bQrjjssitG2SJzshaLwMtXgRagUNpYYoVkMSBLM+9GGiJZMvduG6DRZ4qc04DMPtQQxOjEtACmhO7K1AbNbQDEggZyJwscFpAGwENhoBeUwh3bWolhe8BTYVKxQEWrSUn/uhcM5KhvUu/+eQu0Lzhi+VrK0PrZZNDQKs9cpYUuFYgMVpD4/NxenJTiMCNqdUEUf1qZWjppLT5qSkkUZbCwkbZMSuVnu80hfSkzRbQeqCZSAh6huR4VtoM2gHAlLf72smuWgE+VV7XpE25Ab2WFDgyhnSuKbs4GuGzCjR+tIoUuMFg3kgcWKLTwRqanJQ2W00hAsenfaApRC42hbCvK1SlE0HtE9BGgneJO+ELamitD1YjjOYnNYVcraGhtKkW0EqVVeDx733I2NH581k1NNxNLG0i0IJ8/NjVaOZ0tYZ2Vtr0Xv7tPV3hkWp9EFkgS/J0vosngTaSoaG06WHi+xObQkaAdlbanP8B2+2l0f90LmUAAAAASUVORK5CYII=); }
          
        • midnight.css
          /* Based on the theme at http://bonsaiden.github.com/JavaScript-Garden */
          
          /*<!--match-->*/
          .cm-s-midnight span.CodeMirror-matchhighlight { background: #494949; }
          .cm-s-midnight.CodeMirror-focused span.CodeMirror-matchhighlight { background: #314D67 !important; }
          
          /*<!--activeline-->*/
          .cm-s-midnight .CodeMirror-activeline-background {background: #253540 !important;}
          
          .cm-s-midnight.CodeMirror {
              background: #0F192A;
              color: #D1EDFF;
          }
          
          .cm-s-midnight.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
          
          .cm-s-midnight div.CodeMirror-selected {background: #314D67 !important;}
          .cm-s-midnight.CodeMirror ::selection { background: rgba(49, 77, 103, .99); }
          .cm-s-midnight.CodeMirror ::-moz-selection { background: rgba(49, 77, 103, .99); }
          .cm-s-midnight .CodeMirror-gutters {background: #0F192A; border-right: 1px solid;}
          .cm-s-midnight .CodeMirror-guttermarker { color: white; }
          .cm-s-midnight .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
          .cm-s-midnight .CodeMirror-linenumber {color: #D0D0D0;}
          .cm-s-midnight .CodeMirror-cursor {
              border-left: 1px solid #F8F8F0 !important;
          }
          
          .cm-s-midnight span.cm-comment {color: #428BDD;}
          .cm-s-midnight span.cm-atom {color: #AE81FF;}
          .cm-s-midnight span.cm-number {color: #D1EDFF;}
          
          .cm-s-midnight span.cm-property, .cm-s-midnight span.cm-attribute {color: #A6E22E;}
          .cm-s-midnight span.cm-keyword {color: #E83737;}
          .cm-s-midnight span.cm-string {color: #1DC116;}
          
          .cm-s-midnight span.cm-variable {color: #FFAA3E;}
          .cm-s-midnight span.cm-variable-2 {color: #FFAA3E;}
          .cm-s-midnight span.cm-def {color: #4DD;}
          .cm-s-midnight span.cm-bracket {color: #D1EDFF;}
          .cm-s-midnight span.cm-tag {color: #449;}
          .cm-s-midnight span.cm-link {color: #AE81FF;}
          .cm-s-midnight span.cm-error {background: #F92672; color: #F8F8F0;}
          
          .cm-s-midnight .CodeMirror-matchingbracket {
            text-decoration: underline;
            color: white !important;
          }
          
        • monokai.css
          /* Based on Sublime Text's Monokai theme */
          
          .cm-s-monokai.CodeMirror {background: #272822; color: #f8f8f2;}
          .cm-s-monokai div.CodeMirror-selected {background: #49483E !important;}
          .cm-s-monokai.CodeMirror ::selection { background: rgba(73, 72, 62, .99); }
          .cm-s-monokai.CodeMirror ::-moz-selection { background: rgba(73, 72, 62, .99); }
          .cm-s-monokai .CodeMirror-gutters {background: #272822; border-right: 0px;}
          .cm-s-monokai .CodeMirror-guttermarker { color: white; }
          .cm-s-monokai .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
          .cm-s-monokai .CodeMirror-linenumber {color: #d0d0d0;}
          .cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;}
          
          .cm-s-monokai span.cm-comment {color: #75715e;}
          .cm-s-monokai span.cm-atom {color: #ae81ff;}
          .cm-s-monokai span.cm-number {color: #ae81ff;}
          
          .cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;}
          .cm-s-monokai span.cm-keyword {color: #f92672;}
          .cm-s-monokai span.cm-string {color: #e6db74;}
          
          .cm-s-monokai span.cm-variable {color: #f8f8f2;}
          .cm-s-monokai span.cm-variable-2 {color: #9effff;}
          .cm-s-monokai span.cm-def {color: #fd971f;}
          .cm-s-monokai span.cm-bracket {color: #f8f8f2;}
          .cm-s-monokai span.cm-tag {color: #f92672;}
          .cm-s-monokai span.cm-link {color: #ae81ff;}
          .cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;}
          
          .cm-s-monokai .CodeMirror-activeline-background {background: #373831 !important;}
          .cm-s-monokai .CodeMirror-matchingbracket {
            text-decoration: underline;
            color: white !important;
          }
          
        • neat.css
          .cm-s-neat span.cm-comment { color: #a86; }
          .cm-s-neat span.cm-keyword { line-height: 1em; font-weight: bold; color: blue; }
          .cm-s-neat span.cm-string { color: #a22; }
          .cm-s-neat span.cm-builtin { line-height: 1em; font-weight: bold; color: #077; }
          .cm-s-neat span.cm-special { line-height: 1em; font-weight: bold; color: #0aa; }
          .cm-s-neat span.cm-variable { color: black; }
          .cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; }
          .cm-s-neat span.cm-meta {color: #555;}
          .cm-s-neat span.cm-link { color: #3a3; }
          
          .cm-s-neat .CodeMirror-activeline-background {background: #e8f2ff !important;}
          .cm-s-neat .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;}
          
        • neo.css
          /* neo theme for codemirror */
          
          /* Color scheme */
          
          .cm-s-neo.CodeMirror {
            background-color:#ffffff;
            color:#2e383c;
            line-height:1.4375;
          }
          .cm-s-neo .cm-comment {color:#75787b}
          .cm-s-neo .cm-keyword, .cm-s-neo .cm-property {color:#1d75b3}
          .cm-s-neo .cm-atom,.cm-s-neo .cm-number {color:#75438a}
          .cm-s-neo .cm-node,.cm-s-neo .cm-tag {color:#9c3328}
          .cm-s-neo .cm-string {color:#b35e14}
          .cm-s-neo .cm-variable,.cm-s-neo .cm-qualifier {color:#047d65}
          
          
          /* Editor styling */
          
          .cm-s-neo pre {
            padding:0;
          }
          
          .cm-s-neo .CodeMirror-gutters {
            border:none;
            border-right:10px solid transparent;
            background-color:transparent;
          }
          
          .cm-s-neo .CodeMirror-linenumber {
            padding:0;
            color:#e0e2e5;
          }
          
          .cm-s-neo .CodeMirror-guttermarker { color: #1d75b3; }
          .cm-s-neo .CodeMirror-guttermarker-subtle { color: #e0e2e5; }
          
          .cm-s-neo div.CodeMirror-cursor {
            width: auto;
            border: 0;
            background: rgba(155,157,162,0.37);
            z-index: 1;
          }
          
        • night.css
          /* Loosely based on the Midnight Textmate theme */
          
          .cm-s-night.CodeMirror { background: #0a001f; color: #f8f8f8; }
          .cm-s-night div.CodeMirror-selected { background: #447 !important; }
          .cm-s-night.CodeMirror ::selection { background: rgba(68, 68, 119, .99); }
          .cm-s-night.CodeMirror ::-moz-selection { background: rgba(68, 68, 119, .99); }
          .cm-s-night .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; }
          .cm-s-night .CodeMirror-guttermarker { color: white; }
          .cm-s-night .CodeMirror-guttermarker-subtle { color: #bbb; }
          .cm-s-night .CodeMirror-linenumber { color: #f8f8f8; }
          .cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-night span.cm-comment { color: #6900a1; }
          .cm-s-night span.cm-atom { color: #845dc4; }
          .cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; }
          .cm-s-night span.cm-keyword { color: #599eff; }
          .cm-s-night span.cm-string { color: #37f14a; }
          .cm-s-night span.cm-meta { color: #7678e2; }
          .cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; }
          .cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; }
          .cm-s-night span.cm-bracket { color: #8da6ce; }
          .cm-s-night span.cm-comment { color: #6900a1; }
          .cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; }
          .cm-s-night span.cm-link { color: #845dc4; }
          .cm-s-night span.cm-error { color: #9d1e15; }
          
          .cm-s-night .CodeMirror-activeline-background {background: #1C005A !important;}
          .cm-s-night .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;}
          
        • paraiso-dark.css
          /*
          
              Name:       Paraíso (Dark)
              Author:     Jan T. Sott
          
              Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror)
              Inspired by the art of Rubens LP (http://www.rubenslp.com.br)
          
          */
          
          .cm-s-paraiso-dark.CodeMirror {background: #2f1e2e; color: #b9b6b0;}
          .cm-s-paraiso-dark div.CodeMirror-selected {background: #41323f !important;}
          .cm-s-paraiso-dark.CodeMirror ::selection { background: rgba(65, 50, 63, .99); }
          .cm-s-paraiso-dark.CodeMirror ::-moz-selection { background: rgba(65, 50, 63, .99); }
          .cm-s-paraiso-dark .CodeMirror-gutters {background: #2f1e2e; border-right: 0px;}
          .cm-s-paraiso-dark .CodeMirror-guttermarker { color: #ef6155; }
          .cm-s-paraiso-dark .CodeMirror-guttermarker-subtle { color: #776e71; }
          .cm-s-paraiso-dark .CodeMirror-linenumber {color: #776e71;}
          .cm-s-paraiso-dark .CodeMirror-cursor {border-left: 1px solid #8d8687 !important;}
          
          .cm-s-paraiso-dark span.cm-comment {color: #e96ba8;}
          .cm-s-paraiso-dark span.cm-atom {color: #815ba4;}
          .cm-s-paraiso-dark span.cm-number {color: #815ba4;}
          
          .cm-s-paraiso-dark span.cm-property, .cm-s-paraiso-dark span.cm-attribute {color: #48b685;}
          .cm-s-paraiso-dark span.cm-keyword {color: #ef6155;}
          .cm-s-paraiso-dark span.cm-string {color: #fec418;}
          
          .cm-s-paraiso-dark span.cm-variable {color: #48b685;}
          .cm-s-paraiso-dark span.cm-variable-2 {color: #06b6ef;}
          .cm-s-paraiso-dark span.cm-def {color: #f99b15;}
          .cm-s-paraiso-dark span.cm-bracket {color: #b9b6b0;}
          .cm-s-paraiso-dark span.cm-tag {color: #ef6155;}
          .cm-s-paraiso-dark span.cm-link {color: #815ba4;}
          .cm-s-paraiso-dark span.cm-error {background: #ef6155; color: #8d8687;}
          
          .cm-s-paraiso-dark .CodeMirror-activeline-background {background: #4D344A !important;}
          .cm-s-paraiso-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • paraiso-light.css
          /*
          
              Name:       Paraíso (Light)
              Author:     Jan T. Sott
          
              Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror)
              Inspired by the art of Rubens LP (http://www.rubenslp.com.br)
          
          */
          
          .cm-s-paraiso-light.CodeMirror {background: #e7e9db; color: #41323f;}
          .cm-s-paraiso-light div.CodeMirror-selected {background: #b9b6b0 !important;}
          .cm-s-paraiso-light.CodeMirror ::selection { background: #b9b6b0; }
          .cm-s-paraiso-light.CodeMirror ::-moz-selection { background: #b9b6b0; }
          .cm-s-paraiso-light .CodeMirror-gutters {background: #e7e9db; border-right: 0px;}
          .cm-s-paraiso-light .CodeMirror-guttermarker { color: black; }
          .cm-s-paraiso-light .CodeMirror-guttermarker-subtle { color: #8d8687; }
          .cm-s-paraiso-light .CodeMirror-linenumber {color: #8d8687;}
          .cm-s-paraiso-light .CodeMirror-cursor {border-left: 1px solid #776e71 !important;}
          
          .cm-s-paraiso-light span.cm-comment {color: #e96ba8;}
          .cm-s-paraiso-light span.cm-atom {color: #815ba4;}
          .cm-s-paraiso-light span.cm-number {color: #815ba4;}
          
          .cm-s-paraiso-light span.cm-property, .cm-s-paraiso-light span.cm-attribute {color: #48b685;}
          .cm-s-paraiso-light span.cm-keyword {color: #ef6155;}
          .cm-s-paraiso-light span.cm-string {color: #fec418;}
          
          .cm-s-paraiso-light span.cm-variable {color: #48b685;}
          .cm-s-paraiso-light span.cm-variable-2 {color: #06b6ef;}
          .cm-s-paraiso-light span.cm-def {color: #f99b15;}
          .cm-s-paraiso-light span.cm-bracket {color: #41323f;}
          .cm-s-paraiso-light span.cm-tag {color: #ef6155;}
          .cm-s-paraiso-light span.cm-link {color: #815ba4;}
          .cm-s-paraiso-light span.cm-error {background: #ef6155; color: #776e71;}
          
          .cm-s-paraiso-light .CodeMirror-activeline-background {background: #CFD1C4 !important;}
          .cm-s-paraiso-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • pastel-on-dark.css
          /**
           * Pastel On Dark theme ported from ACE editor
           * @license MIT
           * @copyright AtomicPages LLC 2014
           * @author Dennis Thompson, AtomicPages LLC
           * @version 1.1
           * @source https://github.com/atomicpages/codemirror-pastel-on-dark-theme
           */
          
          .cm-s-pastel-on-dark.CodeMirror {
          	background: #2c2827;
          	color: #8F938F;
          	line-height: 1.5;
          	font-size: 14px;
          }
          .cm-s-pastel-on-dark div.CodeMirror-selected { background: rgba(221,240,255,0.2) !important; }
          .cm-s-pastel-on-dark.CodeMirror ::selection { background: rgba(221,240,255,0.2); }
          .cm-s-pastel-on-dark.CodeMirror ::-moz-selection { background: rgba(221,240,255,0.2); }
          
          .cm-s-pastel-on-dark .CodeMirror-gutters {
          	background: #34302f;
          	border-right: 0px;
          	padding: 0 3px;
          }
          .cm-s-pastel-on-dark .CodeMirror-guttermarker { color: white; }
          .cm-s-pastel-on-dark .CodeMirror-guttermarker-subtle { color: #8F938F; }
          .cm-s-pastel-on-dark .CodeMirror-linenumber { color: #8F938F; }
          .cm-s-pastel-on-dark .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; }
          .cm-s-pastel-on-dark span.cm-comment { color: #A6C6FF; }
          .cm-s-pastel-on-dark span.cm-atom { color: #DE8E30; }
          .cm-s-pastel-on-dark span.cm-number { color: #CCCCCC; }
          .cm-s-pastel-on-dark span.cm-property { color: #8F938F; }
          .cm-s-pastel-on-dark span.cm-attribute { color: #a6e22e; }
          .cm-s-pastel-on-dark span.cm-keyword { color: #AEB2F8; }
          .cm-s-pastel-on-dark span.cm-string { color: #66A968; }
          .cm-s-pastel-on-dark span.cm-variable { color: #AEB2F8; }
          .cm-s-pastel-on-dark span.cm-variable-2 { color: #BEBF55; }
          .cm-s-pastel-on-dark span.cm-variable-3 { color: #DE8E30; }
          .cm-s-pastel-on-dark span.cm-def { color: #757aD8; }
          .cm-s-pastel-on-dark span.cm-bracket { color: #f8f8f2; }
          .cm-s-pastel-on-dark span.cm-tag { color: #C1C144; }
          .cm-s-pastel-on-dark span.cm-link { color: #ae81ff; }
          .cm-s-pastel-on-dark span.cm-qualifier,.cm-s-pastel-on-dark span.cm-builtin { color: #C1C144; }
          .cm-s-pastel-on-dark span.cm-error {
          	background: #757aD8;
          	color: #f8f8f0;
          }
          .cm-s-pastel-on-dark .CodeMirror-activeline-background { background: rgba(255, 255, 255, 0.031) !important; }
          .cm-s-pastel-on-dark .CodeMirror-matchingbracket {
          	border: 1px solid rgba(255,255,255,0.25);
          	color: #8F938F !important;
          	margin: -1px -1px 0 -1px;
          }
          
        • rubyblue.css
          .cm-s-rubyblue.CodeMirror { background: #112435; color: white; }
          .cm-s-rubyblue div.CodeMirror-selected { background: #38566F !important; }
          .cm-s-rubyblue.CodeMirror ::selection { background: rgba(56, 86, 111, 0.99); }
          .cm-s-rubyblue.CodeMirror ::-moz-selection { background: rgba(56, 86, 111, 0.99); }
          .cm-s-rubyblue .CodeMirror-gutters { background: #1F4661; border-right: 7px solid #3E7087; }
          .cm-s-rubyblue .CodeMirror-guttermarker { color: white; }
          .cm-s-rubyblue .CodeMirror-guttermarker-subtle { color: #3E7087; }
          .cm-s-rubyblue .CodeMirror-linenumber { color: white; }
          .cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-rubyblue span.cm-comment { color: #999; font-style:italic; line-height: 1em; }
          .cm-s-rubyblue span.cm-atom { color: #F4C20B; }
          .cm-s-rubyblue span.cm-number, .cm-s-rubyblue span.cm-attribute { color: #82C6E0; }
          .cm-s-rubyblue span.cm-keyword { color: #F0F; }
          .cm-s-rubyblue span.cm-string { color: #F08047; }
          .cm-s-rubyblue span.cm-meta { color: #F0F; }
          .cm-s-rubyblue span.cm-variable-2, .cm-s-rubyblue span.cm-tag { color: #7BD827; }
          .cm-s-rubyblue span.cm-variable-3, .cm-s-rubyblue span.cm-def { color: white; }
          .cm-s-rubyblue span.cm-bracket { color: #F0F; }
          .cm-s-rubyblue span.cm-link { color: #F4C20B; }
          .cm-s-rubyblue span.CodeMirror-matchingbracket { color:#F0F !important; }
          .cm-s-rubyblue span.cm-builtin, .cm-s-rubyblue span.cm-special { color: #FF9D00; }
          .cm-s-rubyblue span.cm-error { color: #AF2018; }
          
          .cm-s-rubyblue .CodeMirror-activeline-background {background: #173047 !important;}
          
        • solarized.css
          /*
          Solarized theme for code-mirror
          http://ethanschoonover.com/solarized
          */
          
          /*
          Solarized color pallet
          http://ethanschoonover.com/solarized/img/solarized-palette.png
          */
          
          .solarized.base03 { color: #002b36; }
          .solarized.base02 { color: #073642; }
          .solarized.base01 { color: #586e75; }
          .solarized.base00 { color: #657b83; }
          .solarized.base0 { color: #839496; }
          .solarized.base1 { color: #93a1a1; }
          .solarized.base2 { color: #eee8d5; }
          .solarized.base3  { color: #fdf6e3; }
          .solarized.solar-yellow  { color: #b58900; }
          .solarized.solar-orange  { color: #cb4b16; }
          .solarized.solar-red { color: #dc322f; }
          .solarized.solar-magenta { color: #d33682; }
          .solarized.solar-violet  { color: #6c71c4; }
          .solarized.solar-blue { color: #268bd2; }
          .solarized.solar-cyan { color: #2aa198; }
          .solarized.solar-green { color: #859900; }
          
          /* Color scheme for code-mirror */
          
          .cm-s-solarized {
            line-height: 1.45em;
            color-profile: sRGB;
            rendering-intent: auto;
          }
          .cm-s-solarized.cm-s-dark {
            color: #839496;
            background-color:  #002b36;
            text-shadow: #002b36 0 1px;
          }
          .cm-s-solarized.cm-s-light {
            background-color: #fdf6e3;
            color: #657b83;
            text-shadow: #eee8d5 0 1px;
          }
          
          .cm-s-solarized .CodeMirror-widget {
            text-shadow: none;
          }
          
          
          .cm-s-solarized .cm-keyword { color: #cb4b16 }
          .cm-s-solarized .cm-atom { color: #d33682; }
          .cm-s-solarized .cm-number { color: #d33682; }
          .cm-s-solarized .cm-def { color: #2aa198; }
          
          .cm-s-solarized .cm-variable { color: #839496; }
          .cm-s-solarized .cm-variable-2 { color: #b58900; }
          .cm-s-solarized .cm-variable-3 { color: #6c71c4; }
          
          .cm-s-solarized .cm-property { color: #2aa198; }
          .cm-s-solarized .cm-operator {color: #6c71c4;}
          
          .cm-s-solarized .cm-comment { color: #586e75; font-style:italic; }
          
          .cm-s-solarized .cm-string { color: #859900; }
          .cm-s-solarized .cm-string-2 { color: #b58900; }
          
          .cm-s-solarized .cm-meta { color: #859900; }
          .cm-s-solarized .cm-qualifier { color: #b58900; }
          .cm-s-solarized .cm-builtin { color: #d33682; }
          .cm-s-solarized .cm-bracket { color: #cb4b16; }
          .cm-s-solarized .CodeMirror-matchingbracket { color: #859900; }
          .cm-s-solarized .CodeMirror-nonmatchingbracket { color: #dc322f; }
          .cm-s-solarized .cm-tag { color: #93a1a1 }
          .cm-s-solarized .cm-attribute {  color: #2aa198; }
          .cm-s-solarized .cm-header { color: #586e75; }
          .cm-s-solarized .cm-quote { color: #93a1a1; }
          .cm-s-solarized .cm-hr {
            color: transparent;
            border-top: 1px solid #586e75;
            display: block;
          }
          .cm-s-solarized .cm-link { color: #93a1a1; cursor: pointer; }
          .cm-s-solarized .cm-special { color: #6c71c4; }
          .cm-s-solarized .cm-em {
            color: #999;
            text-decoration: underline;
            text-decoration-style: dotted;
          }
          .cm-s-solarized .cm-strong { color: #eee; }
          .cm-s-solarized .cm-error,
          .cm-s-solarized .cm-invalidchar {
            color: #586e75;
            border-bottom: 1px dotted #dc322f;
          }
          
          .cm-s-solarized.cm-s-dark .CodeMirror-selected { background: #073642; }
          .cm-s-solarized.cm-s-dark.CodeMirror ::selection { background: rgba(7, 54, 66, 0.99); }
          .cm-s-solarized.cm-s-dark.CodeMirror ::-moz-selection { background: rgba(7, 54, 66, 0.99); }
          
          .cm-s-solarized.cm-s-light .CodeMirror-selected { background: #eee8d5; }
          .cm-s-solarized.cm-s-light.CodeMirror ::selection { background: #eee8d5; }
          .cm-s-solarized.cm-s-lightCodeMirror ::-moz-selection { background: #eee8d5; }
          
          /* Editor styling */
          
          
          
          /* Little shadow on the view-port of the buffer view */
          .cm-s-solarized.CodeMirror {
            -moz-box-shadow: inset 7px 0 12px -6px #000;
            -webkit-box-shadow: inset 7px 0 12px -6px #000;
            box-shadow: inset 7px 0 12px -6px #000;
          }
          
          /* Gutter border and some shadow from it  */
          .cm-s-solarized .CodeMirror-gutters {
            border-right: 1px solid;
          }
          
          /* Gutter colors and line number styling based of color scheme (dark / light) */
          
          /* Dark */
          .cm-s-solarized.cm-s-dark .CodeMirror-gutters {
            background-color:  #002b36;
            border-color: #00232c;
          }
          
          .cm-s-solarized.cm-s-dark .CodeMirror-linenumber {
            text-shadow: #021014 0 -1px;
          }
          
          /* Light */
          .cm-s-solarized.cm-s-light .CodeMirror-gutters {
            background-color: #fdf6e3;
            border-color: #eee8d5;
          }
          
          /* Common */
          .cm-s-solarized .CodeMirror-linenumber {
            color: #586e75;
            padding: 0 5px;
          }
          .cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; }
          .cm-s-solarized.cm-s-dark .CodeMirror-guttermarker { color: #ddd; }
          .cm-s-solarized.cm-s-light .CodeMirror-guttermarker { color: #cb4b16; }
          
          .cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text {
            color: #586e75;
          }
          
          .cm-s-solarized .CodeMirror-lines .CodeMirror-cursor {
            border-left: 1px solid #819090;
          }
          
          /*
          Active line. Negative margin compensates left padding of the text in the
          view-port
          */
          .cm-s-solarized.cm-s-dark .CodeMirror-activeline-background {
            background: rgba(255, 255, 255, 0.10);
          }
          .cm-s-solarized.cm-s-light .CodeMirror-activeline-background {
            background: rgba(0, 0, 0, 0.10);
          }
          
        • the-matrix.css
          .cm-s-the-matrix.CodeMirror { background: #000000; color: #00FF00; }
          .cm-s-the-matrix div.CodeMirror-selected { background: #2D2D2D !important; }
          .cm-s-the-matrix.CodeMirror ::selection { background: rgba(45, 45, 45, 0.99); }
          .cm-s-the-matrix.CodeMirror ::-moz-selection { background: rgba(45, 45, 45, 0.99); }
          .cm-s-the-matrix .CodeMirror-gutters { background: #060; border-right: 2px solid #00FF00; }
          .cm-s-the-matrix .CodeMirror-guttermarker { color: #0f0; }
          .cm-s-the-matrix .CodeMirror-guttermarker-subtle { color: white; }
          .cm-s-the-matrix .CodeMirror-linenumber { color: #FFFFFF; }
          .cm-s-the-matrix .CodeMirror-cursor { border-left: 1px solid #00FF00 !important; }
          
          .cm-s-the-matrix span.cm-keyword {color: #008803; font-weight: bold;}
          .cm-s-the-matrix span.cm-atom {color: #3FF;}
          .cm-s-the-matrix span.cm-number {color: #FFB94F;}
          .cm-s-the-matrix span.cm-def {color: #99C;}
          .cm-s-the-matrix span.cm-variable {color: #F6C;}
          .cm-s-the-matrix span.cm-variable-2 {color: #C6F;}
          .cm-s-the-matrix span.cm-variable-3 {color: #96F;}
          .cm-s-the-matrix span.cm-property {color: #62FFA0;}
          .cm-s-the-matrix span.cm-operator {color: #999}
          .cm-s-the-matrix span.cm-comment {color: #CCCCCC;}
          .cm-s-the-matrix span.cm-string {color: #39C;}
          .cm-s-the-matrix span.cm-meta {color: #C9F;}
          .cm-s-the-matrix span.cm-qualifier {color: #FFF700;}
          .cm-s-the-matrix span.cm-builtin {color: #30a;}
          .cm-s-the-matrix span.cm-bracket {color: #cc7;}
          .cm-s-the-matrix span.cm-tag {color: #FFBD40;}
          .cm-s-the-matrix span.cm-attribute {color: #FFF700;}
          .cm-s-the-matrix span.cm-error {color: #FF0000;}
          
          .cm-s-the-matrix .CodeMirror-activeline-background {background: #040;}
          
        • tomorrow-night-bright.css
          /*
          
              Name:       Tomorrow Night - Bright
              Author:     Chris Kempson
          
              Port done by Gerard Braad <me@gbraad.nl>
          
          */
          
          .cm-s-tomorrow-night-bright.CodeMirror {background: #000000; color: #eaeaea;}
          .cm-s-tomorrow-night-bright div.CodeMirror-selected {background: #424242 !important;}
          .cm-s-tomorrow-night-bright .CodeMirror-gutters {background: #000000; border-right: 0px;}
          .cm-s-tomorrow-night-bright .CodeMirror-guttermarker { color: #e78c45; }
          .cm-s-tomorrow-night-bright .CodeMirror-guttermarker-subtle { color: #777; }
          .cm-s-tomorrow-night-bright .CodeMirror-linenumber {color: #424242;}
          .cm-s-tomorrow-night-bright .CodeMirror-cursor {border-left: 1px solid #6A6A6A !important;}
          
          .cm-s-tomorrow-night-bright span.cm-comment {color: #d27b53;}
          .cm-s-tomorrow-night-bright span.cm-atom {color: #a16a94;}
          .cm-s-tomorrow-night-bright span.cm-number {color: #a16a94;}
          
          .cm-s-tomorrow-night-bright span.cm-property, .cm-s-tomorrow-night-bright span.cm-attribute {color: #99cc99;}
          .cm-s-tomorrow-night-bright span.cm-keyword {color: #d54e53;}
          .cm-s-tomorrow-night-bright span.cm-string {color: #e7c547;}
          
          .cm-s-tomorrow-night-bright span.cm-variable {color: #b9ca4a;}
          .cm-s-tomorrow-night-bright span.cm-variable-2 {color: #7aa6da;}
          .cm-s-tomorrow-night-bright span.cm-def {color: #e78c45;}
          .cm-s-tomorrow-night-bright span.cm-bracket {color: #eaeaea;}
          .cm-s-tomorrow-night-bright span.cm-tag {color: #d54e53;}
          .cm-s-tomorrow-night-bright span.cm-link {color: #a16a94;}
          .cm-s-tomorrow-night-bright span.cm-error {background: #d54e53; color: #6A6A6A;}
          
          .cm-s-tomorrow-night-bright .CodeMirror-activeline-background {background: #2a2a2a !important;}
          .cm-s-tomorrow-night-bright .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • tomorrow-night-eighties.css
          /*
          
              Name:       Tomorrow Night - Eighties
              Author:     Chris Kempson
          
              CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
              Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
          
          */
          
          .cm-s-tomorrow-night-eighties.CodeMirror {background: #000000; color: #CCCCCC;}
          .cm-s-tomorrow-night-eighties div.CodeMirror-selected {background: #2D2D2D !important;}
          .cm-s-tomorrow-night-eighties.CodeMirror ::selection { background: rgba(45, 45, 45, 0.99); }
          .cm-s-tomorrow-night-eighties.CodeMirror ::-moz-selection { background: rgba(45, 45, 45, 0.99); }
          .cm-s-tomorrow-night-eighties .CodeMirror-gutters {background: #000000; border-right: 0px;}
          .cm-s-tomorrow-night-eighties .CodeMirror-guttermarker { color: #f2777a; }
          .cm-s-tomorrow-night-eighties .CodeMirror-guttermarker-subtle { color: #777; }
          .cm-s-tomorrow-night-eighties .CodeMirror-linenumber {color: #515151;}
          .cm-s-tomorrow-night-eighties .CodeMirror-cursor {border-left: 1px solid #6A6A6A !important;}
          
          .cm-s-tomorrow-night-eighties span.cm-comment {color: #d27b53;}
          .cm-s-tomorrow-night-eighties span.cm-atom {color: #a16a94;}
          .cm-s-tomorrow-night-eighties span.cm-number {color: #a16a94;}
          
          .cm-s-tomorrow-night-eighties span.cm-property, .cm-s-tomorrow-night-eighties span.cm-attribute {color: #99cc99;}
          .cm-s-tomorrow-night-eighties span.cm-keyword {color: #f2777a;}
          .cm-s-tomorrow-night-eighties span.cm-string {color: #ffcc66;}
          
          .cm-s-tomorrow-night-eighties span.cm-variable {color: #99cc99;}
          .cm-s-tomorrow-night-eighties span.cm-variable-2 {color: #6699cc;}
          .cm-s-tomorrow-night-eighties span.cm-def {color: #f99157;}
          .cm-s-tomorrow-night-eighties span.cm-bracket {color: #CCCCCC;}
          .cm-s-tomorrow-night-eighties span.cm-tag {color: #f2777a;}
          .cm-s-tomorrow-night-eighties span.cm-link {color: #a16a94;}
          .cm-s-tomorrow-night-eighties span.cm-error {background: #f2777a; color: #6A6A6A;}
          
          .cm-s-tomorrow-night-eighties .CodeMirror-activeline-background {background: #343600 !important;}
          .cm-s-tomorrow-night-eighties .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
          
        • ttcn.css
          /* DEFAULT THEME */
          .cm-atom {color: #219;}
          .cm-attribute {color: #00c;}
          .cm-bracket {color: #997;}
          .cm-comment {color: #333333;}
          .cm-def {color: #00f;}
          .cm-em {font-style: italic;}
          .cm-error {color: #f00;}
          .cm-header {color: #00f; font-weight: bold;}
          .cm-hr {color: #999;}
          .cm-invalidchar {color: #f00;}
          .cm-keyword {font-weight:bold}
          .cm-link {color: #00c; text-decoration: underline;}
          .cm-meta {color: #555;}
          .cm-negative {color: #d44;}
          .cm-positive {color: #292;}
          .cm-qualifier {color: #555;}
          .cm-quote {color: #090;}
          .cm-strikethrough {text-decoration: line-through;}
          .cm-string {color: #006400;}
          .cm-string-2 {color: #f50;}
          .cm-strong {font-weight: bold;}
          .cm-tag {color: #170;}
          .cm-variable {color: #8B2252;}
          .cm-variable-2 {color: #05a;}
          .cm-variable-3 {color: #085;}
          
          .cm-negative {color: #d44;}
          .cm-positive {color: #292;}
          .cm-header, .cm-strong {font-weight: bold;}
          .cm-em {font-style: italic;}
          .cm-link {text-decoration: underline;}
          .cm-strikethrough {text-decoration: line-through;}
          
          .cm-s-default .cm-error {color: #f00;}
          .cm-invalidchar {color: #f00;}
          
          /* ASN */
          .cm-s-ttcn .cm-accessTypes,
          .cm-s-ttcn .cm-compareTypes {color: #27408B}
          .cm-s-ttcn .cm-cmipVerbs {color: #8B2252}
          .cm-s-ttcn .cm-modifier {color:#D2691E}
          .cm-s-ttcn .cm-status {color:#8B4545}
          .cm-s-ttcn .cm-storage {color:#A020F0}
          .cm-s-ttcn .cm-tags {color:#006400}
          
          /* CFG */
          .cm-s-ttcn .cm-externalCommands {color: #8B4545; font-weight:bold}
          .cm-s-ttcn .cm-fileNCtrlMaskOptions,
          .cm-s-ttcn .cm-sectionTitle {color: #2E8B57; font-weight:bold}
          
          /* TTCN */
          .cm-s-ttcn .cm-booleanConsts,
          .cm-s-ttcn .cm-otherConsts,
          .cm-s-ttcn .cm-verdictConsts {color: #006400}
          .cm-s-ttcn .cm-configOps,
          .cm-s-ttcn .cm-functionOps,
          .cm-s-ttcn .cm-portOps,
          .cm-s-ttcn .cm-sutOps,
          .cm-s-ttcn .cm-timerOps,
          .cm-s-ttcn .cm-verdictOps {color: #0000FF}
          .cm-s-ttcn .cm-preprocessor,
          .cm-s-ttcn .cm-templateMatch,
          .cm-s-ttcn .cm-ttcn3Macros {color: #27408B}
          .cm-s-ttcn .cm-types {color: #A52A2A; font-weight:bold}
          .cm-s-ttcn .cm-visibilityModifiers {font-weight:bold}
          
        • twilight.css
          .cm-s-twilight.CodeMirror { background: #141414; color: #f7f7f7; } /**/
          .cm-s-twilight .CodeMirror-selected { background: #323232 !important; } /**/
          .cm-s-twilight.CodeMirror ::selection { background: rgba(50, 50, 50, 0.99); }
          .cm-s-twilight.CodeMirror ::-moz-selection { background: rgba(50, 50, 50, 0.99); }
          
          .cm-s-twilight .CodeMirror-gutters { background: #222; border-right: 1px solid #aaa; }
          .cm-s-twilight .CodeMirror-guttermarker { color: white; }
          .cm-s-twilight .CodeMirror-guttermarker-subtle { color: #aaa; }
          .cm-s-twilight .CodeMirror-linenumber { color: #aaa; }
          .cm-s-twilight .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-twilight .cm-keyword {  color: #f9ee98; } /**/
          .cm-s-twilight .cm-atom { color: #FC0; }
          .cm-s-twilight .cm-number { color:  #ca7841; } /**/
          .cm-s-twilight .cm-def { color: #8DA6CE; }
          .cm-s-twilight span.cm-variable-2, .cm-s-twilight span.cm-tag { color: #607392; } /**/
          .cm-s-twilight span.cm-variable-3, .cm-s-twilight span.cm-def { color: #607392; } /**/
          .cm-s-twilight .cm-operator { color: #cda869; } /**/
          .cm-s-twilight .cm-comment { color:#777; font-style:italic; font-weight:normal; } /**/
          .cm-s-twilight .cm-string { color:#8f9d6a; font-style:italic; } /**/
          .cm-s-twilight .cm-string-2 { color:#bd6b18 } /*?*/
          .cm-s-twilight .cm-meta { background-color:#141414; color:#f7f7f7; } /*?*/
          .cm-s-twilight .cm-builtin { color: #cda869; } /*?*/
          .cm-s-twilight .cm-tag { color: #997643; } /**/
          .cm-s-twilight .cm-attribute { color: #d6bb6d; } /*?*/
          .cm-s-twilight .cm-header { color: #FF6400; }
          .cm-s-twilight .cm-hr { color: #AEAEAE; }
          .cm-s-twilight .cm-link {   color:#ad9361; font-style:italic; text-decoration:none; } /**/
          .cm-s-twilight .cm-error { border-bottom: 1px solid red; }
          
          .cm-s-twilight .CodeMirror-activeline-background {background: #27282E !important;}
          .cm-s-twilight .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;}
          
        • vibrant-ink.css
          /* Taken from the popular Visual Studio Vibrant Ink Schema */
          
          .cm-s-vibrant-ink.CodeMirror { background: black; color: white; }
          .cm-s-vibrant-ink .CodeMirror-selected { background: #35493c !important; }
          .cm-s-vibrant-ink.CodeMirror ::selection { background: rgba(53, 73, 60, 0.99); }
          .cm-s-vibrant-ink.CodeMirror ::-moz-selection { background: rgba(53, 73, 60, 0.99); }
          
          .cm-s-vibrant-ink .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }
          .cm-s-vibrant-ink .CodeMirror-guttermarker { color: white; }
          .cm-s-vibrant-ink .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
          .cm-s-vibrant-ink .CodeMirror-linenumber { color: #d0d0d0; }
          .cm-s-vibrant-ink .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-vibrant-ink .cm-keyword {  color: #CC7832; }
          .cm-s-vibrant-ink .cm-atom { color: #FC0; }
          .cm-s-vibrant-ink .cm-number { color:  #FFEE98; }
          .cm-s-vibrant-ink .cm-def { color: #8DA6CE; }
          .cm-s-vibrant-ink span.cm-variable-2, .cm-s-vibrant span.cm-tag { color: #FFC66D }
          .cm-s-vibrant-ink span.cm-variable-3, .cm-s-vibrant span.cm-def { color: #FFC66D }
          .cm-s-vibrant-ink .cm-operator { color: #888; }
          .cm-s-vibrant-ink .cm-comment { color: gray; font-weight: bold; }
          .cm-s-vibrant-ink .cm-string { color:  #A5C25C }
          .cm-s-vibrant-ink .cm-string-2 { color: red }
          .cm-s-vibrant-ink .cm-meta { color: #D8FA3C; }
          .cm-s-vibrant-ink .cm-builtin { color: #8DA6CE; }
          .cm-s-vibrant-ink .cm-tag { color: #8DA6CE; }
          .cm-s-vibrant-ink .cm-attribute { color: #8DA6CE; }
          .cm-s-vibrant-ink .cm-header { color: #FF6400; }
          .cm-s-vibrant-ink .cm-hr { color: #AEAEAE; }
          .cm-s-vibrant-ink .cm-link { color: blue; }
          .cm-s-vibrant-ink .cm-error { border-bottom: 1px solid red; }
          
          .cm-s-vibrant-ink .CodeMirror-activeline-background {background: #27282E !important;}
          .cm-s-vibrant-ink .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;}
          
        • xq-dark.css
          /*
          Copyright (C) 2011 by MarkLogic Corporation
          Author: Mike Brevoort <mike@brevoort.com>
          
          Permission is hereby granted, free of charge, to any person obtaining a copy
          of this software and associated documentation files (the "Software"), to deal
          in the Software without restriction, including without limitation the rights
          to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
          copies of the Software, and to permit persons to whom the Software is
          furnished to do so, subject to the following conditions:
          
          The above copyright notice and this permission notice shall be included in
          all copies or substantial portions of the Software.
          
          THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
          IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
          FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
          AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
          LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
          OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
          THE SOFTWARE.
          */
          .cm-s-xq-dark.CodeMirror { background: #0a001f; color: #f8f8f8; }
          .cm-s-xq-dark .CodeMirror-selected { background: #27007A !important; }
          .cm-s-xq-dark.CodeMirror ::selection { background: rgba(39, 0, 122, 0.99); }
          .cm-s-xq-dark.CodeMirror ::-moz-selection { background: rgba(39, 0, 122, 0.99); }
          .cm-s-xq-dark .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; }
          .cm-s-xq-dark .CodeMirror-guttermarker { color: #FFBD40; }
          .cm-s-xq-dark .CodeMirror-guttermarker-subtle { color: #f8f8f8; }
          .cm-s-xq-dark .CodeMirror-linenumber { color: #f8f8f8; }
          .cm-s-xq-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
          
          .cm-s-xq-dark span.cm-keyword {color: #FFBD40;}
          .cm-s-xq-dark span.cm-atom {color: #6C8CD5;}
          .cm-s-xq-dark span.cm-number {color: #164;}
          .cm-s-xq-dark span.cm-def {color: #FFF; text-decoration:underline;}
          .cm-s-xq-dark span.cm-variable {color: #FFF;}
          .cm-s-xq-dark span.cm-variable-2 {color: #EEE;}
          .cm-s-xq-dark span.cm-variable-3 {color: #DDD;}
          .cm-s-xq-dark span.cm-property {}
          .cm-s-xq-dark span.cm-operator {}
          .cm-s-xq-dark span.cm-comment {color: gray;}
          .cm-s-xq-dark span.cm-string {color: #9FEE00;}
          .cm-s-xq-dark span.cm-meta {color: yellow;}
          .cm-s-xq-dark span.cm-qualifier {color: #FFF700;}
          .cm-s-xq-dark span.cm-builtin {color: #30a;}
          .cm-s-xq-dark span.cm-bracket {color: #cc7;}
          .cm-s-xq-dark span.cm-tag {color: #FFBD40;}
          .cm-s-xq-dark span.cm-attribute {color: #FFF700;}
          .cm-s-xq-dark span.cm-error {color: #f00;}
          
          .cm-s-xq-dark .CodeMirror-activeline-background {background: #27282E !important;}
          .cm-s-xq-dark .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;}
        • xq-light.css
          /*
          Copyright (C) 2011 by MarkLogic Corporation
          Author: Mike Brevoort <mike@brevoort.com>
          
          Permission is hereby granted, free of charge, to any person obtaining a copy
          of this software and associated documentation files (the "Software"), to deal
          in the Software without restriction, including without limitation the rights
          to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
          copies of the Software, and to permit persons to whom the Software is
          furnished to do so, subject to the following conditions:
          
          The above copyright notice and this permission notice shall be included in
          all copies or substantial portions of the Software.
          
          THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
          IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
          FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
          AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
          LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
          OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
          THE SOFTWARE.
          */
          .cm-s-xq-light span.cm-keyword {line-height: 1em; font-weight: bold; color: #5A5CAD; }
          .cm-s-xq-light span.cm-atom {color: #6C8CD5;}
          .cm-s-xq-light span.cm-number {color: #164;}
          .cm-s-xq-light span.cm-def {text-decoration:underline;}
          .cm-s-xq-light span.cm-variable {color: black; }
          .cm-s-xq-light span.cm-variable-2 {color:black;}
          .cm-s-xq-light span.cm-variable-3 {color: black; }
          .cm-s-xq-light span.cm-property {}
          .cm-s-xq-light span.cm-operator {}
          .cm-s-xq-light span.cm-comment {color: #0080FF; font-style: italic;}
          .cm-s-xq-light span.cm-string {color: red;}
          .cm-s-xq-light span.cm-meta {color: yellow;}
          .cm-s-xq-light span.cm-qualifier {color: grey}
          .cm-s-xq-light span.cm-builtin {color: #7EA656;}
          .cm-s-xq-light span.cm-bracket {color: #cc7;}
          .cm-s-xq-light span.cm-tag {color: #3F7F7F;}
          .cm-s-xq-light span.cm-attribute {color: #7F007F;}
          .cm-s-xq-light span.cm-error {color: #f00;}
          
          .cm-s-xq-light .CodeMirror-activeline-background {background: #e8f2ff !important;}
          .cm-s-xq-light .CodeMirror-matchingbracket {outline:1px solid grey;color:black !important;background:yellow;}
        • zenburn.css
          /**
           * "
           *  Using Zenburn color palette from the Emacs Zenburn Theme
           *  https://github.com/bbatsov/zenburn-emacs/blob/master/zenburn-theme.el
           *
           *  Also using parts of https://github.com/xavi/coderay-lighttable-theme
           * "
           * From: https://github.com/wisenomad/zenburn-lighttable-theme/blob/master/zenburn.css
           */
          
          .cm-s-zenburn .CodeMirror-gutters { background: #3f3f3f !important; }
          .cm-s-zenburn .CodeMirror-foldgutter-open, .CodeMirror-foldgutter-folded { color: #999; }
          .cm-s-zenburn .CodeMirror-cursor { border-left: 1px solid white !important; }
          .cm-s-zenburn { background-color: #3f3f3f; color: #dcdccc; }
          .cm-s-zenburn span.cm-builtin { color: #dcdccc; font-weight: bold; }
          .cm-s-zenburn span.cm-comment { color: #7f9f7f; }
          .cm-s-zenburn span.cm-keyword { color: #f0dfaf; font-weight: bold; }
          .cm-s-zenburn span.cm-atom { color: #bfebbf; }
          .cm-s-zenburn span.cm-def { color: #dcdccc; }
          .cm-s-zenburn span.cm-variable { color: #dfaf8f; }
          .cm-s-zenburn span.cm-variable-2 { color: #dcdccc; }
          .cm-s-zenburn span.cm-string { color: #cc9393; }
          .cm-s-zenburn span.cm-string-2 { color: #cc9393; }
          .cm-s-zenburn span.cm-number { color: #dcdccc; }
          .cm-s-zenburn span.cm-tag { color: #93e0e3; }
          .cm-s-zenburn span.cm-property { color: #dfaf8f; }
          .cm-s-zenburn span.cm-attribute { color: #dfaf8f; }
          .cm-s-zenburn span.cm-qualifier { color: #7cb8bb; }
          .cm-s-zenburn span.cm-meta { color: #f0dfaf; }
          .cm-s-zenburn span.cm-header { color: #f0efd0; }
          .cm-s-zenburn span.cm-operator { color: #f0efd0; }
          .cm-s-zenburn span.CodeMirror-matchingbracket { box-sizing: border-box; background: transparent; border-bottom: 1px solid; }
          .cm-s-zenburn span.CodeMirror-nonmatchingbracket { border-bottom: 1px solid; background: none; }
          .cm-s-zenburn .CodeMirror-activeline { background: #000000; }
          .cm-s-zenburn .CodeMirror-activeline-background { background: #000000; }
          .cm-s-zenburn .CodeMirror-selected { background: #545454; }
          .cm-s-zenburn .CodeMirror-focused .CodeMirror-selected { background: #4f4f4f; }
          
      • AUTHORS
        List of CodeMirror contributors. Updated before every release.
        
        4r2r
        Aaron Brooks
        Abdelouahab
        Abe Fettig
        Adam Ahmed
        Adam King
        adanlobato
        Adán Lobato
        Adrian Aichner
        aeroson
        Ahmad Amireh
        Ahmad M. Zawawi
        ahoward
        Akeksandr Motsjonov
        Alberto González Palomo
        Alberto Pose
        Albert Xing
        Alexander Pavlov
        Alexander Schepanovski
        Alexander Shvets
        Alexander Solovyov
        Alexandre Bique
        alexey-k
        Alex Piggott
        Aliaksei Chapyzhenka
        Amin Shali
        Amsul
        amuntean
        Amy
        Ananya Sen
        anaran
        AndersMad
        Anders Nawroth
        Anderson Mesquita
        Andrea G
        Andreas Reischuck
        Andre von Houck
        Andrey Fedorov
        Andrey Klyuchnikov
        Andrey Lushnikov
        Andy Joslin
        Andy Kimball
        Andy Li
        angelozerr
        angelo.zerr@gmail.com
        Ankit
        Ankit Ahuja
        Ansel Santosa
        Anthony Grimes
        Anton Kovalyov
        areos
        as3boyan
        AtomicPages LLC
        Atul Bhouraskar
        Aurelian Oancea
        Bastian Müller
        Bem Jones-Bey
        benbro
        Beni Cherniavsky-Paskin
        Benjamin DeCoste
        Ben Keen
        Bernhard Sirlinger
        Bert Chang
        Billy Moon
        binny
        B Krishna Chaitanya
        Blaine G
        blukat29
        boomyjee
        borawjm
        Brandon Frohs
        Brandon Wamboldt
        Brett Zamir
        Brian Grinstead
        Brian Sletten
        Bruce Mitchener
        Chandra Sekhar Pydi
        Charles Skelton
        Cheah Chu Yeow
        Chris Coyier
        Chris Granger
        Chris Houseknecht
        Chris Lohfink
        Chris Morgan
        Christian Oyarzun
        Christian Petrov
        Christopher Brown
        Christopher Mitchell
        Christopher Pfohl
        ciaranj
        CodeAnimal
        coderaiser
        ComFreek
        Curtis Gagliardi
        dagsta
        daines
        Dale Jung
        Dan Bentley
        Dan Heberden
        Daniel, Dao Quang Minh
        Daniele Di Sarli
        Daniel Faust
        Daniel Huigens
        Daniel KJ
        Daniel Neel
        Daniel Parnell
        Danny Yoo
        darealshinji
        Darius Roberts
        Dave Myers
        David Barnett
        David Mignot
        David Pathakjee
        David Vázquez
        deebugger
        Deep Thought
        Devon Carew
        dignifiedquire
        Dimage Sapelkin
        Dmitry Kiselyov
        domagoj412
        Dominator008
        Domizio Demichelis
        Doug Wikle
        Drew Bratcher
        Drew Hintz
        Drew Khoury
        Dror BG
        duralog
        eborden
        edsharp
        ekhaled
        Enam Mijbah Noor
        Eric Allam
        eustas
        Fabien O'Carroll
        Fabio Zendhi Nagao
        Faiza Alsaied
        Fauntleroy
        fbuchinger
        feizhang365
        Felipe Lalanne
        Felix Raab
        Filip Noetzel
        flack
        ForbesLindesay
        Forbes Lindesay
        Ford_Lawnmower
        Forrest Oliphant
        Frank Wiegand
        Gabriel Gheorghian
        Gabriel Horner
        Gabriel Nahmias
        galambalazs
        Gautam Mehta
        gekkoe
        Gerard Braad
        Gergely Hegykozi
        Giovanni Calò
        Glenn Jorde
        Glenn Ruehle
        Golevka
        Gordon Smith
        Grant Skinner
        greengiant
        Gregory Koberger
        Guillaume Massé
        Guillaume Massé
        Gustavo Rodrigues
        Hakan Tunc
        Hans Engel
        Hardest
        Hasan Karahan
        Herculano Campos
        Hiroyuki Makino
        hitsthings
        Hocdoc
        Ian Beck
        Ian Dickinson
        Ian Wehrman
        Ian Wetherbee
        Ice White
        ICHIKAWA, Yuji
        ilvalle
        Ingo Richter
        Irakli Gozalishvili
        Ivan Kurnosov
        Ivoah
        Jacob Lee
        Jakob Miland
        Jakub Vrana
        Jakub Vrána
        James Campos
        James Thorne
        Jamie Hill
        Jan Jongboom
        jankeromnes
        Jan Keromnes
        Jan Odvarko
        Jan T. Sott
        Jared Forsyth
        Jason
        Jason Barnabe
        Jason Grout
        Jason Johnston
        Jason San Jose
        Jason Siefken
        Jaydeep Solanki
        Jean Boussier
        jeffkenton
        Jeff Pickhardt
        jem (graphite)
        Jeremy Parmenter
        Jochen Berger
        Johan Ask
        John Connor
        John Lees-Miller
        John Snelson
        John Van Der Loo
        Jonas Döbertin
        Jonathan Malmaud
        jongalloway
        Jon Malmaud
        Jon Sangster
        Joost-Wim Boekesteijn
        Joseph Pecoraro
        Joshua Newman
        Josh Watzman
        jots
        jsoojeon
        ju1ius
        Juan Benavides Romero
        Jucovschi Constantin
        Juho Vuori
        Justin Hileman
        jwallers@gmail.com
        kaniga
        Ken Newman
        Ken Rockot
        Kevin Earls
        Kevin Sawicki
        Kevin Ushey
        Klaus Silveira
        Koh Zi Han, Cliff
        komakino
        Konstantin Lopuhin
        koops
        ks-ifware
        kubelsmieci
        KwanEsq
        Lanfei
        Lanny
        Laszlo Vidacs
        leaf corcoran
        Leonid Khachaturov
        Leon Sorokin
        Leonya Khachaturov
        Liam Newman
        Libo Cannici
        LloydMilligan
        LM
        lochel
        Lorenzo Stoakes
        Luciano Longo
        Luke Stagner
        lynschinzer
        Maksim Lin
        Maksym Taran
        Malay Majithia
        Manuel Rego Casasnovas
        Marat Dreizin
        Marcel Gerber
        Marco Aurélio
        Marco Munizaga
        Marcus Bointon
        Marek Rudnicki
        Marijn Haverbeke
        Mário Gonçalves
        Mario Pietsch
        Mark Lentczner
        Marko Bonaci
        Martin Balek
        Martín Gaitán
        Martin Hasoň
        Martin Hunt
        Mason Malone
        Mateusz Paprocki
        Mathias Bynens
        mats cronqvist
        Matthew Beale
        Matthias Bussonnier
        Matthias BUSSONNIER
        Matt McDonald
        Matt Pass
        Matt Sacks
        mauricio
        Maximilian Hils
        Maxim Kraev
        Max Kirsch
        Max Xiantu
        mbarkhau
        Metatheos
        Micah Dubinko
        Michael Grey
        Michael Lehenbauer
        Michael Zhou
        Mighty Guava
        Miguel Castillo
        mihailik
        Mike
        Mike Brevoort
        Mike Diaz
        Mike Ivanov
        Mike Kadin
        MinRK
        Miraculix87
        misfo
        mloginov
        Moritz Schwörer
        mps
        ms
        mtaran-google
        Narciso Jaramillo
        Nathan Williams
        ndr
        nerbert
        nextrevision
        ngn
        nguillaumin
        Ng Zhi An
        Nicholas Bollweg
        Nicholas Bollweg (Nick)
        Nick Kreeger
        Nick Small
        Niels van Groningen
        nightwing
        Nikita Beloglazov
        Nikita Vasilyev
        Nikolay Kostov
        nilp0inter
        Nisarg Jhaveri
        nlwillia
        Norman Rzepka
        pablo
        Page
        Panupong Pasupat
        paris
        Paris
        Patil Arpith
        Patrick Stoica
        Patrick Strawderman
        Paul Garvin
        Paul Ivanov
        Pavel Feldman
        Pavel Strashkin
        Paweł Bartkiewicz
        peteguhl
        Peter Flynn
        peterkroon
        Peter Kroon
        prasanthj
        Prasanth J
        Radek Piórkowski
        Rahul
        Randall Mason
        Randy Burden
        Randy Edmunds
        Rasmus Erik Voel Jensen
        ray ratchup
        Ray Ratchup
        Richard van der Meer
        Richard Z.H. Wang
        Robert Crossfield
        Roberto Abdelkader Martínez Pérez
        robertop23
        Robert Plummer
        Ruslan Osmanov
        Ryan Prior
        sabaca
        Samuel Ainsworth
        sandeepshetty
        Sander AKA Redsandro
        santec
        Sascha Peilicke
        satchmorun
        sathyamoorthi
        SCLINIC\jdecker
        Scott Aikin
        Scott Goodhew
        Sebastian Zaha
        shaund
        shaun gilchrist
        Shawn A
        sheopory
        Shiv Deepak
        Shmuel Englard
        Shubham Jain
        silverwind
        snasa
        soliton4
        sonson
        spastorelli
        srajanpaliwal
        Stanislav Oaserele
        Stas Kobzar
        Stefan Borsje
        Steffen Beyer
        Steve O'Hara
        stoskov
        Taha Jahangir
        Takuji Shimokawa
        Tarmil
        tel
        tfjgeorge
        Thaddee Tyl
        TheHowl
        think
        Thomas Dvornik
        Thomas Schmid
        Tim Alby
        Tim Baumann
        Timothy Farrell
        Timothy Hatcher
        TobiasBg
        Tomas-A
        Tomas Varaneckas
        Tom Erik Støwer
        Tom MacWright
        Tony Jian
        Travis Heppe
        Triangle717
        twifkak
        Vestimir Markov
        vf
        Vincent Woo
        Volker Mische
        wenli
        Wesley Wiser
        Will Binns-Smith
        William Jamieson
        William Stein
        Willy
        Wojtek Ptak
        Xavier Mendez
        Yassin N. Hassan
        YNH Webdev
        Yunchi Luo
        Yuvi Panda
        Zachary Dremann
        Zhang Hao
        zziuni
        魏鹏刚
        
      • CONTRIBUTING.md
        # How to contribute
        
        - [Getting help](#getting-help-)
        - [Submitting bug reports](#submitting-bug-reports-)
        - [Contributing code](#contributing-code-)
        
        ## Getting help
        
        Community discussion, questions, and informal bug reporting is done on the
        [discuss.CodeMirror forum](http://discuss.codemirror.net).
        
        ## Submitting bug reports
        
        The preferred way to report bugs is to use the
        [GitHub issue tracker](http://github.com/codemirror/CodeMirror/issues). Before
        reporting a bug, read these pointers.
        
        **Note:** The issue tracker is for *bugs*, not requests for help. Questions
        should be asked on the
        [discuss.CodeMirror forum](http://discuss.codemirror.net) instead.
        
        ### Reporting bugs effectively
        
        - CodeMirror is maintained by volunteers. They don't owe you anything, so be
          polite. Reports with an indignant or belligerent tone tend to be moved to the
          bottom of the pile.
        
        - Include information about **the browser in which the problem occurred**. Even
          if you tested several browsers, and the problem occurred in all of them,
          mention this fact in the bug report. Also include browser version numbers and
          the operating system that you're on.
        
        - Mention which release of CodeMirror you're using. Preferably, try also with
          the current development snapshot, to ensure the problem has not already been
          fixed.
        
        - Mention very precisely what went wrong. "X is broken" is not a good bug
          report. What did you expect to happen? What happened instead? Describe the
          exact steps a maintainer has to take to make the problem occur. We can not
          fix something that we can not observe.
        
        - If the problem can not be reproduced in any of the demos included in the
          CodeMirror distribution, please provide an HTML document that demonstrates
          the problem. The best way to do this is to go to
          [jsbin.com](http://jsbin.com/ihunin/edit), enter it there, press save, and
          include the resulting link in your bug report.
        
        ## Contributing code
        
        - Make sure you have a [GitHub Account](https://github.com/signup/free)
        - Fork [CodeMirror](https://github.com/codemirror/CodeMirror/)
          ([how to fork a repo](https://help.github.com/articles/fork-a-repo))
        - Make your changes
        - If your changes are easy to test or likely to regress, add tests.
          Tests for the core go into `test/test.js`, some modes have their own
          test suite under `mode/XXX/test.js`. Feel free to add new test
          suites to modes that don't have one yet (be sure to link the new
          tests into `test/index.html`).
        - Follow the general code style of the rest of the project (see
          below). Run `bin/lint` to verify that the linter is happy.
        - Make sure all tests pass. Visit `test/index.html` in your browser to
          run them.
        - Submit a pull request
        ([how to create a pull request](https://help.github.com/articles/fork-a-repo))
        
        ### Coding standards
        
        - 2 spaces per indentation level, no tabs.
        - Include semicolons after statements.
        - Note that the linter (`bin/lint`) which is run after each commit
          complains about unused variables and functions. Prefix their names
          with an underscore to muffle it.
        
        - CodeMirror does *not* follow JSHint or JSLint prescribed style.
          Patches that try to 'fix' code to pass one of these linters will be
          unceremoniously discarded.
        
      • LICENSE
        Copyright (C) 2015 by Marijn Haverbeke <marijnh@gmail.com> and others
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in
        all copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        THE SOFTWARE.
        
      • README.md
        # CodeMirror
        [![Build Status](https://travis-ci.org/codemirror/CodeMirror.svg)](https://travis-ci.org/codemirror/CodeMirror)
        [![NPM version](https://img.shields.io/npm/v/codemirror.svg)](https://www.npmjs.org/package/codemirror)  
        [Funding status: ![maintainer happiness](https://marijnhaverbeke.nl/fund/status_s.png?again)](https://marijnhaverbeke.nl/fund/)
        
        CodeMirror is a JavaScript component that provides a code editor in
        the browser. When a mode is available for the language you are coding
        in, it will color your code, and optionally help with indentation.
        
        The project page is http://codemirror.net  
        The manual is at http://codemirror.net/doc/manual.html  
        The contributing guidelines are in [CONTRIBUTING.md](https://github.com/codemirror/CodeMirror/blob/master/CONTRIBUTING.md)
        
      • bower.json
        {
          "name": "codemirror",
          "version":"5.2.1",
          "main": ["lib/codemirror.js", "lib/codemirror.css"],
          "ignore": [
            "**/.*",
            "node_modules",
            "components",
            "bin",
            "demo",
            "doc",
            "test",
            "index.html",
            "package.json",
            "mode/*/*test.js",
            "mode/*/*.html"
          ]
        }
        
      • index.html
        <!doctype html>
        
        <title>CodeMirror</title>
        <meta charset="utf-8"/>
        
        <link rel=stylesheet href="lib/codemirror.css">
        <link rel=stylesheet href="doc/docs.css">
        <script src="lib/codemirror.js"></script>
        <script src="mode/xml/xml.js"></script>
        <script src="mode/javascript/javascript.js"></script>
        <script src="mode/css/css.js"></script>
        <script src="mode/htmlmixed/htmlmixed.js"></script>
        <script src="addon/edit/matchbrackets.js"></script>
        
        <script src="doc/activebookmark.js"></script>
        
        <style>
          .CodeMirror { height: auto; border: 1px solid #ddd; }
          .CodeMirror-scroll { max-height: 200px; }
          .CodeMirror pre { padding-left: 7px; line-height: 1.25; }
        </style>
        
        <div id=nav>
          <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="doc/logo.png"></a>
        
          <ul>
            <li><a class=active data-default="true" href="#description">Home</a>
            <li><a href="doc/manual.html">Manual</a>
            <li><a href="https://github.com/codemirror/codemirror">Code</a>
          </ul>
          <ul>
            <li><a href="#features">Features</a>
            <li><a href="#community">Community</a>
            <li><a href="#browsersupport">Browser support</a>
          </ul>
        </div>
        
        <article>
        
        <section id=description class=first>
          <p><strong>CodeMirror</strong> is a versatile text editor
          implemented in JavaScript for the browser. It is specialized for
          editing code, and comes with a number of <a href="mode/index.html">language modes</a> and <a href="doc/manual.html#addons">addons</a>
          that implement more advanced editing functionality.</p>
        
          <p>A rich <a href="doc/manual.html#api">programming API</a> and a
          CSS <a href="doc/manual.html#styling">theming</a> system are
          available for customizing CodeMirror to fit your application, and
          extending it with new functionality.</p>
        </section>
        
        <section id=demo>
          <h2>This is CodeMirror</h2>
          <form style="position: relative; margin-top: .5em;"><textarea id=demotext>
        <!-- Create a simple CodeMirror instance -->
        <link rel="stylesheet" href="lib/codemirror.css">
        <script src="lib/codemirror.js"></script>
        <script>
          var editor = CodeMirror.fromTextArea(myTextarea, {
            lineNumbers: true
          });
        </script></textarea>
          <select id="demolist" onchange="document.location = this.options[this.selectedIndex].value;">
            <option value="#">Other demos...</option>
            <option value="demo/complete.html">Autocompletion</option>
            <option value="demo/folding.html">Code folding</option>
            <option value="demo/theme.html">Themes</option>
            <option value="mode/htmlmixed/index.html">Mixed language modes</option>
            <option value="demo/bidi.html">Bi-directional text</option>
            <option value="demo/variableheight.html">Variable font sizes</option>
            <option value="demo/search.html">Search interface</option>
            <option value="demo/vim.html">Vim bindings</option>
            <option value="demo/emacs.html">Emacs bindings</option>
            <option value="demo/sublime.html">Sublime Text bindings</option>
            <option value="demo/tern.html">Tern integration</option>
            <option value="demo/merge.html">Merge/diff interface</option>
            <option value="demo/fullscreen.html">Full-screen editor</option>
            <option value="demo/simplescrollbars.html">Custom scrollbars</option>
          </select></form>
          <script>
            var editor = CodeMirror.fromTextArea(document.getElementById("demotext"), {
              lineNumbers: true,
              mode: "text/html",
              matchBrackets: true
            });
          </script>
        
          <div class=actions>
            <div class=actionspicture>
              <img src="doc/yinyang.png" class=yinyang>
              <div class="actionlink download">
                <a href="http://codemirror.net/codemirror.zip">DOWNLOAD</a>
              </div>
              <div class="actionlink fund">
                <a href="https://marijnhaverbeke.nl/fund/">FUND</a>
              </div>
            </div>
            <div class=actionsleft>
              Get the current version: <a href="http://codemirror.net/codemirror.zip">5.2</a>.<br>
              You can see the <a href="https://github.com/codemirror/codemirror" title="Github repository">code</a> or<br>
              read the <a href="doc/releases.html">release notes</a>.<br>
              There is a <a href="doc/compress.html">minification helper</a>.
            </div>
            <div class=actionsright>
              Software needs maintenance,<br>
              maintainers need to subsist.<br>
              Current funding status = <img src="https://marijnhaverbeke.nl/fund/status_s.png" title="Current maintainer happiness" style="vertical-align: middle; height: 16px; width: 16px"><br>
              You can help <a href="https://marijnhaverbeke.nl/fund/" title="Set up a monthly contribution">per month</a> or
              <a title="Donate with Paypal" href="javascript:document.getElementById('paypal').submit();">once</a>.
              <form action="https://www.paypal.com/cgi-bin/webscr" method="post" id="paypal">
                <input type="hidden" name="cmd" value="_s-xclick"/>
                <input type="hidden" name="hosted_button_id" value="3FVHS5FGUY7CC"/>
              </form>
            </div>
          </div>
          
        </section>
        
        <section id=features>
          <h2>Features</h2>
          <ul>
            <li>Support for <a href="mode/index.html">over 100 languages</a> out of the box
            <li>A powerful, <a href="mode/htmlmixed/index.html">composable</a> language mode <a href="doc/manual.html#modeapi">system</a>
            <li><a href="doc/manual.html#addon_show-hint">Autocompletion</a> (<a href="demo/xmlcomplete.html">XML</a>)
            <li><a href="doc/manual.html#addon_foldcode">Code folding</a>
            <li><a href="doc/manual.html#option_extraKeys">Configurable</a> keybindings
            <li><a href="demo/vim.html">Vim</a>, <a href="demo/emacs.html">Emacs</a>, and <a href="demo/sublime.html">Sublime Text</a> bindings
            <li><a href="doc/manual.html#addon_search">Search and replace</a> interface
            <li><a href="doc/manual.html#addon_matchbrackets">Bracket</a> and <a href="doc/manual.html#addon_matchtags">tag</a> matching
            <li>Support for <a href="demo/buffers.html">split views</a>
            <li><a href="doc/manual.html#addon_lint">Linter integration</a>
            <li><a href="demo/variableheight.html">Mixing font sizes and styles</a>
            <li><a href="demo/theme.html">Various themes</a>
            <li>Able to <a href="demo/resize.html">resize to fit content</a>
            <li><a href="doc/manual.html#mark_replacedWith">Inline</a> and <a href="doc/manual.html#addLineWidget">block</a> widgets
            <li>Programmable <a href="demo/marker.html">gutters</a>
            <li>Making ranges of text <a href="doc/manual.html#markText">styled, read-only, or atomic</a>
            <li><a href="demo/bidi.html">Bi-directional text</a> support
            <li>Many other <a href="doc/manual.html#api">methods</a> and <a href="doc/manual.html#addons">addons</a>...
          </ul>
        </section>
        
        <section id=community>
          <h2>Community</h2>
        
          <p>CodeMirror is an open-source project shared under
          an <a href="LICENSE">MIT license</a>. It is the editor used in the
          dev tools for
          both <a href="https://hacks.mozilla.org/2013/11/firefox-developer-tools-episode-27-edit-as-html-codemirror-more/">Firefox</a>
          and <a href="https://developers.google.com/chrome-developer-tools/">Chrome</a>, <a href="http://www.lighttable.com/">Light
          Table</a>, <a href="http://brackets.io/">Adobe
          Brackets</a>, <a href="http://blog.bitbucket.org/2013/05/14/edit-your-code-in-the-cloud-with-bitbucket/">Bitbucket</a>,
          and <a href="doc/realworld.html">many other projects</a>.</p>
        
          <p>Development and bug tracking happens
          on <a href="https://github.com/codemirror/CodeMirror/">github</a>
          (<a href="http://marijnhaverbeke.nl/git/codemirror">alternate git
          repository</a>).
          Please <a href="http://codemirror.net/doc/reporting.html">read these
          pointers</a> before submitting a bug. Use pull requests to submit
          patches. All contributions must be released under the same MIT
          license that CodeMirror uses.</p>
        
          <p>Discussion around the project is done on
          a <a href="http://discuss.codemirror.net">discussion forum</a>.
          There is also
          the <a href="http://groups.google.com/group/codemirror-announce">codemirror-announce</a>
          list, which is only used for major announcements (such as new
          versions). If needed, you can
          contact <a href="mailto:marijnh@gmail.com">the maintainer</a>
          directly.</p>
        
          <p>A list of CodeMirror-related software that is not part of the
          main distribution is maintained
          on <a href="https://github.com/codemirror/CodeMirror/wiki/CodeMirror-addons">our
          wiki</a>. Feel free to add your project.</p>
        </section>
        
        <section id=browsersupport>
          <h2>Browser support</h2>
          <p>The <em>desktop</em> versions of the following browsers,
          in <em>standards mode</em> (HTML5 <code>&lt;!doctype html></code>
          recommended) are supported:</p>
          <table style="margin-bottom: 1em">
            <tr><th>Firefox</th><td>version 4 and up</td></tr>
            <tr><th>Chrome</th><td>any version</td></tr>
            <tr><th>Safari</th><td>version 5.2 and up</td></tr>
            <tr><th style="padding-right: 1em;">Internet Explorer</th><td>version 8 and up</td></tr>
            <tr><th>Opera</th><td>version 9 and up</td></tr>
          </table>
          <p>Support for modern mobile browsers is experimental. Recent
          versions of the iOS browser and Chrome on Android should work
          pretty well.</p>
        </section>
        
        </article>
        
      • package.json
        {
            "name": "codemirror",
            "version":"5.2.1",
            "main": "lib/codemirror.js",
            "description": "In-browser code editing made bearable",
            "licenses": [{"type": "MIT",
                          "url": "http://codemirror.net/LICENSE"}],
            "directories": {"lib": "./lib"},
            "scripts": {"test": "node ./test/run.js"},
            "devDependencies": {"node-static": "0.6.0",
                                "phantomjs": "1.9.2-5",
                                "blint": ">=0.1.1"},
            "bugs": "http://github.com/codemirror/CodeMirror/issues",
            "keywords": ["JavaScript", "CodeMirror", "Editor"],
            "homepage": "http://codemirror.net",
            "maintainers":[{"name": "Marijn Haverbeke",
                            "email": "marijnh@gmail.com",
                            "web": "http://marijnhaverbeke.nl"}],
            "repository": {"type": "git",
                           "url": "https://github.com/codemirror/CodeMirror.git"}
        }
        
    • es5-shim
      • es5-sham.min.js
        /*!
         * https://github.com/es-shims/es5-shim
         * @license es5-shim Copyright 2009-2014 by contributors, MIT License
         * see https://github.com/es-shims/es5-shim/blob/v4.0.6/LICENSE
         */
        (function(e,t){"use strict";if(typeof define==="function"&&define.amd){define(t)}else if(typeof exports==="object"){module.exports=t()}else{e.returnExports=t()}})(this,function(){var e=Function.prototype.call;var t=Object.prototype;var r=e.bind(t.hasOwnProperty);var n;var o;var c;var i;var f=r(t,"__defineGetter__");if(f){n=e.bind(t.__defineGetter__);o=e.bind(t.__defineSetter__);c=e.bind(t.__lookupGetter__);i=e.bind(t.__lookupSetter__)}if(!Object.getPrototypeOf){Object.getPrototypeOf=function E(e){var r=e.__proto__;if(r||r===null){return r}else if(e.constructor){return e.constructor.prototype}else{return t}}}function l(e){try{e.sentinel=0;return Object.getOwnPropertyDescriptor(e,"sentinel").value===0}catch(t){}}if(Object.defineProperty){var u=l({});var a=typeof document==="undefined"||l(document.createElement("div"));if(!a||!u){var p=Object.getOwnPropertyDescriptor}}if(!Object.getOwnPropertyDescriptor||p){var b="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function g(e,n){if(typeof e!=="object"&&typeof e!=="function"||e===null){throw new TypeError(b+e)}if(p){try{return p.call(Object,e,n)}catch(o){}}var l;if(!r(e,n)){return l}l={enumerable:true,configurable:true};if(f){var u=e.__proto__;var a=e!==t;if(a){e.__proto__=t}var s=c(e,n);var O=i(e,n);if(a){e.__proto__=u}if(s||O){if(s){l.get=s}if(O){l.set=O}return l}}l.value=e[n];l.writable=true;return l}}if(!Object.getOwnPropertyNames){Object.getOwnPropertyNames=function T(e){return Object.keys(e)}}if(!Object.create){var s;var O=!({__proto__:null}instanceof Object);if(O||typeof document==="undefined"){s=function(){return{__proto__:null}}}else{s=function(){var e=document.createElement("iframe");var t=document.body||document.documentElement;e.style.display="none";t.appendChild(e);e.src="javascript:";var r=e.contentWindow.Object.prototype;t.removeChild(e);e=null;delete r.constructor;delete r.hasOwnProperty;delete r.propertyIsEnumerable;delete r.isPrototypeOf;delete r.toLocaleString;delete r.toString;delete r.valueOf;r.__proto__=null;function n(){}n.prototype=r;s=function(){return new n};return new n}}Object.create=function x(e,t){var r;function n(){}if(e===null){r=s()}else{if(typeof e!=="object"&&typeof e!=="function"){throw new TypeError("Object prototype may only be an Object or null")}n.prototype=e;r=new n;r.__proto__=e}if(t!==void 0){Object.defineProperties(r,t)}return r}}function j(e){try{Object.defineProperty(e,"sentinel",{});return"sentinel"in e}catch(t){}}if(Object.defineProperty){var d=j({});var y=typeof document==="undefined"||j(document.createElement("div"));if(!d||!y){var _=Object.defineProperty,v=Object.defineProperties}}if(!Object.defineProperty||_){var w="Property description must be an object: ";var P="Object.defineProperty called on non-object: ";var h="getters & setters can not be defined on this javascript engine";Object.defineProperty=function z(e,r,l){if(typeof e!=="object"&&typeof e!=="function"||e===null){throw new TypeError(P+e)}if(typeof l!=="object"&&typeof l!=="function"||l===null){throw new TypeError(w+l)}if(_){try{return _.call(Object,e,r,l)}catch(u){}}if("value"in l){if(f&&(c(e,r)||i(e,r))){var a=e.__proto__;e.__proto__=t;delete e[r];e[r]=l.value;e.__proto__=a}else{e[r]=l.value}}else{if(!f){throw new TypeError(h)}if("get"in l){n(e,r,l.get)}if("set"in l){o(e,r,l.set)}}return e}}if(!Object.defineProperties||v){Object.defineProperties=function S(e,t){if(v){try{return v.call(Object,e,t)}catch(n){}}for(var o in t){if(r(t,o)&&o!=="__proto__"){Object.defineProperty(e,o,t[o])}}return e}}if(!Object.seal){Object.seal=function D(e){if(Object(e)!==e){throw new TypeError("Object.seal can only be called on Objects.")}return e}}if(!Object.freeze){Object.freeze=function F(e){if(Object(e)!==e){throw new TypeError("Object.freeze can only be called on Objects.")}return e}}try{Object.freeze(function(){})}catch(m){Object.freeze=function k(e){return function t(r){if(typeof r==="function"){return r}else{return e(r)}}}(Object.freeze)}if(!Object.preventExtensions){Object.preventExtensions=function G(e){if(Object(e)!==e){throw new TypeError("Object.preventExtensions can only be called on Objects.")}return e}}if(!Object.isSealed){Object.isSealed=function C(e){if(Object(e)!==e){throw new TypeError("Object.isSealed can only be called on Objects.")}return false}}if(!Object.isFrozen){Object.isFrozen=function N(e){if(Object(e)!==e){throw new TypeError("Object.isFrozen can only be called on Objects.")}return false}}if(!Object.isExtensible){Object.isExtensible=function I(e){if(Object(e)!==e){throw new TypeError("Object.isExtensible can only be called on Objects.")}var t="";while(r(e,t)){t+="?"}e[t]=true;var n=r(e,t);delete e[t];return n}}});
        
      • es5-shim.min.js
        /*!
         * https://github.com/es-shims/es5-shim
         * @license es5-shim Copyright 2009-2014 by contributors, MIT License
         * see https://github.com/es-shims/es5-shim/blob/v4.0.6/LICENSE
         */
        (function(t,e){"use strict";if(typeof define==="function"&&define.amd){define(e)}else if(typeof exports==="object"){module.exports=e()}else{t.returnExports=e()}})(this,function(){var t=Array.prototype;var e=Object.prototype;var r=Function.prototype;var n=String.prototype;var i=Number.prototype;var a=t.slice;var o=t.splice;var u=t.push;var l=t.unshift;var s=r.call;var f=e.toString;var c=function(t){return f.call(t)==="[object Function]"};var p=function(t){return f.call(t)==="[object RegExp]"};var h=function ue(t){return f.call(t)==="[object Array]"};var v=function le(t){return f.call(t)==="[object String]"};var g=function se(t){var e=f.call(t);var r=e==="[object Arguments]";if(!r){r=!h(t)&&t!==null&&typeof t==="object"&&typeof t.length==="number"&&t.length>=0&&c(t.callee)}return r};var y=function(t){var e=Object.defineProperty&&function(){try{Object.defineProperty({},"x",{});return true}catch(t){return false}}();var r;if(e){r=function(t,e,r,n){if(!n&&e in t){return}Object.defineProperty(t,e,{configurable:true,enumerable:false,writable:true,value:r})}}else{r=function(t,e,r,n){if(!n&&e in t){return}t[e]=r}}return function n(e,i,a){for(var o in i){if(t.call(i,o)){r(e,o,i[o],a)}}}}(e.hasOwnProperty);function d(t){var e=+t;if(e!==e){e=0}else if(e!==0&&e!==1/0&&e!==-(1/0)){e=(e>0||-1)*Math.floor(Math.abs(e))}return e}function m(t){var e=typeof t;return t===null||e==="undefined"||e==="boolean"||e==="number"||e==="string"}function b(t){var e,r,n;if(m(t)){return t}r=t.valueOf;if(c(r)){e=r.call(t);if(m(e)){return e}}n=t.toString;if(c(n)){e=n.call(t);if(m(e)){return e}}throw new TypeError}var w={ToObject:function(t){if(t==null){throw new TypeError("can't convert "+t+" to object")}return Object(t)},ToUint32:function fe(t){return t>>>0}};var x=function ce(){};y(r,{bind:function pe(t){var e=this;if(!c(e)){throw new TypeError("Function.prototype.bind called on incompatible "+e)}var r=a.call(arguments,1);var n;var i=function(){if(this instanceof n){var i=e.apply(this,r.concat(a.call(arguments)));if(Object(i)===i){return i}return this}else{return e.apply(t,r.concat(a.call(arguments)))}};var o=Math.max(0,e.length-r.length);var u=[];for(var l=0;l<o;l++){u.push("$"+l)}n=Function("binder","return function ("+u.join(",")+"){ return binder.apply(this, arguments); }")(i);if(e.prototype){x.prototype=e.prototype;n.prototype=new x;x.prototype=null}return n}});var O=s.bind(e.hasOwnProperty);var T=function(){var t=[1,2];var e=t.splice();return t.length===2&&h(e)&&e.length===0}();y(t,{splice:function he(t,e){if(arguments.length===0){return[]}else{return o.apply(this,arguments)}}},!T);var j=function(){var e={};t.splice.call(e,0,0,1);return e.length===1}();y(t,{splice:function ve(t,e){if(arguments.length===0){return[]}var r=arguments;this.length=Math.max(d(this.length),0);if(arguments.length>0&&typeof e!=="number"){r=a.call(arguments);if(r.length<2){r.push(this.length-t)}else{r[1]=d(e)}}return o.apply(this,r)}},!j);var S=[].unshift(0)!==1;y(t,{unshift:function(){l.apply(this,arguments);return this.length}},S);y(Array,{isArray:h});var E=Object("a");var N=E[0]!=="a"||!(0 in E);var I=function ge(t){var e=true;var r=true;if(t){t.call("foo",function(t,r,n){if(typeof n!=="object"){e=false}});t.call([1],function(){"use strict";r=typeof this==="string"},"x")}return!!t&&e&&r};y(t,{forEach:function ye(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=arguments[1],i=-1,a=r.length>>>0;if(!c(t)){throw new TypeError}while(++i<a){if(i in r){t.call(n,r[i],i,e)}}}},!I(t.forEach));y(t,{map:function de(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=r.length>>>0,i=Array(n),a=arguments[1];if(!c(t)){throw new TypeError(t+" is not a function")}for(var o=0;o<n;o++){if(o in r){i[o]=t.call(a,r[o],o,e)}}return i}},!I(t.map));y(t,{filter:function me(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=r.length>>>0,i=[],a,o=arguments[1];if(!c(t)){throw new TypeError(t+" is not a function")}for(var u=0;u<n;u++){if(u in r){a=r[u];if(t.call(o,a,u,e)){i.push(a)}}}return i}},!I(t.filter));y(t,{every:function be(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=r.length>>>0,i=arguments[1];if(!c(t)){throw new TypeError(t+" is not a function")}for(var a=0;a<n;a++){if(a in r&&!t.call(i,r[a],a,e)){return false}}return true}},!I(t.every));y(t,{some:function we(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=r.length>>>0,i=arguments[1];if(!c(t)){throw new TypeError(t+" is not a function")}for(var a=0;a<n;a++){if(a in r&&t.call(i,r[a],a,e)){return true}}return false}},!I(t.some));var D=false;if(t.reduce){D=typeof t.reduce.call("es5",function(t,e,r,n){return n})==="object"}y(t,{reduce:function xe(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=r.length>>>0;if(!c(t)){throw new TypeError(t+" is not a function")}if(!n&&arguments.length===1){throw new TypeError("reduce of empty array with no initial value")}var i=0;var a;if(arguments.length>=2){a=arguments[1]}else{do{if(i in r){a=r[i++];break}if(++i>=n){throw new TypeError("reduce of empty array with no initial value")}}while(true)}for(;i<n;i++){if(i in r){a=t.call(void 0,a,r[i],i,e)}}return a}},!D);var M=false;if(t.reduceRight){M=typeof t.reduceRight.call("es5",function(t,e,r,n){return n})==="object"}y(t,{reduceRight:function Oe(t){var e=w.ToObject(this),r=N&&v(this)?this.split(""):e,n=r.length>>>0;if(!c(t)){throw new TypeError(t+" is not a function")}if(!n&&arguments.length===1){throw new TypeError("reduceRight of empty array with no initial value")}var i,a=n-1;if(arguments.length>=2){i=arguments[1]}else{do{if(a in r){i=r[a--];break}if(--a<0){throw new TypeError("reduceRight of empty array with no initial value")}}while(true)}if(a<0){return i}do{if(a in r){i=t.call(void 0,i,r[a],a,e)}}while(a--);return i}},!M);var F=Array.prototype.indexOf&&[0,1].indexOf(1,2)!==-1;y(t,{indexOf:function Te(t){var e=N&&v(this)?this.split(""):w.ToObject(this),r=e.length>>>0;if(!r){return-1}var n=0;if(arguments.length>1){n=d(arguments[1])}n=n>=0?n:Math.max(0,r+n);for(;n<r;n++){if(n in e&&e[n]===t){return n}}return-1}},F);var R=Array.prototype.lastIndexOf&&[0,1].lastIndexOf(0,-3)!==-1;y(t,{lastIndexOf:function je(t){var e=N&&v(this)?this.split(""):w.ToObject(this),r=e.length>>>0;if(!r){return-1}var n=r-1;if(arguments.length>1){n=Math.min(n,d(arguments[1]))}n=n>=0?n:r-Math.abs(n);for(;n>=0;n--){if(n in e&&t===e[n]){return n}}return-1}},R);var U=!{toString:null}.propertyIsEnumerable("toString"),k=function(){}.propertyIsEnumerable("prototype"),C=!O("x","0"),A=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],P=A.length;y(Object,{keys:function Se(t){var e=c(t),r=g(t),n=t!==null&&typeof t==="object",i=n&&v(t);if(!n&&!e&&!r){throw new TypeError("Object.keys called on a non-object")}var a=[];var o=k&&e;if(i&&C||r){for(var u=0;u<t.length;++u){a.push(String(u))}}if(!r){for(var l in t){if(!(o&&l==="prototype")&&O(t,l)){a.push(String(l))}}}if(U){var s=t.constructor,f=s&&s.prototype===t;for(var p=0;p<P;p++){var h=A[p];if(!(f&&h==="constructor")&&O(t,h)){a.push(h)}}}return a}});var Z=Object.keys&&function(){return Object.keys(arguments).length===2}(1,2);var J=Object.keys;y(Object,{keys:function Ee(e){if(g(e)){return J(t.slice.call(e))}else{return J(e)}}},!Z);var z=-621987552e5;var $="-000001";var B=Date.prototype.toISOString&&new Date(z).toISOString().indexOf($)===-1;y(Date.prototype,{toISOString:function Ne(){var t,e,r,n,i;if(!isFinite(this)){throw new RangeError("Date.prototype.toISOString called on non-finite value.")}n=this.getUTCFullYear();i=this.getUTCMonth();n+=Math.floor(i/12);i=(i%12+12)%12;t=[i+1,this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()];n=(n<0?"-":n>9999?"+":"")+("00000"+Math.abs(n)).slice(0<=n&&n<=9999?-4:-6);e=t.length;while(e--){r=t[e];if(r<10){t[e]="0"+r}}return n+"-"+t.slice(0,2).join("-")+"T"+t.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"}},B);var H=false;try{H=Date.prototype.toJSON&&new Date(NaN).toJSON()===null&&new Date(z).toJSON().indexOf($)!==-1&&Date.prototype.toJSON.call({toISOString:function(){return true}})}catch(L){}if(!H){Date.prototype.toJSON=function Ie(t){var e=Object(this),r=b(e),n;if(typeof r==="number"&&!isFinite(r)){return null}n=e.toISOString;if(typeof n!=="function"){throw new TypeError("toISOString property is not callable")}return n.call(e)}}var X=Date.parse("+033658-09-27T01:46:40.000Z")===1e15;var Y=!isNaN(Date.parse("2012-04-04T24:00:00.500Z"))||!isNaN(Date.parse("2012-11-31T23:59:59.000Z"));var q=isNaN(Date.parse("2000-01-01T00:00:00.000Z"));if(!Date.parse||q||Y||!X){Date=function(t){function e(r,n,i,a,o,u,l){var s=arguments.length;if(this instanceof t){var f=s===1&&String(r)===r?new t(e.parse(r)):s>=7?new t(r,n,i,a,o,u,l):s>=6?new t(r,n,i,a,o,u):s>=5?new t(r,n,i,a,o):s>=4?new t(r,n,i,a):s>=3?new t(r,n,i):s>=2?new t(r,n):s>=1?new t(r):new t;f.constructor=e;return f}return t.apply(this,arguments)}var r=new RegExp("^"+"(\\d{4}|[+-]\\d{6})"+"(?:-(\\d{2})"+"(?:-(\\d{2})"+"(?:"+"T(\\d{2})"+":(\\d{2})"+"(?:"+":(\\d{2})"+"(?:(\\.\\d{1,}))?"+")?"+"("+"Z|"+"(?:"+"([-+])"+"(\\d{2})"+":(\\d{2})"+")"+")?)?)?)?"+"$");var n=[0,31,59,90,120,151,181,212,243,273,304,334,365];function i(t,e){var r=e>1?1:0;return n[e]+Math.floor((t-1969+r)/4)-Math.floor((t-1901+r)/100)+Math.floor((t-1601+r)/400)+365*(t-1970)}function a(e){return Number(new t(1970,0,1,0,0,0,e))}for(var o in t){e[o]=t[o]}e.now=t.now;e.UTC=t.UTC;e.prototype=t.prototype;e.prototype.constructor=e;e.parse=function u(e){var n=r.exec(e);if(n){var o=Number(n[1]),u=Number(n[2]||1)-1,l=Number(n[3]||1)-1,s=Number(n[4]||0),f=Number(n[5]||0),c=Number(n[6]||0),p=Math.floor(Number(n[7]||0)*1e3),h=Boolean(n[4]&&!n[8]),v=n[9]==="-"?1:-1,g=Number(n[10]||0),y=Number(n[11]||0),d;if(s<(f>0||c>0||p>0?24:25)&&f<60&&c<60&&p<1e3&&u>-1&&u<12&&g<24&&y<60&&l>-1&&l<i(o,u+1)-i(o,u)){d=((i(o,u)+l)*24+s+g*v)*60;d=((d+f+y*v)*60+c)*1e3+p;if(h){d=a(d)}if(-864e13<=d&&d<=864e13){return d}}return NaN}return t.parse.apply(this,arguments)};return e}(Date)}if(!Date.now){Date.now=function De(){return(new Date).getTime()}}var G=i.toFixed&&(8e-5.toFixed(3)!=="0.000"||.9.toFixed(0)!=="1"||1.255.toFixed(2)!=="1.25"||0xde0b6b3a7640080.toFixed(0)!=="1000000000000000128");var K={base:1e7,size:6,data:[0,0,0,0,0,0],multiply:function Me(t,e){var r=-1;while(++r<K.size){e+=t*K.data[r];K.data[r]=e%K.base;e=Math.floor(e/K.base)}},divide:function Fe(t){var e=K.size,r=0;while(--e>=0){r+=K.data[e];K.data[e]=Math.floor(r/t);r=r%t*K.base}},numToString:function Re(){var t=K.size;var e="";while(--t>=0){if(e!==""||t===0||K.data[t]!==0){var r=String(K.data[t]);if(e===""){e=r}else{e+="0000000".slice(0,7-r.length)+r}}}return e},pow:function Ue(t,e,r){return e===0?r:e%2===1?Ue(t,e-1,r*t):Ue(t*t,e/2,r)},log:function ke(t){var e=0;while(t>=4096){e+=12;t/=4096}while(t>=2){e+=1;t/=2}return e}};y(i,{toFixed:function Ce(t){var e,r,n,i,a,o,u,l;e=Number(t);e=e!==e?0:Math.floor(e);if(e<0||e>20){throw new RangeError("Number.toFixed called with invalid number of decimals")}r=Number(this);if(r!==r){return"NaN"}if(r<=-1e21||r>=1e21){return String(r)}n="";if(r<0){n="-";r=-r}i="0";if(r>1e-21){a=K.log(r*K.pow(2,69,1))-69;o=a<0?r*K.pow(2,-a,1):r/K.pow(2,a,1);o*=4503599627370496;a=52-a;if(a>0){K.multiply(0,o);u=e;while(u>=7){K.multiply(1e7,0);u-=7}K.multiply(K.pow(10,u,1),0);u=a-1;while(u>=23){K.divide(1<<23);u-=23}K.divide(1<<u);K.multiply(1,1);K.divide(2);i=K.numToString()}else{K.multiply(0,o);K.multiply(1<<-a,0);i=K.numToString()+"0.00000000000000000000".slice(2,2+e)}}if(e>0){l=i.length;if(l<=e){i=n+"0.0000000000000000000".slice(0,e-l+2)+i}else{i=n+i.slice(0,l-e)+"."+i.slice(l-e)}}else{i=n+i}return i}},G);var Q=n.split;if("ab".split(/(?:ab)*/).length!==2||".".split(/(.?)(.?)/).length!==4||"tesst".split(/(s)*/)[1]==="t"||"test".split(/(?:)/,-1).length!==4||"".split(/.?/).length||".".split(/()()/).length>1){(function(){var t=typeof/()??/.exec("")[1]==="undefined";n.split=function(e,r){var n=this;if(typeof e==="undefined"&&r===0){return[]}if(f.call(e)!=="[object RegExp]"){return Q.call(this,e,r)}var i=[],a=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.extended?"x":"")+(e.sticky?"y":""),o=0,l,s,c,p;e=new RegExp(e.source,a+"g");n+="";if(!t){l=new RegExp("^"+e.source+"$(?!\\s)",a)}r=typeof r==="undefined"?-1>>>0:w.ToUint32(r);s=e.exec(n);while(s){c=s.index+s[0].length;if(c>o){i.push(n.slice(o,s.index));if(!t&&s.length>1){s[0].replace(l,function(){for(var t=1;t<arguments.length-2;t++){if(typeof arguments[t]==="undefined"){s[t]=void 0}}})}if(s.length>1&&s.index<n.length){u.apply(i,s.slice(1))}p=s[0].length;o=c;if(i.length>=r){break}}if(e.lastIndex===s.index){e.lastIndex++}s=e.exec(n)}if(o===n.length){if(p||!e.test("")){i.push("")}}else{i.push(n.slice(o))}return i.length>r?i.slice(0,r):i}})()}else if("0".split(void 0,0).length){n.split=function Ae(t,e){if(typeof t==="undefined"&&e===0){return[]}return Q.call(this,t,e)}}var V=n.replace;var W=function(){var t=[];"x".replace(/x(.)?/g,function(e,r){t.push(r)});return t.length===1&&typeof t[0]==="undefined"}();if(!W){n.replace=function Pe(t,e){var r=c(e);var n=p(t)&&/\)[*?]/.test(t.source);if(!r||!n){return V.call(this,t,e)}else{var i=function(r){var n=arguments.length;var i=t.lastIndex;t.lastIndex=0;var a=t.exec(r)||[];t.lastIndex=i;a.push(arguments[n-2],arguments[n-1]);return e.apply(this,a)};return V.call(this,t,i)}}}var _=n.substr;var te="".substr&&"0b".substr(-1)!=="b";y(n,{substr:function Ze(t,e){return _.call(this,t<0?(t=this.length+t)<0?0:t:t,e)}},te);var ee="	\n\f\r \xa0\u1680\u180e\u2000\u2001\u2002\u2003"+"\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028"+"\u2029\ufeff";var re="\u200b";var ne="["+ee+"]";var ie=new RegExp("^"+ne+ne+"*");var ae=new RegExp(ne+ne+"*$");var oe=n.trim&&(ee.trim()||!re.trim());y(n,{trim:function Je(){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}return String(this).replace(ie,"").replace(ae,"")}},oe);if(parseInt(ee+"08")!==8||parseInt(ee+"0x16")!==22){parseInt=function(t){var e=/^0[xX]/;return function r(n,i){n=String(n).trim();if(!Number(i)){i=e.test(n)?16:10}return t(n,i)}}(parseInt)}});
        
    • github
      • github.js
        /*!
         * @overview  Github.js
         *
         * @copyright (c) 2013 Michael Aufreiter, Development Seed
         *            Github.js is freely distributable.
         *
         * @license   Licensed under MIT license
         *
         *            For all details and documentation:
         *            http://substance.io/michael/github
         */
        
        (function() {
        
          // Initial Setup
          // -------------
        
          var XMLHttpRequest,  _;
          if (typeof exports !== 'undefined') {
              XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
              _ = require('underscore');
              btoa = require('btoa');
          } else {
              _ = window._;
          }
          //prefer native XMLHttpRequest always
          if (typeof window !== 'undefined' && typeof window.XMLHttpRequest !== 'undefined'){
              XMLHttpRequest = window.XMLHttpRequest;
          }
        
        
          var API_URL = 'https://api.github.com';
        
          var Github = function(options) {
        
            // HTTP Request Abstraction
            // =======
            //
            // I'm not proud of this and neither should you be if you were responsible for the XMLHttpRequest spec.
        
            function _request(method, path, data, cb, raw, sync) {
              function getURL() {
                var url = path.indexOf('//') >= 0 ? path : API_URL + path;
                return url + ((/\?/).test(url) ? "&" : "?") + (new Date()).getTime();
              }
        
              var xhr = new XMLHttpRequest();
              if (!raw) {xhr.dataType = "json";}
        
              xhr.open(method, getURL(), !sync);
              if (!sync) {
                xhr.onreadystatechange = function () {
                  if (this.readyState == 4) {
                    if (this.status >= 200 && this.status < 300 || this.status === 304) {
                      cb(null, raw ? this.responseText : this.responseText ? JSON.parse(this.responseText) : true, this);
                    } else {
                      cb({path: path, request: this, error: this.status});
                    }
                  }
                };
              }
              xhr.setRequestHeader('Accept','application/vnd.github.v3.raw+json');
              xhr.setRequestHeader('Content-Type','application/json;charset=UTF-8');
              if ((options.token) || (options.username && options.password)) {
                var authorization = options.token ? 'token ' + options.token : 'Basic ' + btoa(options.username + ':' + options.password);
                xhr.setRequestHeader('Authorization', authorization);
              }
              if (data)
                xhr.send(JSON.stringify(data));
              else
                xhr.send();
              if (sync) return xhr.response;
            }
        
            function _requestAllPages(path, cb) {
              var results = [];
              (function iterate() {
                _request("GET", path, null, function(err, res, xhr) {
                  if (err) {
                    return cb(err);
                  }
        
                  results.push.apply(results, res);
        
                  var links = (xhr.getResponseHeader('link') || '').split(/\s*,\s*/g),
                      next = _.find(links, function(link) { return /rel="next"/.test(link); });
        
                  if (next) {
                    next = (/<(.*)>/.exec(next) || [])[1];
                  }
        
                  if (!next) {
                    cb(err, results);
                  } else {
                    path = next;
                    iterate();
                  }
                });
              })();
            }
        
        
            // User API
            // =======
        
            Github.User = function() {
              this.repos = function(cb) {
                // Github does not always honor the 1000 limit so we want to iterate over the data set.
                _requestAllPages("/user/repos?type=all&per_page=1000&sort=updated", function(err, res) {
                  cb(err, res);
                });
              };
        
              // List user organizations
              // -------
        
              this.orgs = function(cb) {
                _request("GET", "/user/orgs", null, function(err, res) {
                  cb(err, res);
                });
              };
        
              // List authenticated user's gists
              // -------
        
              this.gists = function(cb) {
                _request("GET", "/gists", null, function(err, res) {
                  cb(err,res);
                });
              };
        
              // List authenticated user's unread notifications
              // -------
        
              this.notifications = function(cb) {
                _request("GET", "/notifications", null, function(err, res) {
                  cb(err,res);
                });
              };
        
              // Show user information
              // -------
        
              this.show = function(username, cb) {
                var command = username ? "/users/"+username : "/user";
        
                _request("GET", command, null, function(err, res) {
                  cb(err, res);
                });
              };
        
              // List user repositories
              // -------
        
              this.userRepos = function(username, cb) {
                // Github does not always honor the 1000 limit so we want to iterate over the data set.
                _requestAllPages("/users/"+username+"/repos?type=all&per_page=1000&sort=updated", function(err, res) {
                  cb(err, res);
                });
              };
        
              // List a user's gists
              // -------
        
              this.userGists = function(username, cb) {
                _request("GET", "/users/"+username+"/gists", null, function(err, res) {
                  cb(err,res);
                });
              };
        
              // List organization repositories
              // -------
        
              this.orgRepos = function(orgname, cb) {
                // Github does not always honor the 1000 limit so we want to iterate over the data set.
                _requestAllPages("/orgs/"+orgname+"/repos?type=all&&page_num=1000&sort=updated&direction=desc", function(err, res) {
                  cb(err, res);
                });
              };
        
              // Follow user
              // -------
        
              this.follow = function(username, cb) {
                _request("PUT", "/user/following/"+username, null, function(err, res) {
                  cb(err, res);
                });
              };
        
              // Unfollow user
              // -------
        
              this.unfollow = function(username, cb) {
                _request("DELETE", "/user/following/"+username, null, function(err, res) {
                  cb(err, res);
                });
              };
        
              // Create a repo
              // -------
              this.createRepo = function(options, cb) {
                _request("POST", "/user/repos", options, cb);
              };
        
            };
        
            // Repository API
            // =======
        
            Github.Repository = function(options) {
              var repo = options.name;
              var user = options.user;
        
              var that = this;
              var repoPath = "/repos/" + user + "/" + repo;
        
              var currentTree = {
                "branch": null,
                "sha": null
              };
        
        
              // Delete a repo
              // --------
        
              this.deleteRepo = function(cb) {
                _request("DELETE", repoPath, options, cb);
              };
        
              // Uses the cache if branch has not been changed
              // -------
        
              function updateTree(branch, cb) {
                if (branch === currentTree.branch && currentTree.sha) return cb(null, currentTree.sha);
                that.getRef("heads/"+branch, function(err, sha) {
                  currentTree.branch = branch;
                  currentTree.sha = sha;
                  cb(err, sha);
                });
              }
        
              // Get a particular reference
              // -------
        
              this.getRef = function(ref, cb) {
                _request("GET", repoPath + "/git/refs/" + ref, null, function(err, res) {
                  if (err) return cb(err);
                  cb(null, res.object.sha);
                });
              };
        
              // Create a new reference
              // --------
              //
              // {
              //   "ref": "refs/heads/my-new-branch-name",
              //   "sha": "827efc6d56897b048c772eb4087f854f46256132"
              // }
        
              this.createRef = function(options, cb) {
                _request("POST", repoPath + "/git/refs", options, cb);
              };
        
              // Delete a reference
              // --------
              //
              // repo.deleteRef('heads/gh-pages')
              // repo.deleteRef('tags/v1.0')
        
              this.deleteRef = function(ref, cb) {
                _request("DELETE", repoPath + "/git/refs/"+ref, options, cb);
              };
        
              // Create a repo
              // -------
        
              this.createRepo = function(options, cb) {
                _request("POST", "/user/repos", options, cb);
              };
        
              // Delete a repo
              // --------
        
              this.deleteRepo = function(cb) {
                _request("DELETE", repoPath, options, cb);
              };
        
              // List all tags of a repository
              // -------
        
              this.listTags = function(cb) {
                _request("GET", repoPath + "/tags", null, function(err, tags) {
                  if (err) return cb(err);
                  cb(null, tags);
                });
              };
        
              // List all pull requests of a respository
              // -------
        
              this.listPulls = function(state, cb) {
                _request("GET", repoPath + "/pulls" + (state ? '?state=' + state : ''), null, function(err, pulls) {
                  if (err) return cb(err);
                  cb(null, pulls);
                });
              };
        
              // Gets details for a specific pull request
              // -------
        
              this.getPull = function(number, cb) {
                _request("GET", repoPath + "/pulls/" + number, null, function(err, pull) {
                  if (err) return cb(err);
                  cb(null, pull);
                });
              };
        
              // Retrieve the changes made between base and head
              // -------
        
              this.compare = function(base, head, cb) {
                _request("GET", repoPath + "/compare/" + base + "..." + head, null, function(err, diff) {
                  if (err) return cb(err);
                  cb(null, diff);
                });
              };
        
              // List all branches of a repository
              // -------
        
              this.listBranches = function(cb) {
                _request("GET", repoPath + "/git/refs/heads", null, function(err, heads) {
                  if (err) return cb(err);
                  cb(null, _.map(heads, function(head) { return _.last(head.ref.split('/')); }));
                });
              };
        
              // Retrieve the contents of a blob
              // -------
        
              this.getBlob = function(sha, cb) {
                _request("GET", repoPath + "/git/blobs/" + sha, null, cb, 'raw');
              };
        
              // For a given file path, get the corresponding sha (blob for files, tree for dirs)
              // -------
        
              this.getSha = function(branch, path, cb) {
                if (!path || path === "") return that.getRef("heads/"+branch, cb);
                _request("GET", repoPath + "/contents/"+path, {ref: branch}, function(err, pathContent) {
                  if (err) return cb(err);
                  cb(null, pathContent.sha);
                });
              };
        
              // Retrieve the tree a commit points to
              // -------
        
              this.getTree = function(tree, cb) {
                _request("GET", repoPath + "/git/trees/"+tree, null, function(err, res) {
                  if (err) return cb(err);
                  cb(null, res.tree);
                });
              };
        
              // Post a new blob object, getting a blob SHA back
              // -------
        
              this.postBlob = function(content, cb) {
                if (typeof(content) === "string") {
                  content = {
                    "content": content,
                    "encoding": "utf-8"
                  };
                } else {
                  	content = {
                      "content": btoa(String.fromCharCode.apply(null, new Uint8Array(content))),
                      "encoding": "base64"
                    };
                  }
        
                _request("POST", repoPath + "/git/blobs", content, function(err, res) {
                  if (err) return cb(err);
                  cb(null, res.sha);
                });
              };
        
              // Update an existing tree adding a new blob object getting a tree SHA back
              // -------
        
              this.updateTree = function(baseTree, path, blob, cb) {
                var data = {
                  "base_tree": baseTree,
                  "tree": [
                    {
                      "path": path,
                      "mode": "100644",
                      "type": "blob",
                      "sha": blob
                    }
                  ]
                };
                _request("POST", repoPath + "/git/trees", data, function(err, res) {
                  if (err) return cb(err);
                  cb(null, res.sha);
                });
              };
        
              // Post a new tree object having a file path pointer replaced
              // with a new blob SHA getting a tree SHA back
              // -------
        
              this.postTree = function(tree, cb) {
                _request("POST", repoPath + "/git/trees", { "tree": tree }, function(err, res) {
                  if (err) return cb(err);
                  cb(null, res.sha);
                });
              };
        
              // Create a new commit object with the current commit SHA as the parent
              // and the new tree SHA, getting a commit SHA back
              // -------
        
              this.commit = function(parent, tree, message, cb) {
                var user = new Github.User();
                user.show(null, function(err, userData){
                  if (err) return cb(err);
                  var data = {
                    "message": message,
                    "author": {
                      "name": options.user,
                      "email": userData.email
                    },
                    "parents": [
                      parent
                    ],
                    "tree": tree
                  };
                  _request("POST", repoPath + "/git/commits", data, function(err, res) {
                    if (err) return cb(err);
                    currentTree.sha = res.sha; // update latest commit
                    cb(null, res.sha);
                  });
                });
              };
        
              // Update the reference of your head to point to the new commit SHA
              // -------
        
              this.updateHead = function(head, commit, cb) {
                _request("PATCH", repoPath + "/git/refs/heads/" + head, { "sha": commit }, function(err, res) {
                  cb(err);
                });
              };
        
              // Show repository information
              // -------
        
              this.show = function(cb) {
                _request("GET", repoPath, null, cb);
              };
        
              // Get contents
              // --------
        
              this.contents = function(ref, path, cb) {
                _request("GET", repoPath + "/contents/"+path, { ref: ref }, cb);
              };
        
              // Fork repository
              // -------
        
              this.fork = function(cb) {
                _request("POST", repoPath + "/forks", null, cb);
              };
        
              // Branch repository
              // --------
        
              this.branch = function(oldBranch,newBranch,cb) {
                if(arguments.length === 2 && typeof arguments[1] === "function") {
                  cb = newBranch;
                  newBranch = oldBranch;
                  oldBranch = "master";
                }
                this.getRef("heads/" + oldBranch, function(err,ref) {
                  if(err && cb) return cb(err);
                  that.createRef({
                    ref: "refs/heads/" + newBranch,
                    sha: ref
                  },cb);
                });
              };
        
              // Create pull request
              // --------
        
              this.createPullRequest = function(options, cb) {
                _request("POST", repoPath + "/pulls", options, cb);
              };
        
              // List hooks
              // --------
        
              this.listHooks = function(cb) {
                _request("GET", repoPath + "/hooks", null, cb);
              };
        
              // Get a hook
              // --------
        
              this.getHook = function(id, cb) {
                _request("GET", repoPath + "/hooks/" + id, null, cb);
              };
        
              // Create a hook
              // --------
        
              this.createHook = function(options, cb) {
                _request("POST", repoPath + "/hooks", options, cb);
              };
        
              // Edit a hook
              // --------
        
              this.editHook = function(id, options, cb) {
                _request("PATCH", repoPath + "/hooks/" + id, options, cb);
              };
        
              // Delete a hook
              // --------
        
              this.deleteHook = function(id, cb) {
                _request("DELETE", repoPath + "/hooks/" + id, null, cb);
              };
        
              // Read file at given path
              // -------
        
              this.read = function(branch, path, cb) {
                _request("GET", repoPath + "/contents/"+path, {ref: branch}, function(err, obj) {
                  if (err && err.error === 404) return cb("not found", null, null);
        
                  if (err) return cb(err);
                  cb(null, obj);
                }, true);
              };
        
        
              // Remove a file
              // -------
        
              this.remove = function(branch, path, cb) {
                that.getSha(branch, path, function(err, sha) {
                  if (err) return cb(err);
                  _request("DELETE", repoPath + "/contents/" + path, {
                    message: path + " is removed",
                    sha: sha,
                    branch: branch
                  }, cb);
                });
              };
        
              // Delete a file from the tree
              // -------
        
              this.delete = function(branch, path, cb) {
                that.getSha(branch, path, function(err, sha) {
                  if (!sha) return cb("not found", null);
                  var delPath = repoPath + "/contents/" + path;
                  var params = {
                    "message": "Deleted " + path,
                    "sha": sha
                  };
                  delPath += "?message=" + encodeURIComponent(params.message);
                  delPath += "&sha=" + encodeURIComponent(params.sha);
                  delPath += '&branch=' + encodeURIComponent(branch);
                  _request("DELETE", delPath, null, cb);
                });
              };
        
              // Move a file to a new location
              // -------
        
              this.move = function(branch, path, newPath, cb) {
                updateTree(branch, function(err, latestCommit) {
                  that.getTree(latestCommit+"?recursive=true", function(err, tree) {
                    // Update Tree
                    _.each(tree, function(ref) {
                      if (ref.path === path) ref.path = newPath;
                      if (ref.type === "tree") delete ref.sha;
                    });
        
                    that.postTree(tree, function(err, rootTree) {
                      that.commit(latestCommit, rootTree, 'Deleted '+path , function(err, commit) {
                        that.updateHead(branch, commit, function(err) {
                          cb(err);
                        });
                      });
                    });
                  });
                });
              };
        
              // Write file contents to a given branch and path
              // -------
        
              this.write = function(branch, path, content, message, cb) {
                that.getSha(branch, path, function(err, sha) {
                  if (err && err.error!=404) return cb(err);
                  _request("PUT", repoPath + "/contents/" + path, {
                    message: message,
                    content: btoa(content),
                    branch: branch,
                    sha: sha
                  }, cb);
                });
              };
        
              // List commits on a repository. Takes an object of optional paramaters:
              // sha: SHA or branch to start listing commits from
              // path: Only commits containing this file path will be returned
              // since: ISO 8601 date - only commits after this date will be returned
              // until: ISO 8601 date - only commits before this date will be returned
              // -------
        
              this.getCommits = function(options, cb) {
                  options = options || {};
                  var url = repoPath + "/commits";
                  var params = [];
                  if (options.sha) {
                      params.push("sha=" + encodeURIComponent(options.sha));
                  }
                  if (options.path) {
                      params.push("path=" + encodeURIComponent(options.path));
                  }
                  if (options.since) {
                      var since = options.since;
                      if (since.constructor === Date) {
                          since = since.toISOString();
                      }
                      params.push("since=" + encodeURIComponent(since));
                  }
                  if (options.until) {
                      var until = options.until;
                      if (until.constructor === Date) {
                          until = until.toISOString();
                      }
                      params.push("until=" + encodeURIComponent(until));
                  }
                  if (options.page) {
                      params.push("page=" + options.page);
                  }
                  if (options.perpage) {
                      params.push("per_page=" + options.perpage);
                  }
                  if (params.length > 0) {
                      url += "?" + params.join("&");
                  }
                  _request("GET", url, null, cb);
              };
            };
        
            // Gists API
            // =======
        
            Github.Gist = function(options) {
              var id = options.id;
              var gistPath = "/gists/"+id;
        
              // Read the gist
              // --------
        
              this.read = function(cb) {
                _request("GET", gistPath, null, function(err, gist) {
                  cb(err, gist);
                });
              };
        
              // Create the gist
              // --------
              // {
              //  "description": "the description for this gist",
              //    "public": true,
              //    "files": {
              //      "file1.txt": {
              //        "content": "String file contents"
              //      }
              //    }
              // }
        
              this.create = function(options, cb){
                _request("POST","/gists", options, cb);
              };
        
              // Delete the gist
              // --------
        
              this.delete = function(cb) {
                _request("DELETE", gistPath, null, function(err,res) {
                  cb(err,res);
                });
              };
        
              // Fork a gist
              // --------
        
              this.fork = function(cb) {
                _request("POST", gistPath+"/fork", null, function(err,res) {
                  cb(err,res);
                });
              };
        
              // Update a gist with the new stuff
              // --------
        
              this.update = function(options, cb) {
                _request("PATCH", gistPath, options, function(err,res) {
                  cb(err,res);
                });
              };
        
              // Star a gist
              // --------
        
              this.star = function(cb) {
                _request("PUT", gistPath+"/star", null, function(err,res) {
                  cb(err,res);
                });
              };
        
              // Untar a gist
              // --------
        
              this.unstar = function(cb) {
                _request("DELETE", gistPath+"/star", null, function(err,res) {
                  cb(err,res);
                });
              };
        
              // Check if a gist is starred
              // --------
        
              this.isStarred = function(cb) {
                _request("GET", gistPath+"/star", null, function(err,res) {
                  cb(err,res);
                });
              };
            };
        
            // Issues API
            // ==========
        
            Github.Issue = function(options) {
              var path = "/repos/" + options.user + "/" + options.repo + "/issues";
        
              this.list = function(options, cb) {
                _request("GET", path, options, cb);
              };
            };
        
            // Top Level API
            // -------
        
            this.getIssues = function(user, repo) {
              return new Github.Issue({user: user, repo: repo});
            };
        
            this.getRepo = function(user, repo) {
              return new Github.Repository({user: user, name: repo});
            };
        
            this.getUser = function() {
              return new Github.User();
            };
        
            this.getGist = function(id) {
              return new Github.Gist({id: id});
            };
          };
        
        
          if (typeof exports !== 'undefined') {
            // Github = exports;
            module.exports = Github;
          } else {
            window.Github = Github;
          }
        }).call(this);
    • google-diff-match-patch
      • diff_match_patch.js
        (function(){function diff_match_patch(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=0.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=0.5;this.Patch_Margin=4;this.Match_MaxBits=32}
        diff_match_patch.prototype.diff_main=function(a,b,c,d){"undefined"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error("Null input. (diff_main)");if(a==b)return a?[[0,a]]:[];"undefined"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b);c=a.substring(0,f);a=a.substring(f);b=b.substring(f);var f=this.diff_commonSuffix(a,b),g=a.substring(a.length-f);a=a.substring(0,a.length-f);b=b.substring(0,b.length-f);a=this.diff_compute_(a,
        b,e,d);c&&a.unshift([0,c]);g&&a.push([0,g]);this.diff_cleanupMerge(a);return a};
        diff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[[1,b]];if(!b)return[[-1,a]];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);return-1!=g?(c=[[1,e.substring(0,g)],[0,f],[1,e.substring(g+f.length)]],a.length>b.length&&(c[0][0]=c[2][0]=-1),c):1==f.length?[[-1,a],[1,b]]:(e=this.diff_halfMatch_(a,b))?(f=e[0],a=e[1],g=e[2],b=e[3],e=e[4],f=this.diff_main(f,g,c,d),c=this.diff_main(a,b,c,d),f.concat([[0,e]],c)):c&&100<a.length&&100<b.length?this.diff_lineMode_(a,b,
        d):this.diff_bisect_(a,b,d)};
        diff_match_patch.prototype.diff_lineMode_=function(a,b,c){var d=this.diff_linesToChars_(a,b);a=d.chars1;b=d.chars2;d=d.lineArray;a=this.diff_main(a,b,!1,c);this.diff_charsToLines_(a,d);this.diff_cleanupSemantic(a);a.push([0,""]);for(var e=d=b=0,f="",g="";b<a.length;){switch(a[b][0]){case 1:e++;g+=a[b][1];break;case -1:d++;f+=a[b][1];break;case 0:if(1<=d&&1<=e){a.splice(b-d-e,d+e);b=b-d-e;d=this.diff_main(f,g,!1,c);for(e=d.length-1;0<=e;e--)a.splice(b,0,d[e]);b+=d.length}d=e=0;g=f=""}b++}a.pop();return a};
        diff_match_patch.prototype.diff_bisect_=function(a,b,c){for(var d=a.length,e=b.length,f=Math.ceil((d+e)/2),g=f,h=2*f,j=Array(h),i=Array(h),k=0;k<h;k++)j[k]=-1,i[k]=-1;j[g+1]=0;i[g+1]=0;for(var k=d-e,q=0!=k%2,r=0,t=0,p=0,w=0,v=0;v<f&&!((new Date).getTime()>c);v++){for(var n=-v+r;n<=v-t;n+=2){var l=g+n,m;m=n==-v||n!=v&&j[l-1]<j[l+1]?j[l+1]:j[l-1]+1;for(var s=m-n;m<d&&s<e&&a.charAt(m)==b.charAt(s);)m++,s++;j[l]=m;if(m>d)t+=2;else if(s>e)r+=2;else if(q&&(l=g+k-n,0<=l&&l<h&&-1!=i[l])){var u=d-i[l];if(m>=
        u)return this.diff_bisectSplit_(a,b,m,s,c)}}for(n=-v+p;n<=v-w;n+=2){l=g+n;u=n==-v||n!=v&&i[l-1]<i[l+1]?i[l+1]:i[l-1]+1;for(m=u-n;u<d&&m<e&&a.charAt(d-u-1)==b.charAt(e-m-1);)u++,m++;i[l]=u;if(u>d)w+=2;else if(m>e)p+=2;else if(!q&&(l=g+k-n,0<=l&&(l<h&&-1!=j[l])&&(m=j[l],s=g+m-l,u=d-u,m>=u)))return this.diff_bisectSplit_(a,b,m,s,c)}}return[[-1,a],[1,b]]};
        diff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d);a=a.substring(c);b=b.substring(d);f=this.diff_main(f,g,!1,e);e=this.diff_main(a,b,!1,e);return f.concat(e)};
        diff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b="",c=0,f=-1,g=d.length;f<a.length-1;){f=a.indexOf("\n",c);-1==f&&(f=a.length-1);var r=a.substring(c,f+1),c=f+1;(e.hasOwnProperty?e.hasOwnProperty(r):void 0!==e[r])?b+=String.fromCharCode(e[r]):(b+=String.fromCharCode(g),e[r]=g,d[g++]=r)}return b}var d=[],e={};d[0]="";var f=c(a),g=c(b);return{chars1:f,chars2:g,lineArray:d}};
        diff_match_patch.prototype.diff_charsToLines_=function(a,b){for(var c=0;c<a.length;c++){for(var d=a[c][1],e=[],f=0;f<d.length;f++)e[f]=b[d.charCodeAt(f)];a[c][1]=e.join("")}};diff_match_patch.prototype.diff_commonPrefix=function(a,b){if(!a||!b||a.charAt(0)!=b.charAt(0))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(f,e)==b.substring(f,e)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
        diff_match_patch.prototype.diff_commonSuffix=function(a,b){if(!a||!b||a.charAt(a.length-1)!=b.charAt(b.length-1))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(a.length-e,a.length-f)==b.substring(b.length-e,b.length-f)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
        diff_match_patch.prototype.diff_commonOverlap_=function(a,b){var c=a.length,d=b.length;if(0==c||0==d)return 0;c>d?a=a.substring(c-d):c<d&&(b=b.substring(0,c));c=Math.min(c,d);if(a==b)return c;for(var d=0,e=1;;){var f=a.substring(c-e),f=b.indexOf(f);if(-1==f)return d;e+=f;if(0==f||a.substring(c-e)==b.substring(0,e))d=e,e++}};
        diff_match_patch.prototype.diff_halfMatch_=function(a,b){function c(a,b,c){for(var d=a.substring(c,c+Math.floor(a.length/4)),e=-1,g="",h,j,n,l;-1!=(e=b.indexOf(d,e+1));){var m=f.diff_commonPrefix(a.substring(c),b.substring(e)),s=f.diff_commonSuffix(a.substring(0,c),b.substring(0,e));g.length<s+m&&(g=b.substring(e-s,e)+b.substring(e,e+m),h=a.substring(0,c-s),j=a.substring(c+m),n=b.substring(0,e-s),l=b.substring(e+m))}return 2*g.length>=a.length?[h,j,n,l,g]:null}if(0>=this.Diff_Timeout)return null;
        var d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.length<d.length)return null;var f=this,g=c(d,e,Math.ceil(d.length/4)),d=c(d,e,Math.ceil(d.length/2)),h;if(!g&&!d)return null;h=d?g?g[4].length>d[4].length?g:d:d:g;var j;a.length>b.length?(g=h[0],d=h[1],e=h[2],j=h[3]):(e=h[0],j=h[1],g=h[2],d=h[3]);h=h[4];return[g,d,e,j,h]};
        diff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,j=0,i=0;f<a.length;)0==a[f][0]?(c[d++]=f,g=j,h=i,i=j=0,e=a[f][1]):(1==a[f][0]?j+=a[f][1].length:i+=a[f][1].length,e&&(e.length<=Math.max(g,h)&&e.length<=Math.max(j,i))&&(a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,d--,f=0<d?c[d-1]:-1,i=j=h=g=0,e=null,b=!0)),f++;b&&this.diff_cleanupMerge(a);this.diff_cleanupSemanticLossless(a);for(f=1;f<a.length;){if(-1==a[f-1][0]&&1==a[f][0]){b=a[f-1][1];c=a[f][1];
        d=this.diff_commonOverlap_(b,c);e=this.diff_commonOverlap_(c,b);if(d>=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,[0,c.substring(0,d)]),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,[0,b.substring(0,e)]),a[f-1][0]=1,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=-1,a[f+1][1]=b.substring(e),f++;f++}f++}};
        diff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_),c=g&&c.match(diff_match_patch.linebreakRegex_),d=h&&d.match(diff_match_patch.linebreakRegex_),i=c&&a.match(diff_match_patch.blanklineEndRegex_),j=d&&b.match(diff_match_patch.blanklineStartRegex_);
        return i||j?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c<a.length-1;){if(0==a[c-1][0]&&0==a[c+1][0]){var d=a[c-1][1],e=a[c][1],f=a[c+1][1],g=this.diff_commonSuffix(d,e);if(g)var h=e.substring(e.length-g),d=d.substring(0,d.length-g),e=h+e.substring(0,e.length-g),f=h+f;for(var g=d,h=e,j=f,i=b(d,e)+b(e,f);e.charAt(0)===f.charAt(0);){var d=d+e.charAt(0),e=e.substring(1)+f.charAt(0),f=f.substring(1),k=b(d,e)+b(e,f);k>=i&&(i=k,g=d,h=e,j=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-1,1),c--),a[c][1]=
        h,j?a[c+1][1]=j:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\s/;diff_match_patch.linebreakRegex_=/[\r\n]/;diff_match_patch.blanklineEndRegex_=/\n\r?\n$/;diff_match_patch.blanklineStartRegex_=/^\r?\n\r?\n/;
        diff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,j=!1,i=!1;f<a.length;){if(0==a[f][0])a[f][1].length<this.Diff_EditCost&&(j||i)?(c[d++]=f,g=j,h=i,e=a[f][1]):(d=0,e=null),j=i=!1;else if(-1==a[f][0]?i=!0:j=!0,e&&(g&&h&&j&&i||e.length<this.Diff_EditCost/2&&3==g+h+j+i))a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,e=null,g&&h?(j=i=!0,d=0):(d--,f=0<d?c[d-1]:-1,j=i=!1),b=!0;f++}b&&this.diff_cleanupMerge(a)};
        diff_match_patch.prototype.diff_cleanupMerge=function(a){a.push([0,""]);for(var b=0,c=0,d=0,e="",f="",g;b<a.length;)switch(a[b][0]){case 1:d++;f+=a[b][1];b++;break;case -1:c++;e+=a[b][1];b++;break;case 0:1<c+d?(0!==c&&0!==d&&(g=this.diff_commonPrefix(f,e),0!==g&&(0<b-c-d&&0==a[b-c-d-1][0]?a[b-c-d-1][1]+=f.substring(0,g):(a.splice(0,0,[0,f.substring(0,g)]),b++),f=f.substring(g),e=e.substring(g)),g=this.diff_commonSuffix(f,e),0!==g&&(a[b][1]=f.substring(f.length-g)+a[b][1],f=f.substring(0,f.length-
        g),e=e.substring(0,e.length-g))),0===c?a.splice(b-d,c+d,[1,f]):0===d?a.splice(b-c,c+d,[-1,e]):a.splice(b-c-d,c+d,[-1,e],[1,f]),b=b-c-d+(c?1:0)+(d?1:0)+1):0!==b&&0==a[b-1][0]?(a[b-1][1]+=a[b][1],a.splice(b,1)):b++,c=d=0,f=e=""}""===a[a.length-1][1]&&a.pop();c=!1;for(b=1;b<a.length-1;)0==a[b-1][0]&&0==a[b+1][0]&&(a[b][1].substring(a[b][1].length-a[b-1][1].length)==a[b-1][1]?(a[b][1]=a[b-1][1]+a[b][1].substring(0,a[b][1].length-a[b-1][1].length),a[b+1][1]=a[b-1][1]+a[b+1][1],a.splice(b-1,1),c=!0):a[b][1].substring(0,
        a[b+1][1].length)==a[b+1][1]&&(a[b-1][1]+=a[b+1][1],a[b][1]=a[b][1].substring(a[b+1][1].length)+a[b+1][1],a.splice(b+1,1),c=!0)),b++;c&&this.diff_cleanupMerge(a)};diff_match_patch.prototype.diff_xIndex=function(a,b){var c=0,d=0,e=0,f=0,g;for(g=0;g<a.length;g++){1!==a[g][0]&&(c+=a[g][1].length);-1!==a[g][0]&&(d+=a[g][1].length);if(c>b)break;e=c;f=d}return a.length!=g&&-1===a[g][0]?f:f+(b-e)};
        diff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=/</g,e=/>/g,f=/\n/g,g=0;g<a.length;g++){var h=a[g][0],j=a[g][1],j=j.replace(c,"&amp;").replace(d,"&lt;").replace(e,"&gt;").replace(f,"&para;<br>");switch(h){case 1:b[g]='<ins style="background:#e6ffe6;">'+j+"</ins>";break;case -1:b[g]='<del style="background:#ffe6e6;">'+j+"</del>";break;case 0:b[g]="<span>"+j+"</span>"}}return b.join("")};
        diff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;c<a.length;c++)1!==a[c][0]&&(b[c]=a[c][1]);return b.join("")};diff_match_patch.prototype.diff_text2=function(a){for(var b=[],c=0;c<a.length;c++)-1!==a[c][0]&&(b[c]=a[c][1]);return b.join("")};diff_match_patch.prototype.diff_levenshtein=function(a){for(var b=0,c=0,d=0,e=0;e<a.length;e++){var f=a[e][0],g=a[e][1];switch(f){case 1:c+=g.length;break;case -1:d+=g.length;break;case 0:b+=Math.max(c,d),d=c=0}}return b+=Math.max(c,d)};
        diff_match_patch.prototype.diff_toDelta=function(a){for(var b=[],c=0;c<a.length;c++)switch(a[c][0]){case 1:b[c]="+"+encodeURI(a[c][1]);break;case -1:b[c]="-"+a[c][1].length;break;case 0:b[c]="="+a[c][1].length}return b.join("\t").replace(/%20/g," ")};
        diff_match_patch.prototype.diff_fromDelta=function(a,b){for(var c=[],d=0,e=0,f=b.split(/\t/g),g=0;g<f.length;g++){var h=f[g].substring(1);switch(f[g].charAt(0)){case "+":try{c[d++]=[1,decodeURI(h)]}catch(j){throw Error("Illegal escape in diff_fromDelta: "+h);}break;case "-":case "=":var i=parseInt(h,10);if(isNaN(i)||0>i)throw Error("Invalid number in diff_fromDelta: "+h);h=a.substring(e,e+=i);"="==f[g].charAt(0)?c[d++]=[0,h]:c[d++]=[-1,h];break;default:if(f[g])throw Error("Invalid diff operation in diff_fromDelta: "+
        f[g]);}}if(e!=a.length)throw Error("Delta length ("+e+") does not equal source text length ("+a.length+").");return c};diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error("Null input. (match_main)");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};
        diff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return!f.Match_Distance?g?1:e:e+g/f.Match_Distance}if(b.length>this.Match_MaxBits)throw Error("Pattern too long for this browser.");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));for(var j=1<<b.length-1,h=-1,i,k,q=b.length+a.length,r,t=0;t<b.length;t++){i=0;for(k=q;i<k;)d(t,c+
        k)<=g?i=k:q=k,k=Math.floor((q-i)/2+i);q=k;i=Math.max(1,c-k+1);var p=Math.min(c+k,a.length)+b.length;k=Array(p+2);for(k[p+1]=(1<<t)-1;p>=i;p--){var w=e[a.charAt(p-1)];k[p]=0===t?(k[p+1]<<1|1)&w:(k[p+1]<<1|1)&w|((r[p+1]|r[p])<<1|1)|r[p+1];if(k[p]&j&&(w=d(t,p-1),w<=g))if(g=w,h=p-1,h>c)i=Math.max(1,2*c-h);else break}if(d(t+1,c)>g)break;r=k}return h};
        diff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c<a.length;c++)b[a.charAt(c)]=0;for(c=0;c<a.length;c++)b[a.charAt(c)]|=1<<a.length-c-1;return b};
        diff_match_patch.prototype.patch_addContext_=function(a,b){if(0!=b.length){for(var c=b.substring(a.start2,a.start2+a.length1),d=0;b.indexOf(c)!=b.lastIndexOf(c)&&c.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)d+=this.Patch_Margin,c=b.substring(a.start2-d,a.start2+a.length1+d);d+=this.Patch_Margin;(c=b.substring(a.start2-d,a.start2))&&a.diffs.unshift([0,c]);(d=b.substring(a.start2+a.length1,a.start2+a.length1+d))&&a.diffs.push([0,d]);a.start1-=c.length;a.start2-=c.length;a.length1+=
        c.length+d.length;a.length2+=c.length+d.length}};
        diff_match_patch.prototype.patch_make=function(a,b,c){var d;if("string"==typeof a&&"string"==typeof b&&"undefined"==typeof c)d=a,b=this.diff_main(d,b,!0),2<b.length&&(this.diff_cleanupSemantic(b),this.diff_cleanupEfficiency(b));else if(a&&"object"==typeof a&&"undefined"==typeof b&&"undefined"==typeof c)b=a,d=this.diff_text1(b);else if("string"==typeof a&&b&&"object"==typeof b&&"undefined"==typeof c)d=a;else if("string"==typeof a&&"string"==typeof b&&c&&"object"==typeof c)d=a,b=c;else throw Error("Unknown call format to patch_make.");
        if(0===b.length)return[];c=[];a=new diff_match_patch.patch_obj;for(var e=0,f=0,g=0,h=d,j=0;j<b.length;j++){var i=b[j][0],k=b[j][1];!e&&0!==i&&(a.start1=f,a.start2=g);switch(i){case 1:a.diffs[e++]=b[j];a.length2+=k.length;d=d.substring(0,g)+k+d.substring(g);break;case -1:a.length1+=k.length;a.diffs[e++]=b[j];d=d.substring(0,g)+d.substring(g+k.length);break;case 0:k.length<=2*this.Patch_Margin&&e&&b.length!=j+1?(a.diffs[e++]=b[j],a.length1+=k.length,a.length2+=k.length):k.length>=2*this.Patch_Margin&&
        e&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}1!==i&&(f+=k.length);-1!==i&&(g+=k.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new diff_match_patch.patch_obj;e.diffs=[];for(var f=0;f<d.diffs.length;f++)e.diffs[f]=d.diffs[f].slice();e.start1=d.start1;e.start2=d.start2;e.length1=d.length1;e.length2=d.length2;b[c]=e}return b};
        diff_match_patch.prototype.patch_apply=function(a,b){if(0==a.length)return[b,[]];a=this.patch_deepCopy(a);var c=this.patch_addPadding(a);b=c+b+c;this.patch_splitMax(a);for(var d=0,e=[],f=0;f<a.length;f++){var g=a[f].start2+d,h=this.diff_text1(a[f].diffs),j,i=-1;if(h.length>this.Match_MaxBits){if(j=this.match_main(b,h.substring(0,this.Match_MaxBits),g),-1!=j&&(i=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==i||j>=i))j=-1}else j=this.match_main(b,h,g);
        if(-1==j)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=j-g,g=-1==i?b.substring(j,j+h.length):b.substring(j,i+this.Match_MaxBits),h==g)b=b.substring(0,j)+this.diff_text2(a[f].diffs)+b.substring(j+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);for(var h=0,k,i=0;i<a[f].diffs.length;i++){var q=a[f].diffs[i];0!==q[0]&&(k=this.diff_xIndex(g,h));1===q[0]?b=b.substring(0,
        j+k)+q[1]+b.substring(j+k):-1===q[0]&&(b=b.substring(0,j+k)+b.substring(j+this.diff_xIndex(g,h+q[1].length)));-1!==q[0]&&(h+=q[1].length)}}}b=b.substring(c.length,b.length-c.length);return[b,e]};
        diff_match_patch.prototype.patch_addPadding=function(a){for(var b=this.Patch_Margin,c="",d=1;d<=b;d++)c+=String.fromCharCode(d);for(d=0;d<a.length;d++)a[d].start1+=b,a[d].start2+=b;var d=a[0],e=d.diffs;if(0==e.length||0!=e[0][0])e.unshift([0,c]),d.start1-=b,d.start2-=b,d.length1+=b,d.length2+=b;else if(b>e[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;0==e.length||0!=e[e.length-1][0]?(e.push([0,
        c]),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};
        diff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c<a.length;c++)if(!(a[c].length1<=b)){var d=a[c];a.splice(c--,1);for(var e=d.start1,f=d.start2,g="";0!==d.diffs.length;){var h=new diff_match_patch.patch_obj,j=!0;h.start1=e-g.length;h.start2=f-g.length;""!==g&&(h.length1=h.length2=g.length,h.diffs.push([0,g]));for(;0!==d.diffs.length&&h.length1<b-this.Patch_Margin;){var g=d.diffs[0][0],i=d.diffs[0][1];1===g?(h.length2+=i.length,f+=i.length,h.diffs.push(d.diffs.shift()),
        j=!1):-1===g&&1==h.diffs.length&&0==h.diffs[0][0]&&i.length>2*b?(h.length1+=i.length,e+=i.length,j=!1,h.diffs.push([g,i]),d.diffs.shift()):(i=i.substring(0,b-h.length1-this.Patch_Margin),h.length1+=i.length,e+=i.length,0===g?(h.length2+=i.length,f+=i.length):j=!1,h.diffs.push([g,i]),i==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(i.length))}g=this.diff_text2(h.diffs);g=g.substring(g.length-this.Patch_Margin);i=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);""!==i&&
        (h.length1+=i.length,h.length2+=i.length,0!==h.diffs.length&&0===h.diffs[h.diffs.length-1][0]?h.diffs[h.diffs.length-1][1]+=i:h.diffs.push([0,i]));j||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c];return b.join("")};
        diff_match_patch.prototype.patch_fromText=function(a){var b=[];if(!a)return b;a=a.split("\n");for(var c=0,d=/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;c<a.length;){var e=a[c].match(d);if(!e)throw Error("Invalid patch string: "+a[c]);var f=new diff_match_patch.patch_obj;b.push(f);f.start1=parseInt(e[1],10);""===e[2]?(f.start1--,f.length1=1):"0"==e[2]?f.length1=0:(f.start1--,f.length1=parseInt(e[2],10));f.start2=parseInt(e[3],10);""===e[4]?(f.start2--,f.length2=1):"0"==e[4]?f.length2=0:(f.start2--,f.length2=
        parseInt(e[4],10));for(c++;c<a.length;){e=a[c].charAt(0);try{var g=decodeURI(a[c].substring(1))}catch(h){throw Error("Illegal escape in patch_fromText: "+g);}if("-"==e)f.diffs.push([-1,g]);else if("+"==e)f.diffs.push([1,g]);else if(" "==e)f.diffs.push([0,g]);else if("@"==e)break;else if(""!==e)throw Error('Invalid patch mode "'+e+'" in: '+g);c++}}return b};diff_match_patch.patch_obj=function(){this.diffs=[];this.start2=this.start1=null;this.length2=this.length1=0};
        diff_match_patch.patch_obj.prototype.toString=function(){var a,b;a=0===this.length1?this.start1+",0":1==this.length1?this.start1+1:this.start1+1+","+this.length1;b=0===this.length2?this.start2+",0":1==this.length2?this.start2+1:this.start2+1+","+this.length2;a=["@@ -"+a+" +"+b+" @@\n"];var c;for(b=0;b<this.diffs.length;b++){switch(this.diffs[b][0]){case 1:c="+";break;case -1:c="-";break;case 0:c=" "}a[b+1]=c+encodeURI(this.diffs[b][1])+"\n"}return a.join("").replace(/%20/g," ")};
        this.diff_match_patch=diff_match_patch;this.DIFF_DELETE=-1;this.DIFF_INSERT=1;this.DIFF_EQUAL=0;})()
        
    • json3
      • json3.min.js
        (function(){function N(p,r){function q(a){if(q[a]!==w)return q[a];var c;if("bug-string-char-index"==a)c="a"!="a"[0];else if("json"==a)c=q("json-stringify")&&q("json-parse");else{var e;if("json-stringify"==a){c=r.stringify;var b="function"==typeof c&&s;if(b){(e=function(){return 1}).toJSON=e;try{b="0"===c(0)&&"0"===c(new t)&&'""'==c(new A)&&c(u)===w&&c(w)===w&&c()===w&&"1"===c(e)&&"[1]"==c([e])&&"[null]"==c([w])&&"null"==c(null)&&"[null,null,null]"==c([w,u,null])&&'{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}'==c({a:[e,!0,!1,null,"\x00\b\n\f\r\t"]})&&"1"===c(null,e)&&"[\n 1,\n 2\n]"==c([1,2],null,1)&&'"-271821-04-20T00:00:00.000Z"'==c(new C(-864E13))&&'"+275760-09-13T00:00:00.000Z"'==c(new C(864E13))&&'"-000001-01-01T00:00:00.000Z"'==c(new C(-621987552E5))&&'"1969-12-31T23:59:59.999Z"'==c(new C(-1))}catch(f){b=!1}}c=b}if("json-parse"==a){c=r.parse;if("function"==typeof c)try{if(0===c("0")&&!c(!1)){e=c('{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}');var n=5==e.a.length&&1===e.a[0];if(n){try{n=!c('"\t"')}catch(d){}if(n)try{n=1!==c("01")}catch(g){}if(n)try{n=1!==c("1.")}catch(m){}}}}catch(X){n=!1}c=n}}return q[a]=!!c}p||(p=k.Object());r||(r=k.Object());var t=p.Number||k.Number,A=p.String||k.String,H=p.Object||k.Object,C=p.Date||k.Date,G=p.SyntaxError||k.SyntaxError,K=p.TypeError||k.TypeError,L=p.Math||k.Math,I=p.JSON||k.JSON;"object"==typeof I&&I&&(r.stringify=I.stringify,r.parse=I.parse);var H=H.prototype,u=H.toString,v,B,w,s=new C(-0xc782b5b800cec);try{s=-109252==s.getUTCFullYear()&&0===s.getUTCMonth()&&1===s.getUTCDate()&&10==s.getUTCHours()&&37==s.getUTCMinutes()&&6==s.getUTCSeconds()&&708==s.getUTCMilliseconds()}catch(Q){}if(!q("json")){var D=q("bug-string-char-index");if(!s)var x=L.floor,M=[0,31,59,90,120,151,181,212,243,273,304,334],E=function(a,c){return M[c]+365*(a-1970)+x((a-1969+(c=+(1<c)))/4)-x((a-1901+c)/100)+x((a-1601+c)/400)};(v=H.hasOwnProperty)||(v=function(a){var c={},e;(c.__proto__=null,c.__proto__={toString:1},c).toString!=u?v=function(a){var c=this.__proto__;a=a in(this.__proto__=null,this);this.__proto__=c;return a}:(e=c.constructor,v=function(a){var c=(this.constructor||e).prototype;return a in this&&!(a in c&&this[a]===c[a])});c=null;return v.call(this,a)});B=function(a,c){var e=0,b,f,n;(b=function(){this.valueOf=0}).prototype.valueOf=0;f=new b;for(n in f)v.call(f,n)&&e++;b=f=null;e?B=2==e?function(a,c){var e={},b="[object Function]"==u.call(a),f;for(f in a)b&&"prototype"==f||v.call(e,f)||!(e[f]=1)||!v.call(a,f)||c(f)}:function(a,c){var e="[object Function]"==u.call(a),b,f;for(b in a)e&&"prototype"==b||!v.call(a,b)||(f="constructor"===b)||c(b);(f||v.call(a,b="constructor"))&&c(b)}:(f="valueOf toString toLocaleString propertyIsEnumerable isPrototypeOf hasOwnProperty constructor".split(" "),B=function(a,c){var e="[object Function]"==u.call(a),b,h=!e&&"function"!=typeof a.constructor&&F[typeof a.hasOwnProperty]&&a.hasOwnProperty||v;for(b in a)e&&"prototype"==b||!h.call(a,b)||c(b);for(e=f.length;b=f[--e];h.call(a,b)&&c(b));});return B(a,c)};if(!q("json-stringify")){var U={92:"\\\\",34:'\\"',8:"\\b",12:"\\f",10:"\\n",13:"\\r",9:"\\t"},y=function(a,c){return("000000"+(c||0)).slice(-a)},R=function(a){for(var c='"',b=0,h=a.length,f=!D||10<h,n=f&&(D?a.split(""):a);b<h;b++){var d=a.charCodeAt(b);switch(d){case 8:case 9:case 10:case 12:case 13:case 34:case 92:c+=U[d];break;default:if(32>d){c+="\\u00"+y(2,d.toString(16));break}c+=f?n[b]:a.charAt(b)}}return c+'"'},O=function(a,c,b,h,f,n,d){var g,m,k,l,p,r,s,t,q;try{g=c[a]}catch(z){}if("object"==typeof g&&g)if(m=u.call(g),"[object Date]"!=m||v.call(g,"toJSON"))"function"==typeof g.toJSON&&("[object Number]"!=m&&"[object String]"!=m&&"[object Array]"!=m||v.call(g,"toJSON"))&&(g=g.toJSON(a));else if(g>-1/0&&g<1/0){if(E){l=x(g/864E5);for(m=x(l/365.2425)+1970-1;E(m+1,0)<=l;m++);for(k=x((l-E(m,0))/30.42);E(m,k+1)<=l;k++);l=1+l-E(m,k);p=(g%864E5+864E5)%864E5;r=x(p/36E5)%24;s=x(p/6E4)%60;t=x(p/1E3)%60;p%=1E3}else m=g.getUTCFullYear(),k=g.getUTCMonth(),l=g.getUTCDate(),r=g.getUTCHours(),s=g.getUTCMinutes(),t=g.getUTCSeconds(),p=g.getUTCMilliseconds();g=(0>=m||1E4<=m?(0>m?"-":"+")+y(6,0>m?-m:m):y(4,m))+"-"+y(2,k+1)+"-"+y(2,l)+"T"+y(2,r)+":"+y(2,s)+":"+y(2,t)+"."+y(3,p)+"Z"}else g=null;b&&(g=b.call(c,a,g));if(null===g)return"null";m=u.call(g);if("[object Boolean]"==m)return""+g;if("[object Number]"==m)return g>-1/0&&g<1/0?""+g:"null";if("[object String]"==m)return R(""+g);if("object"==typeof g){for(a=d.length;a--;)if(d[a]===g)throw K();d.push(g);q=[];c=n;n+=f;if("[object Array]"==m){k=0;for(a=g.length;k<a;k++)m=O(k,g,b,h,f,n,d),q.push(m===w?"null":m);a=q.length?f?"[\n"+n+q.join(",\n"+n)+"\n"+c+"]":"["+q.join(",")+"]":"[]"}else B(h||g,function(a){var c=O(a,g,b,h,f,n,d);c!==w&&q.push(R(a)+":"+(f?" ":"")+c)}),a=q.length?f?"{\n"+n+q.join(",\n"+n)+"\n"+c+"}":"{"+q.join(",")+"}":"{}";d.pop();return a}};r.stringify=function(a,c,b){var h,f,n,d;if(F[typeof c]&&c)if("[object Function]"==(d=u.call(c)))f=c;else if("[object Array]"==d){n={};for(var g=0,k=c.length,l;g<k;l=c[g++],(d=u.call(l),"[object String]"==d||"[object Number]"==d)&&(n[l]=1));}if(b)if("[object Number]"==(d=u.call(b))){if(0<(b-=b%1))for(h="",10<b&&(b=10);h.length<b;h+=" ");}else"[object String]"==d&&(h=10>=b.length?b:b.slice(0,10));return O("",(l={},l[""]=a,l),f,n,h,"",[])}}if(!q("json-parse")){var V=A.fromCharCode,W={92:"\\",34:'"',47:"/",98:"\b",116:"\t",110:"\n",102:"\f",114:"\r"},b,J,l=function(){b=J=null;throw G();},z=function(){for(var a=J,c=a.length,e,h,f,k,d;b<c;)switch(d=a.charCodeAt(b),d){case 9:case 10:case 13:case 32:b++;break;case 123:case 125:case 91:case 93:case 58:case 44:return e=D?a.charAt(b):a[b],b++,e;case 34:e="@";for(b++;b<c;)if(d=a.charCodeAt(b),32>d)l();else if(92==d)switch(d=a.charCodeAt(++b),d){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:e+=W[d];b++;break;case 117:h=++b;for(f=b+4;b<f;b++)d=a.charCodeAt(b),48<=d&&57>=d||97<=d&&102>=d||65<=d&&70>=d||l();e+=V("0x"+a.slice(h,b));break;default:l()}else{if(34==d)break;d=a.charCodeAt(b);for(h=b;32<=d&&92!=d&&34!=d;)d=a.charCodeAt(++b);e+=a.slice(h,b)}if(34==a.charCodeAt(b))return b++,e;l();default:h=b;45==d&&(k=!0,d=a.charCodeAt(++b));if(48<=d&&57>=d){for(48==d&&(d=a.charCodeAt(b+1),48<=d&&57>=d)&&l();b<c&&(d=a.charCodeAt(b),48<=d&&57>=d);b++);if(46==a.charCodeAt(b)){for(f=++b;f<c&&(d=a.charCodeAt(f),48<=d&&57>=d);f++);f==b&&l();b=f}d=a.charCodeAt(b);if(101==d||69==d){d=a.charCodeAt(++b);43!=d&&45!=d||b++;for(f=b;f<c&&(d=a.charCodeAt(f),48<=d&&57>=d);f++);f==b&&l();b=f}return+a.slice(h,b)}k&&l();if("true"==a.slice(b,b+4))return b+=4,!0;if("false"==a.slice(b,b+5))return b+=5,!1;if("null"==a.slice(b,b+4))return b+=4,null;l()}return"$"},P=function(a){var c,b;"$"==a&&l();if("string"==typeof a){if("@"==(D?a.charAt(0):a[0]))return a.slice(1);if("["==a){for(c=[];;b||(b=!0)){a=z();if("]"==a)break;b&&(","==a?(a=z(),"]"==a&&l()):l());","==a&&l();c.push(P(a))}return c}if("{"==a){for(c={};;b||(b=!0)){a=z();if("}"==a)break;b&&(","==a?(a=z(),"}"==a&&l()):l());","!=a&&"string"==typeof a&&"@"==(D?a.charAt(0):a[0])&&":"==z()||l();c[a.slice(1)]=P(z())}return c}l()}return a},T=function(a,b,e){e=S(a,b,e);e===w?delete a[b]:a[b]=e},S=function(a,b,e){var h=a[b],f;if("object"==typeof h&&h)if("[object Array]"==u.call(h))for(f=h.length;f--;)T(h,f,e);else B(h,function(a){T(h,a,e)});return e.call(a,b,h)};r.parse=function(a,c){var e,h;b=0;J=""+a;e=P(z());"$"!=z()&&l();b=J=null;return c&&"[object Function]"==u.call(c)?S((h={},h[""]=e,h),"",c):e}}}r.runInContext=N;return r}var K=typeof define==="function"&&define.amd,F={"function":!0,object:!0},G=F[typeof exports]&&exports&&!exports.nodeType&&exports,k=F[typeof window]&&window||this,t=G&&F[typeof module]&&module&&!module.nodeType&&"object"==typeof global&&global;!t||t.global!==t&&t.window!==t&&t.self!==t||(k=t);if(G&&!K)N(k,G);else{var L=k.JSON,Q=k.JSON3,M=!1,A=N(k,k.JSON3={noConflict:function(){M||(M=!0,k.JSON=L,k.JSON3=Q,L=Q=null);return A}});k.JSON={parse:A.parse,stringify:A.stringify}}K&&define(function(){return A})}).call(this);
    • knockout
      • knockout-3.2.0.js
        (function(){(function(p){var s=this||(0,eval)("this"),v=s.document,L=s.navigator,w=s.jQuery,D=s.JSON;(function(p){"function"===typeof require&&"object"===typeof exports&&"object"===typeof module?p(module.exports||exports,require):"function"===typeof define&&define.amd?define(["exports","require"],p):p(s.ko={})})(function(M,N){function H(a,d){return null===a||typeof a in R?a===d:!1}function S(a,d){var c;return function(){c||(c=setTimeout(function(){c=p;a()},d))}}function T(a,d){var c;return function(){clearTimeout(c);c=setTimeout(a,d)}}function I(b,d,c,e){a.d[b]={init:function(b,h,k,f,m){var l,q;a.s(function(){var f=a.a.c(h()),k=!c!==!f,z=!q;if(z||d||k!==l)z&&a.Y.la()&&(q=a.a.ia(a.f.childNodes(b),!0)),k?(z||a.f.T(b,a.a.ia(q)),a.Ca(e?e(m,f):m,b)):a.f.ja(b),l=k},null,{o:b});return{controlsDescendantBindings:!0}}};a.h.ha[b]=!1;a.f.Q[b]=!0}var a="undefined"!==typeof M?M:{};a.b=function(b,d){for(var c=b.split("."),e=a,g=0;g<c.length-1;g++)e=e[c[g]];e[c[c.length-1]]=d};a.A=function(a,d,c){a[d]=c};a.version="3.2.0";a.b("version",a.version);a.a=function(){function b(a,b){for(var c in a)a.hasOwnProperty(c)&&b(c,a[c])}function d(a,b){if(b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function c(a,b){a.__proto__=b;return a}var e={__proto__:[]}instanceof Array,g={},h={};g[L&&/Firefox\/2/i.test(L.userAgent)?"KeyboardEvent":"UIEvents"]=["keyup","keydown","keypress"];g.MouseEvents="click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" ");b(g,function(a,b){if(b.length)for(var c=0,d=b.length;c<d;c++)h[b[c]]=a});var k={propertychange:!0},f=v&&function(){for(var a=3,b=v.createElement("div"),c=b.getElementsByTagName("i");b.innerHTML="\x3c!--[if gt IE "+ ++a+"]><i></i><![endif]--\x3e",c[0];);return 4<a?a:p}();return{vb:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],u:function(a,b){for(var c=0,d=a.length;c<d;c++)b(a[c],c)},m:function(a,b){if("function"==typeof Array.prototype.indexOf)return Array.prototype.indexOf.call(a,b);for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},qb:function(a,b,c){for(var d=0,f=a.length;d<f;d++)if(b.call(c,a[d],d))return a[d];return null},ua:function(m,b){var c=a.a.m(m,b);0<c?m.splice(c,1):0===c&&m.shift()},rb:function(m){m=m||[];for(var b=[],c=0,d=m.length;c<d;c++)0>a.a.m(b,m[c])&&b.push(m[c]);return b},Da:function(a,b){a=a||[];for(var c=[],d=0,f=a.length;d<f;d++)c.push(b(a[d],d));return c},ta:function(a,b){a=a||[];for(var c=[],d=0,f=a.length;d<f;d++)b(a[d],d)&&c.push(a[d]);return c},ga:function(a,b){if(b instanceof
        Array)a.push.apply(a,b);else for(var c=0,d=b.length;c<d;c++)a.push(b[c]);return a},ea:function(b,c,d){var f=a.a.m(a.a.Xa(b),c);0>f?d&&b.push(c):d||b.splice(f,1)},xa:e,extend:d,za:c,Aa:e?c:d,G:b,na:function(a,b){if(!a)return a;var c={},d;for(d in a)a.hasOwnProperty(d)&&(c[d]=b(a[d],d,a));return c},Ka:function(b){for(;b.firstChild;)a.removeNode(b.firstChild)},oc:function(b){b=a.a.S(b);for(var c=v.createElement("div"),d=0,f=b.length;d<f;d++)c.appendChild(a.R(b[d]));return c},ia:function(b,c){for(var d=0,f=b.length,e=[];d<f;d++){var k=b[d].cloneNode(!0);e.push(c?a.R(k):k)}return e},T:function(b,c){a.a.Ka(b);if(c)for(var d=0,f=c.length;d<f;d++)b.appendChild(c[d])},Lb:function(b,c){var d=b.nodeType?[b]:b;if(0<d.length){for(var f=d[0],e=f.parentNode,k=0,g=c.length;k<g;k++)e.insertBefore(c[k],f);k=0;for(g=d.length;k<g;k++)a.removeNode(d[k])}},ka:function(a,b){if(a.length){for(b=8===b.nodeType&&b.parentNode||b;a.length&&a[0].parentNode!==b;)a.shift();if(1<a.length){var c=a[0],d=a[a.length-1];for(a.length=0;c!==d;)if(a.push(c),c=c.nextSibling,!c)return;a.push(d)}}return a},Nb:function(a,b){7>f?a.setAttribute("selected",b):a.selected=b},cb:function(a){return null===a||a===p?"":a.trim?a.trim():a.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g,"")},vc:function(a,b){a=a||"";return b.length>a.length?!1:a.substring(0,b.length)===b},cc:function(a,b){if(a===b)return!0;if(11===a.nodeType)return!1;if(b.contains)return b.contains(3===a.nodeType?a.parentNode:a);if(b.compareDocumentPosition)return 16==(b.compareDocumentPosition(a)&16);for(;a&&a!=b;)a=a.parentNode;return!!a},Ja:function(b){return a.a.cc(b,b.ownerDocument.documentElement)},ob:function(b){return!!a.a.qb(b,a.a.Ja)},t:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},n:function(b,c,d){var e=f&&k[c];if(!e&&w)w(b).bind(c,d);else if(e||"function"!=typeof b.addEventListener)if("undefined"!=typeof b.attachEvent){var g=function(a){d.call(b,a)},h="on"+c;b.attachEvent(h,g);a.a.w.da(b,function(){b.detachEvent(h,g)})}else throw Error("Browser doesn't support addEventListener or attachEvent");else b.addEventListener(c,d,!1)},oa:function(b,c){if(!b||!b.nodeType)throw Error("element must be a DOM node when calling triggerEvent");var d;"input"===a.a.t(b)&&b.type&&"click"==c.toLowerCase()?(d=b.type,d="checkbox"==d||"radio"==d):d=!1;if(w&&!d)w(b).trigger(c);else if("function"==typeof v.createEvent)if("function"==typeof b.dispatchEvent)d=v.createEvent(h[c]||"HTMLEvents"),d.initEvent(c,!0,!0,s,0,0,0,0,0,!1,!1,!1,!1,0,b),b.dispatchEvent(d);else throw Error("The supplied element doesn't support dispatchEvent");else if(d&&b.click)b.click();else if("undefined"!=typeof b.fireEvent)b.fireEvent("on"+c);else throw Error("Browser doesn't support triggering events");},c:function(b){return a.C(b)?b():b},Xa:function(b){return a.C(b)?b.v():b},Ba:function(b,c,d){if(c){var f=/\S+/g,e=b.className.match(f)||[];a.a.u(c.match(f),function(b){a.a.ea(e,b,d)});b.className=e.join(" ")}},bb:function(b,c){var d=a.a.c(c);if(null===d||d===p)d="";var f=a.f.firstChild(b);!f||3!=f.nodeType||a.f.nextSibling(f)?a.f.T(b,[b.ownerDocument.createTextNode(d)]):f.data=d;a.a.fc(b)},Mb:function(a,b){a.name=b;if(7>=f)try{a.mergeAttributes(v.createElement("<input name='"+a.name+"'/>"),!1)}catch(c){}},fc:function(a){9<=f&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},dc:function(a){if(f){var b=a.style.width;a.style.width=0;a.style.width=b}},sc:function(b,c){b=a.a.c(b);c=a.a.c(c);for(var d=[],f=b;f<=c;f++)d.push(f);return d},S:function(a){for(var b=[],c=0,d=a.length;c<d;c++)b.push(a[c]);return b},yc:6===f,zc:7===f,L:f,xb:function(b,c){for(var d=a.a.S(b.getElementsByTagName("input")).concat(a.a.S(b.getElementsByTagName("textarea"))),f="string"==typeof c?function(a){return a.name===c}:function(a){return c.test(a.name)},e=[],k=d.length-1;0<=k;k--)f(d[k])&&e.push(d[k]);return e},pc:function(b){return"string"==typeof b&&(b=a.a.cb(b))?D&&D.parse?D.parse(b):(new Function("return "+b))():null},eb:function(b,c,d){if(!D||!D.stringify)throw Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");return D.stringify(a.a.c(b),c,d)},qc:function(c,d,f){f=f||{};var e=f.params||{},k=f.includeFields||this.vb,g=c;if("object"==typeof c&&"form"===a.a.t(c))for(var g=c.action,h=k.length-1;0<=h;h--)for(var r=a.a.xb(c,k[h]),E=r.length-1;0<=E;E--)e[r[E].name]=r[E].value;d=a.a.c(d);var y=v.createElement("form");y.style.display="none";y.action=g;y.method="post";for(var p in d)c=v.createElement("input"),c.type="hidden",c.name=p,c.value=a.a.eb(a.a.c(d[p])),y.appendChild(c);b(e,function(a,b){var c=v.createElement("input");c.type="hidden";c.name=a;c.value=b;y.appendChild(c)});v.body.appendChild(y);f.submitter?f.submitter(y):y.submit();setTimeout(function(){y.parentNode.removeChild(y)},0)}}}();a.b("utils",a.a);a.b("utils.arrayForEach",a.a.u);a.b("utils.arrayFirst",a.a.qb);a.b("utils.arrayFilter",a.a.ta);a.b("utils.arrayGetDistinctValues",a.a.rb);a.b("utils.arrayIndexOf",a.a.m);a.b("utils.arrayMap",a.a.Da);a.b("utils.arrayPushAll",a.a.ga);a.b("utils.arrayRemoveItem",a.a.ua);a.b("utils.extend",a.a.extend);a.b("utils.fieldsIncludedWithJsonPost",a.a.vb);a.b("utils.getFormFields",a.a.xb);a.b("utils.peekObservable",a.a.Xa);a.b("utils.postJson",a.a.qc);a.b("utils.parseJson",a.a.pc);a.b("utils.registerEventHandler",a.a.n);a.b("utils.stringifyJson",a.a.eb);a.b("utils.range",a.a.sc);a.b("utils.toggleDomNodeCssClass",a.a.Ba);a.b("utils.triggerEvent",a.a.oa);a.b("utils.unwrapObservable",a.a.c);a.b("utils.objectForEach",a.a.G);a.b("utils.addOrRemoveItem",a.a.ea);a.b("unwrap",a.a.c);Function.prototype.bind||(Function.prototype.bind=function(a){var d=this,c=Array.prototype.slice.call(arguments);a=c.shift();return function(){return d.apply(a,c.concat(Array.prototype.slice.call(arguments)))}});a.a.e=new function(){function a(b,h){var k=b[c];if(!k||"null"===k||!e[k]){if(!h)return p;k=b[c]="ko"+d++;e[k]={}}return e[k]}var d=0,c="__ko__"+(new Date).getTime(),e={};return{get:function(c,d){var e=a(c,!1);return e===p?p:e[d]},set:function(c,d,e){if(e!==p||a(c,!1)!==p)a(c,!0)[d]=e},clear:function(a){var b=a[c];return b?(delete e[b],a[c]=null,!0):!1},F:function(){return d++ +c}}};a.b("utils.domData",a.a.e);a.b("utils.domData.clear",a.a.e.clear);a.a.w=new function(){function b(b,d){var f=a.a.e.get(b,c);f===p&&d&&(f=[],a.a.e.set(b,c,f));return f}function d(c){var e=b(c,!1);if(e)for(var e=e.slice(0),f=0;f<e.length;f++)e[f](c);a.a.e.clear(c);a.a.w.cleanExternalData(c);if(g[c.nodeType])for(e=c.firstChild;c=e;)e=c.nextSibling,8===c.nodeType&&d(c)}var c=a.a.e.F(),e={1:!0,8:!0,9:!0},g={1:!0,9:!0};return{da:function(a,c){if("function"!=typeof c)throw Error("Callback must be a function");b(a,!0).push(c)},Kb:function(d,e){var f=b(d,!1);f&&(a.a.ua(f,e),0==f.length&&a.a.e.set(d,c,p))},R:function(b){if(e[b.nodeType]&&(d(b),g[b.nodeType])){var c=[];a.a.ga(c,b.getElementsByTagName("*"));for(var f=0,m=c.length;f<m;f++)d(c[f])}return b},removeNode:function(b){a.R(b);b.parentNode&&b.parentNode.removeChild(b)},cleanExternalData:function(a){w&&"function"==typeof w.cleanData&&w.cleanData([a])}}};a.R=a.a.w.R;a.removeNode=a.a.w.removeNode;a.b("cleanNode",a.R);a.b("removeNode",a.removeNode);a.b("utils.domNodeDisposal",a.a.w);a.b("utils.domNodeDisposal.addDisposeCallback",a.a.w.da);a.b("utils.domNodeDisposal.removeDisposeCallback",a.a.w.Kb);(function(){a.a.ba=function(b){var d;if(w)if(w.parseHTML)d=w.parseHTML(b)||[];else{if((d=w.clean([b]))&&d[0]){for(b=d[0];b.parentNode&&11!==b.parentNode.nodeType;)b=b.parentNode;b.parentNode&&b.parentNode.removeChild(b)}}else{var c=a.a.cb(b).toLowerCase();d=v.createElement("div");c=c.match(/^<(thead|tbody|tfoot)/)&&[1,"<table>","</table>"]||!c.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!c.indexOf("<td")||!c.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||[0,"",""];b="ignored<div>"+c[1]+b+c[2]+"</div>";for("function"==typeof s.innerShiv?d.appendChild(s.innerShiv(b)):d.innerHTML=b;c[0]--;)d=d.lastChild;d=a.a.S(d.lastChild.childNodes)}return d};a.a.$a=function(b,d){a.a.Ka(b);d=a.a.c(d);if(null!==d&&d!==p)if("string"!=typeof d&&(d=d.toString()),w)w(b).html(d);else for(var c=a.a.ba(d),e=0;e<c.length;e++)b.appendChild(c[e])}})();a.b("utils.parseHtmlFragment",a.a.ba);a.b("utils.setHtml",a.a.$a);a.D=function(){function b(c,d){if(c)if(8==c.nodeType){var g=a.D.Gb(c.nodeValue);null!=g&&d.push({bc:c,mc:g})}else if(1==c.nodeType)for(var g=0,h=c.childNodes,k=h.length;g<k;g++)b(h[g],d)}var d={};return{Ua:function(a){if("function"!=typeof a)throw Error("You can only pass a function to ko.memoization.memoize()");var b=(4294967296*(1+Math.random())|0).toString(16).substring(1)+(4294967296*(1+Math.random())|0).toString(16).substring(1);d[b]=a;return"\x3c!--[ko_memo:"+b+"]--\x3e"},Rb:function(a,b){var g=d[a];if(g===p)throw Error("Couldn't find any memo with ID "+a+". Perhaps it's already been unmemoized.");try{return g.apply(null,b||[]),!0}finally{delete d[a]}},Sb:function(c,d){var g=[];b(c,g);for(var h=0,k=g.length;h<k;h++){var f=g[h].bc,m=[f];d&&a.a.ga(m,d);a.D.Rb(g[h].mc,m);f.nodeValue="";f.parentNode&&f.parentNode.removeChild(f)}},Gb:function(a){return(a=a.match(/^\[ko_memo\:(.*?)\]$/))?a[1]:null}}}();a.b("memoization",a.D);a.b("memoization.memoize",a.D.Ua);a.b("memoization.unmemoize",a.D.Rb);a.b("memoization.parseMemoText",a.D.Gb);a.b("memoization.unmemoizeDomNodeAndDescendants",a.D.Sb);a.La={throttle:function(b,d){b.throttleEvaluation=d;var c=null;return a.j({read:b,write:function(a){clearTimeout(c);c=setTimeout(function(){b(a)},d)}})},rateLimit:function(a,d){var c,e,g;"number"==typeof d?c=d:(c=d.timeout,e=d.method);g="notifyWhenChangesStop"==e?T:S;a.Ta(function(a){return g(a,c)})},notify:function(a,d){a.equalityComparer="always"==d?null:H}};var R={undefined:1,"boolean":1,number:1,string:1};a.b("extenders",a.La);a.Pb=function(b,d,c){this.target=b;this.wa=d;this.ac=c;this.Cb=!1;a.A(this,"dispose",this.K)};a.Pb.prototype.K=function(){this.Cb=!0;this.ac()};a.P=function(){a.a.Aa(this,a.P.fn);this.M={}};var G="change",A={U:function(b,d,c){var e=this;c=c||G;var g=new a.Pb(e,d?b.bind(d):b,function(){a.a.ua(e.M[c],g);e.nb&&e.nb()});e.va&&e.va(c);e.M[c]||(e.M[c]=[]);e.M[c].push(g);return g},notifySubscribers:function(b,d){d=d||G;if(this.Ab(d))try{a.k.Ea();for(var c=this.M[d].slice(0),e=0,g;g=c[e];++e)g.Cb||g.wa(b)}finally{a.k.end()}},Ta:function(b){var d=this,c=a.C(d),e,g,h;d.qa||(d.qa=d.notifySubscribers,d.notifySubscribers=function(a,b){b&&b!==G?"beforeChange"===b?d.kb(a):d.qa(a,b):d.lb(a)});var k=b(function(){c&&h===d&&(h=d());e=!1;d.Pa(g,h)&&d.qa(g=h)});d.lb=function(a){e=!0;h=a;k()};d.kb=function(a){e||(g=a,d.qa(a,"beforeChange"))}},Ab:function(a){return this.M[a]&&this.M[a].length},yb:function(){var b=0;a.a.G(this.M,function(a,c){b+=c.length});return b},Pa:function(a,d){return!this.equalityComparer||!this.equalityComparer(a,d)},extend:function(b){var d=this;b&&a.a.G(b,function(b,e){var g=a.La[b];"function"==typeof g&&(d=g(d,e)||d)});return d}};a.A(A,"subscribe",A.U);a.A(A,"extend",A.extend);a.A(A,"getSubscriptionsCount",A.yb);a.a.xa&&a.a.za(A,Function.prototype);a.P.fn=A;a.Db=function(a){return null!=a&&"function"==typeof a.U&&"function"==typeof a.notifySubscribers};a.b("subscribable",a.P);a.b("isSubscribable",a.Db);a.Y=a.k=function(){function b(a){c.push(e);e=a}function d(){e=c.pop()}var c=[],e,g=0;return{Ea:b,end:d,Jb:function(b){if(e){if(!a.Db(b))throw Error("Only subscribable things can act as dependencies");e.wa(b,b.Vb||(b.Vb=++g))}},B:function(a,c,f){try{return b(),a.apply(c,f||[])}finally{d()}},la:function(){if(e)return e.s.la()},ma:function(){if(e)return e.ma}}}();a.b("computedContext",a.Y);a.b("computedContext.getDependenciesCount",a.Y.la);a.b("computedContext.isInitial",a.Y.ma);a.b("computedContext.isSleeping",a.Y.Ac);a.p=function(b){function d(){if(0<arguments.length)return d.Pa(c,arguments[0])&&(d.X(),c=arguments[0],d.W()),this;a.k.Jb(d);return c}var c=b;a.P.call(d);a.a.Aa(d,a.p.fn);d.v=function(){return c};d.W=function(){d.notifySubscribers(c)};d.X=function(){d.notifySubscribers(c,"beforeChange")};a.A(d,"peek",d.v);a.A(d,"valueHasMutated",d.W);a.A(d,"valueWillMutate",d.X);return d};a.p.fn={equalityComparer:H};var F=a.p.rc="__ko_proto__";a.p.fn[F]=a.p;a.a.xa&&a.a.za(a.p.fn,a.P.fn);a.Ma=function(b,d){return null===b||b===p||b[F]===p?!1:b[F]===d?!0:a.Ma(b[F],d)};a.C=function(b){return a.Ma(b,a.p)};a.Ra=function(b){return"function"==typeof b&&b[F]===a.p||"function"==typeof b&&b[F]===a.j&&b.hc?!0:!1};a.b("observable",a.p);a.b("isObservable",a.C);a.b("isWriteableObservable",a.Ra);a.b("isWritableObservable",a.Ra);a.aa=function(b){b=b||[];if("object"!=typeof b||!("length"in b))throw Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");b=a.p(b);a.a.Aa(b,a.aa.fn);return b.extend({trackArrayChanges:!0})};a.aa.fn={remove:function(b){for(var d=this.v(),c=[],e="function"!=typeof b||a.C(b)?function(a){return a===b}:b,g=0;g<d.length;g++){var h=d[g];e(h)&&(0===c.length&&this.X(),c.push(h),d.splice(g,1),g--)}c.length&&this.W();return c},removeAll:function(b){if(b===p){var d=this.v(),c=d.slice(0);this.X();d.splice(0,d.length);this.W();return c}return b?this.remove(function(c){return 0<=a.a.m(b,c)}):[]},destroy:function(b){var d=this.v(),c="function"!=typeof b||a.C(b)?function(a){return a===b}:b;this.X();for(var e=d.length-1;0<=e;e--)c(d[e])&&(d[e]._destroy=!0);this.W()},destroyAll:function(b){return b===p?this.destroy(function(){return!0}):b?this.destroy(function(d){return 0<=a.a.m(b,d)}):[]},indexOf:function(b){var d=this();return a.a.m(d,b)},replace:function(a,d){var c=this.indexOf(a);0<=c&&(this.X(),this.v()[c]=d,this.W())}};a.a.u("pop push reverse shift sort splice unshift".split(" "),function(b){a.aa.fn[b]=function(){var a=this.v();this.X();this.sb(a,b,arguments);a=a[b].apply(a,arguments);this.W();return a}});a.a.u(["slice"],function(b){a.aa.fn[b]=function(){var a=this();return a[b].apply(a,arguments)}});a.a.xa&&a.a.za(a.aa.fn,a.p.fn);a.b("observableArray",a.aa);var J="arrayChange";a.La.trackArrayChanges=function(b){function d(){if(!c){c=!0;var d=b.notifySubscribers;b.notifySubscribers=function(a,b){b&&b!==G||++g;return d.apply(this,arguments)};var f=[].concat(b.v()||[]);e=null;b.U(function(c){c=[].concat(c||[]);if(b.Ab(J)){var d;if(!e||1<g)e=a.a.Fa(f,c,{sparse:!0});d=e;d.length&&b.notifySubscribers(d,J)}f=c;e=null;g=0})}}if(!b.sb){var c=!1,e=null,g=0,h=b.U;b.U=b.subscribe=function(a,b,c){c===J&&d();return h.apply(this,arguments)};b.sb=function(b,d,m){function l(a,b,c){return q[q.length]={status:a,value:b,index:c}}if(c&&!g){var q=[],h=b.length,t=m.length,z=0;switch(d){case"push":z=h;case"unshift":for(d=0;d<t;d++)l("added",m[d],z+d);break;case"pop":z=h-1;case"shift":h&&l("deleted",b[z],z);break;case"splice":d=Math.min(Math.max(0,0>m[0]?h+m[0]:m[0]),h);for(var h=1===t?h:Math.min(d+(m[1]||0),h),t=d+t-2,z=Math.max(h,t),u=[],r=[],E=2;d<z;++d,++E)d<h&&r.push(l("deleted",b[d],d)),d<t&&u.push(l("added",m[E],d));a.a.wb(r,u);break;default:return}e=q}}}};a.s=a.j=function(b,d,c){function e(){a.a.G(v,function(a,b){b.K()});v={}}function g(){e();C=0;u=!0;n=!1}function h(){var a=f.throttleEvaluation;a&&0<=a?(clearTimeout(P),P=setTimeout(k,a)):f.ib?f.ib():k()}function k(b){if(t){if(E)throw Error("A 'pure' computed must not be called recursively");}else if(!u){if(w&&w()){if(!z){s();return}}else z=!1;t=!0;if(y)try{var c={};a.k.Ea({wa:function(a,b){c[b]||(c[b]=1,++C)},s:f,ma:p});C=0;q=r.call(d)}finally{a.k.end(),t=!1}else try{var e=v,m=C;a.k.Ea({wa:function(a,b){u||(m&&e[b]?(v[b]=e[b],++C,delete e[b],--m):v[b]||(v[b]=a.U(h),++C))},s:f,ma:E?p:!C});v={};C=0;try{var l=d?r.call(d):r()}finally{a.k.end(),m&&a.a.G(e,function(a,b){b.K()}),n=!1}f.Pa(q,l)&&(f.notifySubscribers(q,"beforeChange"),q=l,!0!==b&&f.notifySubscribers(q))}finally{t=!1}C||s()}}function f(){if(0<arguments.length){if("function"===typeof O)O.apply(d,arguments);else throw Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");return this}a.k.Jb(f);n&&k(!0);return q}function m(){n&&!C&&k(!0);return q}function l(){return n||0<C}var q,n=!0,t=!1,z=!1,u=!1,r=b,E=!1,y=!1;r&&"object"==typeof r?(c=r,r=c.read):(c=c||{},r||(r=c.read));if("function"!=typeof r)throw Error("Pass a function that returns the value of the ko.computed");var O=c.write,x=c.disposeWhenNodeIsRemoved||c.o||null,B=c.disposeWhen||c.Ia,w=B,s=g,v={},C=0,P=null;d||(d=c.owner);a.P.call(f);a.a.Aa(f,a.j.fn);f.v=m;f.la=function(){return C};f.hc="function"===typeof c.write;f.K=function(){s()};f.Z=l;var A=f.Ta;f.Ta=function(a){A.call(f,a);f.ib=function(){f.kb(q);n=!0;f.lb(f)}};c.pure?(y=E=!0,f.va=function(){y&&(y=!1,k(!0))},f.nb=function(){f.yb()||(e(),y=n=!0)}):c.deferEvaluation&&(f.va=function(){m();delete f.va});a.A(f,"peek",f.v);a.A(f,"dispose",f.K);a.A(f,"isActive",f.Z);a.A(f,"getDependenciesCount",f.la);x&&(z=!0,x.nodeType&&(w=function(){return!a.a.Ja(x)||B&&B()}));y||c.deferEvaluation||k();x&&l()&&x.nodeType&&(s=function(){a.a.w.Kb(x,s);g()},a.a.w.da(x,s));return f};a.jc=function(b){return a.Ma(b,a.j)};A=a.p.rc;a.j[A]=a.p;a.j.fn={equalityComparer:H};a.j.fn[A]=a.j;a.a.xa&&a.a.za(a.j.fn,a.P.fn);a.b("dependentObservable",a.j);a.b("computed",a.j);a.b("isComputed",a.jc);a.Ib=function(b,d){if("function"===typeof b)return a.s(b,d,{pure:!0});b=a.a.extend({},b);b.pure=!0;return a.s(b,d)};a.b("pureComputed",a.Ib);(function(){function b(a,g,h){h=h||new c;a=g(a);if("object"!=typeof a||null===a||a===p||a instanceof Date||a instanceof String||a instanceof Number||a instanceof Boolean)return a;var k=a instanceof Array?[]:{};h.save(a,k);d(a,function(c){var d=g(a[c]);switch(typeof d){case"boolean":case"number":case"string":case"function":k[c]=d;break;case"object":case"undefined":var l=h.get(d);k[c]=l!==p?l:b(d,g,h)}});return k}function d(a,b){if(a instanceof Array){for(var c=0;c<a.length;c++)b(c);"function"==typeof a.toJSON&&b("toJSON")}else for(c in a)b(c)}function c(){this.keys=[];this.hb=[]}a.Qb=function(c){if(0==arguments.length)throw Error("When calling ko.toJS, pass the object you want to convert.");return b(c,function(b){for(var c=0;a.C(b)&&10>c;c++)b=b();return b})};a.toJSON=function(b,c,d){b=a.Qb(b);return a.a.eb(b,c,d)};c.prototype={save:function(b,c){var d=a.a.m(this.keys,b);0<=d?this.hb[d]=c:(this.keys.push(b),this.hb.push(c))},get:function(b){b=a.a.m(this.keys,b);return 0<=b?this.hb[b]:p}}})();a.b("toJS",a.Qb);a.b("toJSON",a.toJSON);(function(){a.i={q:function(b){switch(a.a.t(b)){case"option":return!0===b.__ko__hasDomDataOptionValue__?a.a.e.get(b,a.d.options.Va):7>=a.a.L?b.getAttributeNode("value")&&b.getAttributeNode("value").specified?b.value:b.text:b.value;case"select":return 0<=b.selectedIndex?a.i.q(b.options[b.selectedIndex]):p;default:return b.value}},ca:function(b,d,c){switch(a.a.t(b)){case"option":switch(typeof d){case"string":a.a.e.set(b,a.d.options.Va,p);"__ko__hasDomDataOptionValue__"in
        b&&delete b.__ko__hasDomDataOptionValue__;b.value=d;break;default:a.a.e.set(b,a.d.options.Va,d),b.__ko__hasDomDataOptionValue__=!0,b.value="number"===typeof d?d:""}break;case"select":if(""===d||null===d)d=p;for(var e=-1,g=0,h=b.options.length,k;g<h;++g)if(k=a.i.q(b.options[g]),k==d||""==k&&d===p){e=g;break}if(c||0<=e||d===p&&1<b.size)b.selectedIndex=e;break;default:if(null===d||d===p)d="";b.value=d}}}})();a.b("selectExtensions",a.i);a.b("selectExtensions.readValue",a.i.q);a.b("selectExtensions.writeValue",a.i.ca);a.h=function(){function b(b){b=a.a.cb(b);123===b.charCodeAt(0)&&(b=b.slice(1,-1));var c=[],d=b.match(e),k,n,t=0;if(d){d.push(",");for(var z=0,u;u=d[z];++z){var r=u.charCodeAt(0);if(44===r){if(0>=t){k&&c.push(n?{key:k,value:n.join("")}:{unknown:k});k=n=t=0;continue}}else if(58===r){if(!n)continue}else if(47===r&&z&&1<u.length)(r=d[z-1].match(g))&&!h[r[0]]&&(b=b.substr(b.indexOf(u)+1),d=b.match(e),d.push(","),z=-1,u="/");else if(40===r||123===r||91===r)++t;else if(41===r||125===r||93===r)--t;else if(!k&&!n){k=34===r||39===r?u.slice(1,-1):u;continue}n?n.push(u):n=[u]}}return c}var d=["true","false","null","undefined"],c=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i,e=RegExp("\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|/(?:[^/\\\\]|\\\\.)*/w*|[^\\s:,/][^,\"'{}()/:[\\]]*[^\\s,\"'{}()/:[\\]]|[^\\s]","g"),g=/[\])"'A-Za-z0-9_$]+$/,h={"in":1,"return":1,"typeof":1},k={};return{ha:[],V:k,Wa:b,ya:function(f,m){function e(b,m){var f;if(!z){var u=a.getBindingHandler(b);if(u&&u.preprocess&&!(m=u.preprocess(m,b,e)))return;if(u=k[b])f=m,0<=a.a.m(d,f)?f=!1:(u=f.match(c),f=null===u?!1:u[1]?"Object("+u[1]+")"+u[2]:f),u=f;u&&h.push("'"+b+"':function(_z){"+f+"=_z}")}t&&(m="function(){return "+m+" }");g.push("'"+b+"':"+m)}m=m||{};var g=[],h=[],t=m.valueAccessors,z=m.bindingParams,u="string"===typeof f?b(f):f;a.a.u(u,function(a){e(a.key||a.unknown,a.value)});h.length&&e("_ko_property_writers","{"+h.join(",")+" }");return g.join(",")},lc:function(a,b){for(var c=0;c<a.length;c++)if(a[c].key==b)return!0;return!1},pa:function(b,c,d,e,k){if(b&&a.C(b))!a.Ra(b)||k&&b.v()===e||b(e);else if((b=c.get("_ko_property_writers"))&&b[d])b[d](e)}}}();a.b("expressionRewriting",a.h);a.b("expressionRewriting.bindingRewriteValidators",a.h.ha);a.b("expressionRewriting.parseObjectLiteral",a.h.Wa);a.b("expressionRewriting.preProcessBindings",a.h.ya);a.b("expressionRewriting._twoWayBindings",a.h.V);a.b("jsonExpressionRewriting",a.h);a.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson",a.h.ya);(function(){function b(a){return 8==a.nodeType&&h.test(g?a.text:a.nodeValue)}function d(a){return 8==a.nodeType&&k.test(g?a.text:a.nodeValue)}function c(a,c){for(var f=a,e=1,k=[];f=f.nextSibling;){if(d(f)&&(e--,0===e))return k;k.push(f);b(f)&&e++}if(!c)throw Error("Cannot find closing comment tag to match: "+a.nodeValue);return null}function e(a,b){var d=c(a,b);return d?0<d.length?d[d.length-1].nextSibling:a.nextSibling:null}var g=v&&"\x3c!--test--\x3e"===v.createComment("test").text,h=g?/^\x3c!--\s*ko(?:\s+([\s\S]+))?\s*--\x3e$/:/^\s*ko(?:\s+([\s\S]+))?\s*$/,k=g?/^\x3c!--\s*\/ko\s*--\x3e$/:/^\s*\/ko\s*$/,f={ul:!0,ol:!0};a.f={Q:{},childNodes:function(a){return b(a)?c(a):a.childNodes},ja:function(c){if(b(c)){c=a.f.childNodes(c);for(var d=0,f=c.length;d<f;d++)a.removeNode(c[d])}else a.a.Ka(c)},T:function(c,d){if(b(c)){a.f.ja(c);for(var f=c.nextSibling,e=0,k=d.length;e<k;e++)f.parentNode.insertBefore(d[e],f)}else a.a.T(c,d)},Hb:function(a,c){b(a)?a.parentNode.insertBefore(c,a.nextSibling):a.firstChild?a.insertBefore(c,a.firstChild):a.appendChild(c)},Bb:function(c,d,f){f?b(c)?c.parentNode.insertBefore(d,f.nextSibling):f.nextSibling?c.insertBefore(d,f.nextSibling):c.appendChild(d):a.f.Hb(c,d)},firstChild:function(a){return b(a)?!a.nextSibling||d(a.nextSibling)?null:a.nextSibling:a.firstChild},nextSibling:function(a){b(a)&&(a=e(a));return a.nextSibling&&d(a.nextSibling)?null:a.nextSibling},gc:b,xc:function(a){return(a=(g?a.text:a.nodeValue).match(h))?a[1]:null},Fb:function(c){if(f[a.a.t(c)]){var k=c.firstChild;if(k){do if(1===k.nodeType){var g;g=k.firstChild;var h=null;if(g){do if(h)h.push(g);else if(b(g)){var t=e(g,!0);t?g=t:h=[g]}else d(g)&&(h=[g]);while(g=g.nextSibling)}if(g=h)for(h=k.nextSibling,t=0;t<g.length;t++)h?c.insertBefore(g[t],h):c.appendChild(g[t])}while(k=k.nextSibling)}}}}})();a.b("virtualElements",a.f);a.b("virtualElements.allowedBindings",a.f.Q);a.b("virtualElements.emptyNode",a.f.ja);a.b("virtualElements.insertAfter",a.f.Bb);a.b("virtualElements.prepend",a.f.Hb);a.b("virtualElements.setDomNodeChildren",a.f.T);(function(){a.J=function(){this.Yb={}};a.a.extend(a.J.prototype,{nodeHasBindings:function(b){switch(b.nodeType){case 1:return null!=b.getAttribute("data-bind")||a.g.getComponentNameForNode(b);case 8:return a.f.gc(b);default:return!1}},getBindings:function(b,d){var c=this.getBindingsString(b,d),c=c?this.parseBindingsString(c,d,b):null;return a.g.mb(c,b,d,!1)},getBindingAccessors:function(b,d){var c=this.getBindingsString(b,d),c=c?this.parseBindingsString(c,d,b,{valueAccessors:!0}):null;return a.g.mb(c,b,d,!0)},getBindingsString:function(b){switch(b.nodeType){case 1:return b.getAttribute("data-bind");case 8:return a.f.xc(b);default:return null}},parseBindingsString:function(b,d,c,e){try{var g=this.Yb,h=b+(e&&e.valueAccessors||""),k;if(!(k=g[h])){var f,m="with($context){with($data||{}){return{"+a.h.ya(b,e)+"}}}";f=new Function("$context","$element",m);k=g[h]=f}return k(d,c)}catch(l){throw l.message="Unable to parse bindings.\nBindings value: "+b+"\nMessage: "+l.message,l;}}});a.J.instance=new a.J})();a.b("bindingProvider",a.J);(function(){function b(a){return function(){return a}}function d(a){return a()}
        function c(b){return a.a.na(a.k.B(b),function(a,c){return function(){return b()[c]}})}function e(a,b){return c(this.getBindings.bind(this,a,b))}function g(b,c,d){var f,e=a.f.firstChild(c),k=a.J.instance,g=k.preprocessNode;if(g){for(;f=e;)e=a.f.nextSibling(f),g.call(k,f);e=a.f.firstChild(c)}for(;f=e;)e=a.f.nextSibling(f),h(b,f,d)}function h(b,c,d){var e=!0,k=1===c.nodeType;k&&a.f.Fb(c);if(k&&d||a.J.instance.nodeHasBindings(c))e=f(c,null,b,d).shouldBindDescendants;e&&!l[a.a.t(c)]&&g(b,c,!k)}function k(b){var c=[],d={},f=[];a.a.G(b,function y(e){if(!d[e]){var k=a.getBindingHandler(e);k&&(k.after&&(f.push(e),a.a.u(k.after,function(c){if(b[c]){if(-1!==a.a.m(f,c))throw Error("Cannot combine the following bindings, because they have a cyclic dependency: "+f.join(", "));y(c)}}),f.length--),c.push({key:e,zb:k}));d[e]=!0}});return c}function f(b,c,f,g){var m=a.a.e.get(b,q);if(!c){if(m)throw Error("You cannot apply bindings multiple times to the same element.");a.a.e.set(b,q,!0)}!m&&g&&a.Ob(b,f);var l;if(c&&"function"!==typeof c)l=c;else{var h=a.J.instance,n=h.getBindingAccessors||e,s=a.j(function(){(l=c?c(f,b):n.call(h,b,f))&&f.I&&f.I();return l},null,{o:b});l&&s.Z()||(s=null)}var v;if(l){var w=s?function(a){return function(){return d(s()[a])}}:function(a){return l[a]},A=function(){return a.a.na(s?s():l,d)};A.get=function(a){return l[a]&&d(w(a))};A.has=function(a){return a in l};g=k(l);a.a.u(g,function(c){var d=c.zb.init,e=c.zb.update,k=c.key;if(8===b.nodeType&&!a.f.Q[k])throw Error("The binding '"+k+"' cannot be used with virtual elements");try{"function"==typeof d&&a.k.B(function(){var a=d(b,w(k),A,f.$data,f);if(a&&a.controlsDescendantBindings){if(v!==p)throw Error("Multiple bindings ("+v+" and "+k+") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");v=k}}),"function"==typeof e&&a.j(function(){e(b,w(k),A,f.$data,f)},null,{o:b})}catch(g){throw g.message='Unable to process binding "'+k+": "+l[k]+'"\nMessage: '+g.message,g;}})}return{shouldBindDescendants:v===p}}
        function m(b){return b&&b instanceof a.N?b:new a.N(b)}a.d={};var l={script:!0};a.getBindingHandler=function(b){return a.d[b]};a.N=function(b,c,d,f){var e=this,k="function"==typeof b&&!a.C(b),g,m=a.j(function(){var g=k?b():b,l=a.a.c(g);c?(c.I&&c.I(),a.a.extend(e,c),m&&(e.I=m)):(e.$parents=[],e.$root=l,e.ko=a);e.$rawData=g;e.$data=l;d&&(e[d]=l);f&&f(e,c,l);return e.$data},null,{Ia:function(){return g&&!a.a.ob(g)},o:!0});m.Z()&&(e.I=m,m.equalityComparer=null,g=[],m.Tb=function(b){g.push(b);a.a.w.da(b,function(b){a.a.ua(g,b);g.length||(m.K(),e.I=m=p)})})};a.N.prototype.createChildContext=function(b,c,d){return new a.N(b,this,c,function(a,b){a.$parentContext=b;a.$parent=b.$data;a.$parents=(b.$parents||[]).slice(0);a.$parents.unshift(a.$parent);d&&d(a)})};a.N.prototype.extend=function(b){return new a.N(this.I||this.$data,this,null,function(c,d){c.$rawData=d.$rawData;a.a.extend(c,"function"==typeof b?b():b)})};var q=a.a.e.F(),n=a.a.e.F();a.Ob=function(b,c){if(2==arguments.length)a.a.e.set(b,n,c),c.I&&c.I.Tb(b);else return a.a.e.get(b,n)};a.ra=function(b,c,d){1===b.nodeType&&a.f.Fb(b);return f(b,c,m(d),!0)};a.Wb=function(d,f,e){e=m(e);return a.ra(d,"function"===typeof f?c(f.bind(null,e,d)):a.a.na(f,b),e)};a.Ca=function(a,b){1!==b.nodeType&&8!==b.nodeType||g(m(a),b,!0)};a.pb=function(a,b){!w&&s.jQuery&&(w=s.jQuery);if(b&&1!==b.nodeType&&8!==b.nodeType)throw Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");b=b||s.document.body;h(m(a),b,!0)};a.Ha=function(b){switch(b.nodeType){case 1:case 8:var c=a.Ob(b);if(c)return c;if(b.parentNode)return a.Ha(b.parentNode)}return p};a.$b=function(b){return(b=a.Ha(b))?b.$data:p};a.b("bindingHandlers",a.d);a.b("applyBindings",a.pb);a.b("applyBindingsToDescendants",a.Ca);a.b("applyBindingAccessorsToNode",a.ra);a.b("applyBindingsToNode",a.Wb);a.b("contextFor",a.Ha);a.b("dataFor",a.$b)})();(function(b){function d(d,f){var e=g.hasOwnProperty(d)?g[d]:b,l;e||(e=g[d]=new a.P,c(d,function(a){h[d]=a;delete g[d];l?e.notifySubscribers(a):setTimeout(function(){e.notifySubscribers(a)},0)}),l=!0);e.U(f)}function c(a,b){e("getConfig",[a],function(c){c?e("loadComponent",[a,c],function(a){b(a)}):b(null)})}function e(c,d,g,l){l||(l=a.g.loaders.slice(0));var h=l.shift();if(h){var n=h[c];if(n){var t=!1;if(n.apply(h,d.concat(function(a){t?g(null):null!==a?g(a):e(c,d,g,l)}))!==b&&(t=!0,!h.suppressLoaderExceptions))throw Error("Component loaders must supply values by invoking the callback, not by returning values synchronously.");}else e(c,d,g,l)}else g(null)}var g={},h={};a.g={get:function(a,c){var e=h.hasOwnProperty(a)?h[a]:b;e?setTimeout(function(){c(e)},0):d(a,c)},tb:function(a){delete h[a]},jb:e};a.g.loaders=[];a.b("components",a.g);a.b("components.get",a.g.get);a.b("components.clearCachedDefinition",a.g.tb)})();(function(){function b(b,c,d,e){function k(){0===--u&&e(h)}var h={},u=2,r=d.template;d=d.viewModel;r?g(c,r,function(c){a.g.jb("loadTemplate",[b,c],function(a){h.template=a;k()})}):k();d?g(c,d,function(c){a.g.jb("loadViewModel",[b,c],function(a){h[f]=a;k()})}):k()}function d(a,b,c){if("function"===typeof b)c(function(a){return new b(a)});else if("function"===typeof b[f])c(b[f]);else if("instance"in b){var e=b.instance;c(function(){return e})}else"viewModel"in b?d(a,b.viewModel,c):a("Unknown viewModel value: "+b)}function c(b){switch(a.a.t(b)){case"script":return a.a.ba(b.text);case"textarea":return a.a.ba(b.value);case"template":if(e(b.content))return a.a.ia(b.content.childNodes)}return a.a.ia(b.childNodes)}function e(a){return s.DocumentFragment?a instanceof DocumentFragment:a&&11===a.nodeType}function g(a,b,c){"string"===typeof b.require?N||s.require?(N||s.require)([b.require],c):a("Uses require, but no AMD loader is present"):c(b)}function h(a){return function(b){throw Error("Component '"+a+"': "+b);}}var k={};a.g.tc=function(b,c){if(!c)throw Error("Invalid configuration for "+b);if(a.g.Qa(b))throw Error("Component "+b+" is already registered");k[b]=c};a.g.Qa=function(a){return a in k};a.g.wc=function(b){delete k[b];a.g.tb(b)};a.g.ub={getConfig:function(a,b){b(k.hasOwnProperty(a)?k[a]:null)},loadComponent:function(a,c,d){var e=h(a);g(e,c,function(c){b(a,e,c,d)})},loadTemplate:function(b,d,f){b=h(b);if("string"===typeof d)f(a.a.ba(d));else if(d instanceof Array)f(d);else if(e(d))f(a.a.S(d.childNodes));else if(d.element)if(d=d.element,s.HTMLElement?d instanceof HTMLElement:d&&d.tagName&&1===d.nodeType)f(c(d));else if("string"===typeof d){var k=v.getElementById(d);k?f(c(k)):b("Cannot find element with ID "+d)}else b("Unknown element type: "+d);else b("Unknown template value: "+d)},loadViewModel:function(a,b,c){d(h(a),b,c)}};var f="createViewModel";a.b("components.register",a.g.tc);a.b("components.isRegistered",a.g.Qa);a.b("components.unregister",a.g.wc);a.b("components.defaultLoader",a.g.ub);a.g.loaders.push(a.g.ub);a.g.Ub=k})();(function(){function b(b,e){var g=b.getAttribute("params");if(g){var g=d.parseBindingsString(g,e,b,{valueAccessors:!0,bindingParams:!0}),g=a.a.na(g,function(d){return a.s(d,null,{o:b})}),h=a.a.na(g,function(d){return d.Z()?a.s(function(){return a.a.c(d())},null,{o:b}):d.v()});h.hasOwnProperty("$raw")||(h.$raw=g);return h}return{$raw:{}}}a.g.getComponentNameForNode=function(b){b=a.a.t(b);return a.g.Qa(b)&&b};a.g.mb=function(c,d,g,h){if(1===d.nodeType){var k=a.g.getComponentNameForNode(d);if(k){c=c||{};if(c.component)throw Error('Cannot use the "component" binding on a custom element matching a component');var f={name:k,params:b(d,g)};c.component=h?function(){return f}:f}}return c};var d=new a.J;9>a.a.L&&(a.g.register=function(a){return function(b){v.createElement(b);return a.apply(this,arguments)}}(a.g.register),v.createDocumentFragment=function(b){return function(){var d=b(),g=a.g.Ub,h;for(h in g)g.hasOwnProperty(h)&&d.createElement(h);return d}}(v.createDocumentFragment))})();(function(){var b=0;a.d.component={init:function(d,c,e,g,h){function k(){var a=f&&f.dispose;"function"===typeof a&&a.call(f);m=null}var f,m;a.a.w.da(d,k);a.s(function(){var e=a.a.c(c()),g,n;"string"===typeof e?g=e:(g=a.a.c(e.name),n=a.a.c(e.params));if(!g)throw Error("No component name specified");var t=m=++b;a.g.get(g,function(b){if(m===t){k();if(!b)throw Error("Unknown component '"+g+"'");var c=b.template;if(!c)throw Error("Component '"+g+"' has no template");c=a.a.ia(c);a.f.T(d,c);var c=n,e=b.createViewModel;b=e?e.call(b,c,{element:d}):c;c=h.createChildContext(b);f=b;a.Ca(c,d)}})},null,{o:d});return{controlsDescendantBindings:!0}}};a.f.Q.component=!0})();var Q={"class":"className","for":"htmlFor"};a.d.attr={update:function(b,d){var c=a.a.c(d())||{};a.a.G(c,function(c,d){d=a.a.c(d);var h=!1===d||null===d||d===p;h&&b.removeAttribute(c);8>=a.a.L&&c in Q?(c=Q[c],h?b.removeAttribute(c):b[c]=d):h||b.setAttribute(c,d.toString());"name"===c&&a.a.Mb(b,h?"":d.toString())})}};(function(){a.d.checked={after:["value","attr"],init:function(b,d,c){function e(){var e=b.checked,k=q?h():e;if(!a.Y.ma()&&(!f||e)){var g=a.k.B(d);m?l!==k?(e&&(a.a.ea(g,k,!0),a.a.ea(g,l,!1)),l=k):a.a.ea(g,k,e):a.h.pa(g,c,"checked",k,!0)}}function g(){var c=a.a.c(d());b.checked=m?0<=a.a.m(c,h()):k?c:h()===c}var h=a.Ib(function(){return c.has("checkedValue")?a.a.c(c.get("checkedValue")):c.has("value")?a.a.c(c.get("value")):b.value}),k="checkbox"==b.type,f="radio"==b.type;if(k||f){var m=k&&a.a.c(d())instanceof Array,l=m?h():p,q=f||m;f&&!b.name&&a.d.uniqueName.init(b,function(){return!0});a.s(e,null,{o:b});a.a.n(b,"click",e);a.s(g,null,{o:b})}}};a.h.V.checked=!0;a.d.checkedValue={update:function(b,d){b.value=a.a.c(d())}}})();a.d.css={update:function(b,d){var c=a.a.c(d());"object"==typeof c?a.a.G(c,function(c,d){d=a.a.c(d);a.a.Ba(b,c,d)}):(c=String(c||""),a.a.Ba(b,b.__ko__cssValue,!1),b.__ko__cssValue=c,a.a.Ba(b,c,!0))}};a.d.enable={update:function(b,d){var c=a.a.c(d());c&&b.disabled?b.removeAttribute("disabled"):c||b.disabled||(b.disabled=!0)}};a.d.disable={update:function(b,d){a.d.enable.update(b,function(){return!a.a.c(d())})}};a.d.event={init:function(b,d,c,e,g){var h=d()||{};a.a.G(h,function(k){"string"==typeof k&&a.a.n(b,k,function(b){var h,l=d()[k];if(l){try{var q=a.a.S(arguments);e=g.$data;q.unshift(e);h=l.apply(e,q)}finally{!0!==h&&(b.preventDefault?b.preventDefault():b.returnValue=!1)}!1===c.get(k+"Bubble")&&(b.cancelBubble=!0,b.stopPropagation&&b.stopPropagation())}})})}};a.d.foreach={Eb:function(b){return function(){var d=b(),c=a.a.Xa(d);if(!c||"number"==typeof c.length)return{foreach:d,templateEngine:a.O.Oa};a.a.c(d);return{foreach:c.data,as:c.as,includeDestroyed:c.includeDestroyed,afterAdd:c.afterAdd,beforeRemove:c.beforeRemove,afterRender:c.afterRender,beforeMove:c.beforeMove,afterMove:c.afterMove,templateEngine:a.O.Oa}}},init:function(b,d){return a.d.template.init(b,a.d.foreach.Eb(d))},update:function(b,d,c,e,g){return a.d.template.update(b,a.d.foreach.Eb(d),c,e,g)}};a.h.ha.foreach=!1;a.f.Q.foreach=!0;a.d.hasfocus={init:function(b,d,c){function e(e){b.__ko_hasfocusUpdating=!0;var f=b.ownerDocument;if("activeElement"in f){var g;try{g=f.activeElement}catch(h){g=f.body}e=g===b}f=d();a.h.pa(f,c,"hasfocus",e,!0);b.__ko_hasfocusLastValue=e;b.__ko_hasfocusUpdating=!1}var g=e.bind(null,!0),h=e.bind(null,!1);a.a.n(b,"focus",g);a.a.n(b,"focusin",g);a.a.n(b,"blur",h);a.a.n(b,"focusout",h)},update:function(b,d){var c=!!a.a.c(d());b.__ko_hasfocusUpdating||b.__ko_hasfocusLastValue===c||(c?b.focus():b.blur(),a.k.B(a.a.oa,null,[b,c?"focusin":"focusout"]))}};a.h.V.hasfocus=!0;a.d.hasFocus=a.d.hasfocus;a.h.V.hasFocus=!0;a.d.html={init:function(){return{controlsDescendantBindings:!0}},update:function(b,d){a.a.$a(b,d())}};I("if");I("ifnot",!1,!0);I("with",!0,!1,function(a,d){return a.createChildContext(d)});var K={};a.d.options={init:function(b){if("select"!==a.a.t(b))throw Error("options binding applies only to SELECT elements");for(;0<b.length;)b.remove(0);return{controlsDescendantBindings:!0}},update:function(b,d,c){function e(){return a.a.ta(b.options,function(a){return a.selected})}function g(a,b,c){var d=typeof b;return"function"==d?b(a):"string"==d?a[b]:c}function h(c,d){if(q.length){var e=0<=a.a.m(q,a.i.q(d[0]));a.a.Nb(d[0],e);n&&!e&&a.k.B(a.a.oa,null,[b,"change"])}}var k=0!=b.length&&b.multiple?b.scrollTop:null,f=a.a.c(d()),m=c.get("optionsIncludeDestroyed");d={};var l,q;q=b.multiple?a.a.Da(e(),a.i.q):0<=b.selectedIndex?[a.i.q(b.options[b.selectedIndex])]:[];f&&("undefined"==typeof f.length&&(f=[f]),l=a.a.ta(f,function(b){return m||b===p||null===b||!a.a.c(b._destroy)}),c.has("optionsCaption")&&(f=a.a.c(c.get("optionsCaption")),null!==f&&f!==p&&l.unshift(K)));var n=!1;d.beforeRemove=function(a){b.removeChild(a)};f=h;c.has("optionsAfterRender")&&(f=function(b,d){h(0,d);a.k.B(c.get("optionsAfterRender"),null,[d[0],b!==K?b:p])});a.a.Za(b,l,function(d,e,f){f.length&&(q=f[0].selected?[a.i.q(f[0])]:[],n=!0);e=b.ownerDocument.createElement("option");d===K?(a.a.bb(e,c.get("optionsCaption")),a.i.ca(e,p)):(f=g(d,c.get("optionsValue"),d),a.i.ca(e,a.a.c(f)),d=g(d,c.get("optionsText"),f),a.a.bb(e,d));return[e]},d,f);a.k.B(function(){c.get("valueAllowUnset")&&c.has("value")?a.i.ca(b,a.a.c(c.get("value")),!0):(b.multiple?q.length&&e().length<q.length:q.length&&0<=b.selectedIndex?a.i.q(b.options[b.selectedIndex])!==q[0]:q.length||0<=b.selectedIndex)&&a.a.oa(b,"change")});a.a.dc(b);k&&20<Math.abs(k-b.scrollTop)&&(b.scrollTop=k)}};a.d.options.Va=a.a.e.F();a.d.selectedOptions={after:["options","foreach"],init:function(b,d,c){a.a.n(b,"change",function(){var e=d(),g=[];a.a.u(b.getElementsByTagName("option"),function(b){b.selected&&g.push(a.i.q(b))});a.h.pa(e,c,"selectedOptions",g)})},update:function(b,d){if("select"!=a.a.t(b))throw Error("values binding applies only to SELECT elements");var c=a.a.c(d());c&&"number"==typeof c.length&&a.a.u(b.getElementsByTagName("option"),function(b){var d=0<=a.a.m(c,a.i.q(b));a.a.Nb(b,d)})}};a.h.V.selectedOptions=!0;a.d.style={update:function(b,d){var c=a.a.c(d()||{});a.a.G(c,function(c,d){d=a.a.c(d);if(null===d||d===p||!1===d)d="";b.style[c]=d})}};a.d.submit={init:function(b,d,c,e,g){if("function"!=typeof d())throw Error("The value for a submit binding must be a function");a.a.n(b,"submit",function(a){var c,e=d();try{c=e.call(g.$data,b)}finally{!0!==c&&(a.preventDefault?a.preventDefault():a.returnValue=!1)}})}};a.d.text={init:function(){return{controlsDescendantBindings:!0}},update:function(b,d){a.a.bb(b,d())}};a.f.Q.text=!0;(function(){if(s&&s.navigator)var b=function(a){if(a)return parseFloat(a[1])},d=s.opera&&s.opera.version&&parseInt(s.opera.version()),c=s.navigator.userAgent,e=b(c.match(/^(?:(?!chrome).)*version\/([^ ]*) safari/i)),g=b(c.match(/Firefox\/([^ ]*)/));if(10>a.a.L)var h=a.a.e.F(),k=a.a.e.F(),f=function(b){var c=this.activeElement;(c=c&&a.a.e.get(c,k))&&c(b)},m=function(b,c){var d=b.ownerDocument;a.a.e.get(d,h)||(a.a.e.set(d,h,!0),a.a.n(d,"selectionchange",f));a.a.e.set(b,k,c)};a.d.textInput={init:function(b,c,f){function k(c,d){a.a.n(b,c,d)}function h(){var d=a.a.c(c());if(null===d||d===p)d="";v!==p&&d===v?setTimeout(h,4):b.value!==d&&(s=d,b.value=d)}function u(){y||(v=b.value,y=setTimeout(r,4))}function r(){clearTimeout(y);v=y=p;var d=b.value;s!==d&&(s=d,a.h.pa(c(),f,"textInput",d))}var s=b.value,y,v;10>a.a.L?(k("propertychange",function(a){"value"===a.propertyName&&r()}),8==a.a.L&&(k("keyup",r),k("keydown",r)),8<=a.a.L&&(m(b,r),k("dragend",u))):(k("input",r),5>e&&"textarea"===a.a.t(b)?(k("keydown",u),k("paste",u),k("cut",u)):11>d?k("keydown",u):4>g&&(k("DOMAutoComplete",r),k("dragdrop",r),k("drop",r)));k("change",r);a.s(h,null,{o:b})}};a.h.V.textInput=!0;a.d.textinput={preprocess:function(a,b,c){c("textInput",a)}}})();a.d.uniqueName={init:function(b,d){if(d()){var c="ko_unique_"+ ++a.d.uniqueName.Zb;a.a.Mb(b,c)}}};a.d.uniqueName.Zb=0;a.d.value={after:["options","foreach"],init:function(b,d,c){if("input"!=b.tagName.toLowerCase()||"checkbox"!=b.type&&"radio"!=b.type){var e=["change"],g=c.get("valueUpdate"),h=!1,k=null;g&&("string"==typeof g&&(g=[g]),a.a.ga(e,g),e=a.a.rb(e));var f=function(){k=null;h=!1;var e=d(),f=a.i.q(b);a.h.pa(e,c,"value",f)};!a.a.L||"input"!=b.tagName.toLowerCase()||"text"!=b.type||"off"==b.autocomplete||b.form&&"off"==b.form.autocomplete||-1!=a.a.m(e,"propertychange")||(a.a.n(b,"propertychange",function(){h=!0}),a.a.n(b,"focus",function(){h=!1}),a.a.n(b,"blur",function(){h&&f()}));a.a.u(e,function(c){var d=f;a.a.vc(c,"after")&&(d=function(){k=a.i.q(b);setTimeout(f,0)},c=c.substring(5));a.a.n(b,c,d)});var m=function(){var e=a.a.c(d()),f=a.i.q(b);if(null!==k&&e===k)setTimeout(m,0);else if(e!==f)if("select"===a.a.t(b)){var g=c.get("valueAllowUnset"),f=function(){a.i.ca(b,e,g)};f();g||e===a.i.q(b)?setTimeout(f,0):a.k.B(a.a.oa,null,[b,"change"])}else a.i.ca(b,e)};a.s(m,null,{o:b})}else a.ra(b,{checkedValue:d})},update:function(){}};a.h.V.value=!0;a.d.visible={update:function(b,d){var c=a.a.c(d()),e="none"!=b.style.display;c&&!e?b.style.display="":!c&&e&&(b.style.display="none")}};(function(b){a.d[b]={init:function(d,c,e,g,h){return a.d.event.init.call(this,d,function(){var a={};a[b]=c();return a},e,g,h)}}})("click");a.H=function(){};a.H.prototype.renderTemplateSource=function(){throw Error("Override renderTemplateSource");};a.H.prototype.createJavaScriptEvaluatorBlock=function(){throw Error("Override createJavaScriptEvaluatorBlock");};a.H.prototype.makeTemplateSource=function(b,d){if("string"==typeof b){d=d||v;var c=d.getElementById(b);if(!c)throw Error("Cannot find template with ID "+b);return new a.r.l(c)}if(1==b.nodeType||8==b.nodeType)return new a.r.fa(b);throw Error("Unknown template type: "+b);};a.H.prototype.renderTemplate=function(a,d,c,e){a=this.makeTemplateSource(a,e);return this.renderTemplateSource(a,d,c)};a.H.prototype.isTemplateRewritten=function(a,d){return!1===this.allowTemplateRewriting?!0:this.makeTemplateSource(a,d).data("isRewritten")};a.H.prototype.rewriteTemplate=function(a,d,c){a=this.makeTemplateSource(a,c);d=d(a.text());a.text(d);a.data("isRewritten",!0)};a.b("templateEngine",a.H);a.fb=function(){function b(b,c,d,k){b=a.h.Wa(b);for(var f=a.h.ha,m=0;m<b.length;m++){var l=b[m].key;if(f.hasOwnProperty(l)){var q=f[l];if("function"===typeof q){if(l=q(b[m].value))throw Error(l);}else if(!q)throw Error("This template engine does not support the '"+l+"' binding within its templates");}}d="ko.__tr_ambtns(function($context,$element){return(function(){return{ "+a.h.ya(b,{valueAccessors:!0})+" } })()},'"+d.toLowerCase()+"')";return k.createJavaScriptEvaluatorBlock(d)+c}var d=/(<([a-z]+\d*)(?:\s+(?!data-bind\s*=\s*)[a-z0-9\-]+(?:=(?:\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi,c=/\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;return{ec:function(b,c,d){c.isTemplateRewritten(b,d)||c.rewriteTemplate(b,function(b){return a.fb.nc(b,c)},d)},nc:function(a,g){return a.replace(d,function(a,c,d,e,l){return b(l,c,d,g)}).replace(c,function(a,c){return b(c,"\x3c!-- ko --\x3e","#comment",g)})},Xb:function(b,c){return a.D.Ua(function(d,k){var f=d.nextSibling;f&&f.nodeName.toLowerCase()===c&&a.ra(f,b,k)})}}}();a.b("__tr_ambtns",a.fb.Xb);(function(){a.r={};a.r.l=function(a){this.l=a};a.r.l.prototype.text=function(){var b=a.a.t(this.l),b="script"===b?"text":"textarea"===b?"value":"innerHTML";if(0==arguments.length)return this.l[b];var d=arguments[0];"innerHTML"===b?a.a.$a(this.l,d):this.l[b]=d};var b=a.a.e.F()+"_";a.r.l.prototype.data=function(c){if(1===arguments.length)return a.a.e.get(this.l,b+c);a.a.e.set(this.l,b+c,arguments[1])};var d=a.a.e.F();a.r.fa=function(a){this.l=a};a.r.fa.prototype=new a.r.l;a.r.fa.prototype.text=function(){if(0==arguments.length){var b=a.a.e.get(this.l,d)||{};b.gb===p&&b.Ga&&(b.gb=b.Ga.innerHTML);return b.gb}a.a.e.set(this.l,d,{gb:arguments[0]})};a.r.l.prototype.nodes=function(){if(0==arguments.length)return(a.a.e.get(this.l,d)||{}).Ga;a.a.e.set(this.l,d,{Ga:arguments[0]})};a.b("templateSources",a.r);a.b("templateSources.domElement",a.r.l);a.b("templateSources.anonymousTemplate",a.r.fa)})();(function(){function b(b,c,d){var e;for(c=a.f.nextSibling(c);b&&(e=b)!==c;)b=a.f.nextSibling(e),d(e,b)}function d(c,d){if(c.length){var e=c[0],g=c[c.length-1],h=e.parentNode,n=a.J.instance,t=n.preprocessNode;if(t){b(e,g,function(a,b){var c=a.previousSibling,d=t.call(n,a);d&&(a===e&&(e=d[0]||b),a===g&&(g=d[d.length-1]||c))});c.length=0;if(!e)return;e===g?c.push(e):(c.push(e,g),a.a.ka(c,h))}b(e,g,function(b){1!==b.nodeType&&8!==b.nodeType||a.pb(d,b)});b(e,g,function(b){1!==b.nodeType&&8!==b.nodeType||a.D.Sb(b,[d])});a.a.ka(c,h)}}function c(a){return a.nodeType?a:0<a.length?a[0]:null}function e(b,e,h,l,q){q=q||{};var n=b&&c(b),n=n&&n.ownerDocument,t=q.templateEngine||g;a.fb.ec(h,t,n);h=t.renderTemplate(h,l,q,n);if("number"!=typeof h.length||0<h.length&&"number"!=typeof h[0].nodeType)throw Error("Template engine must return an array of DOM nodes");n=!1;switch(e){case"replaceChildren":a.f.T(b,h);n=!0;break;case"replaceNode":a.a.Lb(b,h);n=!0;break;case"ignoreTargetNode":break;default:throw Error("Unknown renderMode: "+e);}n&&(d(h,l),q.afterRender&&a.k.B(q.afterRender,null,[h,l.$data]));return h}var g;a.ab=function(b){if(b!=p&&!(b instanceof a.H))throw Error("templateEngine must inherit from ko.templateEngine");g=b};a.Ya=function(b,d,h,l,q){h=h||{};if((h.templateEngine||g)==p)throw Error("Set a template engine before calling renderTemplate");q=q||"replaceChildren";if(l){var n=c(l);return a.j(function(){var g=d&&d instanceof a.N?d:new a.N(a.a.c(d)),p=a.C(b)?b():"function"===typeof b?b(g.$data,g):b,g=e(l,q,p,g,h);"replaceNode"==q&&(l=g,n=c(l))},null,{Ia:function(){return!n||!a.a.Ja(n)},o:n&&"replaceNode"==q?n.parentNode:n})}return a.D.Ua(function(c){a.Ya(b,d,h,c,"replaceNode")})};a.uc=function(b,c,g,h,q){function n(a,b){d(b,s);g.afterRender&&g.afterRender(b,a)}function t(c,d){s=q.createChildContext(c,g.as,function(a){a.$index=d});var f=a.C(b)?b():"function"===typeof b?b(c,s):b;return e(null,"ignoreTargetNode",f,s,g)}var s;return a.j(function(){var b=a.a.c(c)||[];"undefined"==typeof b.length&&(b=[b]);b=a.a.ta(b,function(b){return g.includeDestroyed||b===p||null===b||!a.a.c(b._destroy)});a.k.B(a.a.Za,null,[h,b,t,g,n])},null,{o:h})};var h=a.a.e.F();a.d.template={init:function(b,c){var d=a.a.c(c());"string"==typeof d||d.name?a.f.ja(b):(d=a.f.childNodes(b),d=a.a.oc(d),(new a.r.fa(b)).nodes(d));return{controlsDescendantBindings:!0}},update:function(b,c,d,e,g){var n=c(),t;c=a.a.c(n);d=!0;e=null;"string"==typeof c?c={}:(n=c.name,"if"in c&&(d=a.a.c(c["if"])),d&&"ifnot"in c&&(d=!a.a.c(c.ifnot)),t=a.a.c(c.data));"foreach"in c?e=a.uc(n||b,d&&c.foreach||[],c,b,g):d?(g="data"in c?g.createChildContext(t,c.as):g,e=a.Ya(n||b,g,c,b)):a.f.ja(b);g=e;(t=a.a.e.get(b,h))&&"function"==typeof t.K&&t.K();a.a.e.set(b,h,g&&g.Z()?g:p)}};a.h.ha.template=function(b){b=a.h.Wa(b);return 1==b.length&&b[0].unknown||a.h.lc(b,"name")?null:"This template engine does not support anonymous templates nested within its templates"};a.f.Q.template=!0})();a.b("setTemplateEngine",a.ab);a.b("renderTemplate",a.Ya);a.a.wb=function(a,d,c){if(a.length&&d.length){var e,g,h,k,f;for(e=g=0;(!c||e<c)&&(k=a[g]);++g){for(h=0;f=d[h];++h)if(k.value===f.value){k.moved=f.index;f.moved=k.index;d.splice(h,1);e=h=0;break}e+=h}}};a.a.Fa=function(){function b(b,c,e,g,h){var k=Math.min,f=Math.max,m=[],l,q=b.length,n,p=c.length,s=p-q||1,u=q+p+1,r,v,w;for(l=0;l<=q;l++)for(v=r,m.push(r=[]),w=k(p,l+s),n=f(0,l-1);n<=w;n++)r[n]=n?l?b[l-1]===c[n-1]?v[n-1]:k(v[n]||u,r[n-1]||u)+1:n+1:l+1;k=[];f=[];s=[];l=q;for(n=p;l||n;)p=m[l][n]-1,n&&p===m[l][n-1]?f.push(k[k.length]={status:e,value:c[--n],index:n}):l&&p===m[l-1][n]?s.push(k[k.length]={status:g,value:b[--l],index:l}):(--n,--l,h.sparse||k.push({status:"retained",value:c[n]}));a.a.wb(f,s,10*q);return k.reverse()}return function(a,c,e){e="boolean"===typeof e?{dontLimitMoves:e}:e||{};a=a||[];c=c||[];return a.length<=c.length?b(a,c,"added","deleted",e):b(c,a,"deleted","added",e)}}();a.b("utils.compareArrays",a.a.Fa);(function(){function b(b,d,g,h,k){var f=[],m=a.j(function(){var l=d(g,k,a.a.ka(f,b))||[];0<f.length&&(a.a.Lb(f,l),h&&a.k.B(h,null,[g,l,k]));f.length=0;a.a.ga(f,l)},null,{o:b,Ia:function(){return!a.a.ob(f)}});return{$:f,j:m.Z()?m:p}}var d=a.a.e.F();a.a.Za=function(c,e,g,h,k){function f(b,d){x=q[d];r!==d&&(A[b]=x);x.Na(r++);a.a.ka(x.$,c);s.push(x);w.push(x)}function m(b,c){if(b)for(var d=0,e=c.length;d<e;d++)c[d]&&a.a.u(c[d].$,function(a){b(a,d,c[d].sa)})}e=e||[];h=h||{};var l=a.a.e.get(c,d)===p,q=a.a.e.get(c,d)||[],n=a.a.Da(q,function(a){return a.sa}),t=a.a.Fa(n,e,h.dontLimitMoves),s=[],u=0,r=0,v=[],w=[];e=[];for(var A=[],n=[],x,B=0,D,F;D=t[B];B++)switch(F=D.moved,D.status){case"deleted":F===p&&(x=q[u],x.j&&x.j.K(),v.push.apply(v,a.a.ka(x.$,c)),h.beforeRemove&&(e[B]=x,w.push(x)));u++;break;case"retained":f(B,u++);break;case"added":F!==p?f(B,F):(x={sa:D.value,Na:a.p(r++)},s.push(x),w.push(x),l||(n[B]=x))}m(h.beforeMove,A);a.a.u(v,h.beforeRemove?a.R:a.removeNode);for(var B=0,l=a.f.firstChild(c),G;x=w[B];B++){x.$||a.a.extend(x,b(c,g,x.sa,k,x.Na));for(u=0;t=x.$[u];l=t.nextSibling,G=t,u++)t!==l&&a.f.Bb(c,t,G);!x.ic&&k&&(k(x.sa,x.$,x.Na),x.ic=!0)}m(h.beforeRemove,e);m(h.afterMove,A);m(h.afterAdd,n);a.a.e.set(c,d,s)}})();a.b("utils.setDomNodeChildrenFromArrayMapping",a.a.Za);a.O=function(){this.allowTemplateRewriting=!1};a.O.prototype=new a.H;a.O.prototype.renderTemplateSource=function(b){var d=(9>a.a.L?0:b.nodes)?b.nodes():null;if(d)return a.a.S(d.cloneNode(!0).childNodes);b=b.text();return a.a.ba(b)};a.O.Oa=new a.O;a.ab(a.O.Oa);a.b("nativeTemplateEngine",a.O);(function(){a.Sa=function(){var a=this.kc=function(){if(!w||!w.tmpl)return 0;try{if(0<=w.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,e,g){g=g||{};if(2>a)throw Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");var h=b.data("precompiled");h||(h=b.text()||"",h=w.template(null,"{{ko_with $item.koBindingContext}}"+h+"{{/ko_with}}"),b.data("precompiled",h));b=[e.$data];e=w.extend({koBindingContext:e},g.templateOptions);e=w.tmpl(h,b,e);e.appendTo(v.createElement("div"));w.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){v.write("<script type='text/html' id='"+a+"'>"+b+"\x3c/script>")};0<a&&(w.tmpl.tag.ko_code={open:"__.push($1 || '');"},w.tmpl.tag.ko_with={open:"with($1) {",close:"} "})};a.Sa.prototype=new a.H;var b=new a.Sa;0<b.kc&&a.ab(b);a.b("jqueryTmplTemplateEngine",a.Sa)})()})})();})();
    • marked
      • marked.js
        /**
         * marked - a markdown parser
         * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
         * https://github.com/chjj/marked
         */
        
        ;(function() {
        
        /**
         * Block-Level Grammar
         */
        
        var block = {
          newline: /^\n+/,
          code: /^( {4}[^\n]+\n*)+/,
          fences: noop,
          hr: /^( *[-*_]){3,} *(?:\n+|$)/,
          heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
          nptable: noop,
          lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
          blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
          list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
          html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
          def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
          table: noop,
          paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
          text: /^[^\n]+/
        };
        
        block.bullet = /(?:[*+-]|\d+\.)/;
        block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
        block.item = replace(block.item, 'gm')
          (/bull/g, block.bullet)
          ();
        
        block.list = replace(block.list)
          (/bull/g, block.bullet)
          ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
          ('def', '\\n+(?=' + block.def.source + ')')
          ();
        
        block.blockquote = replace(block.blockquote)
          ('def', block.def)
          ();
        
        block._tag = '(?!(?:'
          + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
          + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
          + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
        
        block.html = replace(block.html)
          ('comment', /<!--[\s\S]*?-->/)
          ('closed', /<(tag)[\s\S]+?<\/\1>/)
          ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
          (/tag/g, block._tag)
          ();
        
        block.paragraph = replace(block.paragraph)
          ('hr', block.hr)
          ('heading', block.heading)
          ('lheading', block.lheading)
          ('blockquote', block.blockquote)
          ('tag', '<' + block._tag)
          ('def', block.def)
          ();
        
        /**
         * Normal Block Grammar
         */
        
        block.normal = merge({}, block);
        
        /**
         * GFM Block Grammar
         */
        
        block.gfm = merge({}, block.normal, {
          fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
          paragraph: /^/
        });
        
        block.gfm.paragraph = replace(block.paragraph)
          ('(?!', '(?!'
            + block.gfm.fences.source.replace('\\1', '\\2') + '|'
            + block.list.source.replace('\\1', '\\3') + '|')
          ();
        
        /**
         * GFM + Tables Block Grammar
         */
        
        block.tables = merge({}, block.gfm, {
          nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
          table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
        });
        
        /**
         * Block Lexer
         */
        
        function Lexer(options) {
          this.tokens = [];
          this.tokens.links = {};
          this.options = options || marked.defaults;
          this.rules = block.normal;
        
          if (this.options.gfm) {
            if (this.options.tables) {
              this.rules = block.tables;
            } else {
              this.rules = block.gfm;
            }
          }
        }
        
        /**
         * Expose Block Rules
         */
        
        Lexer.rules = block;
        
        /**
         * Static Lex Method
         */
        
        Lexer.lex = function(src, options) {
          var lexer = new Lexer(options);
          return lexer.lex(src);
        };
        
        /**
         * Preprocessing
         */
        
        Lexer.prototype.lex = function(src) {
          src = src
            .replace(/\r\n|\r/g, '\n')
            .replace(/\t/g, '    ')
            .replace(/\u00a0/g, ' ')
            .replace(/\u2424/g, '\n');
        
          return this.token(src, true);
        };
        
        /**
         * Lexing
         */
        
        Lexer.prototype.token = function(src, top, bq) {
          var src = src.replace(/^ +$/gm, '')
            , next
            , loose
            , cap
            , bull
            , b
            , item
            , space
            , i
            , l;
        
          while (src) {
            // newline
            if (cap = this.rules.newline.exec(src)) {
              src = src.substring(cap[0].length);
              if (cap[0].length > 1) {
                this.tokens.push({
                  type: 'space'
                });
              }
            }
        
            // code
            if (cap = this.rules.code.exec(src)) {
              src = src.substring(cap[0].length);
              cap = cap[0].replace(/^ {4}/gm, '');
              this.tokens.push({
                type: 'code',
                text: !this.options.pedantic
                  ? cap.replace(/\n+$/, '')
                  : cap
              });
              continue;
            }
        
            // fences (gfm)
            if (cap = this.rules.fences.exec(src)) {
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: 'code',
                lang: cap[2],
                text: cap[3]
              });
              continue;
            }
        
            // heading
            if (cap = this.rules.heading.exec(src)) {
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: 'heading',
                depth: cap[1].length,
                text: cap[2]
              });
              continue;
            }
        
            // table no leading pipe (gfm)
            if (top && (cap = this.rules.nptable.exec(src))) {
              src = src.substring(cap[0].length);
        
              item = {
                type: 'table',
                header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
                align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
                cells: cap[3].replace(/\n$/, '').split('\n')
              };
        
              for (i = 0; i < item.align.length; i++) {
                if (/^ *-+: *$/.test(item.align[i])) {
                  item.align[i] = 'right';
                } else if (/^ *:-+: *$/.test(item.align[i])) {
                  item.align[i] = 'center';
                } else if (/^ *:-+ *$/.test(item.align[i])) {
                  item.align[i] = 'left';
                } else {
                  item.align[i] = null;
                }
              }
        
              for (i = 0; i < item.cells.length; i++) {
                item.cells[i] = item.cells[i].split(/ *\| */);
              }
        
              this.tokens.push(item);
        
              continue;
            }
        
            // lheading
            if (cap = this.rules.lheading.exec(src)) {
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: 'heading',
                depth: cap[2] === '=' ? 1 : 2,
                text: cap[1]
              });
              continue;
            }
        
            // hr
            if (cap = this.rules.hr.exec(src)) {
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: 'hr'
              });
              continue;
            }
        
            // blockquote
            if (cap = this.rules.blockquote.exec(src)) {
              src = src.substring(cap[0].length);
        
              this.tokens.push({
                type: 'blockquote_start'
              });
        
              cap = cap[0].replace(/^ *> ?/gm, '');
        
              // Pass `top` to keep the current
              // "toplevel" state. This is exactly
              // how markdown.pl works.
              this.token(cap, top, true);
        
              this.tokens.push({
                type: 'blockquote_end'
              });
        
              continue;
            }
        
            // list
            if (cap = this.rules.list.exec(src)) {
              src = src.substring(cap[0].length);
              bull = cap[2];
        
              this.tokens.push({
                type: 'list_start',
                ordered: bull.length > 1
              });
        
              // Get each top-level item.
              cap = cap[0].match(this.rules.item);
        
              next = false;
              l = cap.length;
              i = 0;
        
              for (; i < l; i++) {
                item = cap[i];
        
                // Remove the list item's bullet
                // so it is seen as the next token.
                space = item.length;
                item = item.replace(/^ *([*+-]|\d+\.) +/, '');
        
                // Outdent whatever the
                // list item contains. Hacky.
                if (~item.indexOf('\n ')) {
                  space -= item.length;
                  item = !this.options.pedantic
                    ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
                    : item.replace(/^ {1,4}/gm, '');
                }
        
                // Determine whether the next list item belongs here.
                // Backpedal if it does not belong in this list.
                if (this.options.smartLists && i !== l - 1) {
                  b = block.bullet.exec(cap[i + 1])[0];
                  if (bull !== b && !(bull.length > 1 && b.length > 1)) {
                    src = cap.slice(i + 1).join('\n') + src;
                    i = l - 1;
                  }
                }
        
                // Determine whether item is loose or not.
                // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
                // for discount behavior.
                loose = next || /\n\n(?!\s*$)/.test(item);
                if (i !== l - 1) {
                  next = item.charAt(item.length - 1) === '\n';
                  if (!loose) loose = next;
                }
        
                this.tokens.push({
                  type: loose
                    ? 'loose_item_start'
                    : 'list_item_start'
                });
        
                // Recurse.
                this.token(item, false, bq);
        
                this.tokens.push({
                  type: 'list_item_end'
                });
              }
        
              this.tokens.push({
                type: 'list_end'
              });
        
              continue;
            }
        
            // html
            if (cap = this.rules.html.exec(src)) {
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: this.options.sanitize
                  ? 'paragraph'
                  : 'html',
                pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
                text: cap[0]
              });
              continue;
            }
        
            // def
            if ((!bq && top) && (cap = this.rules.def.exec(src))) {
              src = src.substring(cap[0].length);
              this.tokens.links[cap[1].toLowerCase()] = {
                href: cap[2],
                title: cap[3]
              };
              continue;
            }
        
            // table (gfm)
            if (top && (cap = this.rules.table.exec(src))) {
              src = src.substring(cap[0].length);
        
              item = {
                type: 'table',
                header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
                align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
                cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
              };
        
              for (i = 0; i < item.align.length; i++) {
                if (/^ *-+: *$/.test(item.align[i])) {
                  item.align[i] = 'right';
                } else if (/^ *:-+: *$/.test(item.align[i])) {
                  item.align[i] = 'center';
                } else if (/^ *:-+ *$/.test(item.align[i])) {
                  item.align[i] = 'left';
                } else {
                  item.align[i] = null;
                }
              }
        
              for (i = 0; i < item.cells.length; i++) {
                item.cells[i] = item.cells[i]
                  .replace(/^ *\| *| *\| *$/g, '')
                  .split(/ *\| */);
              }
        
              this.tokens.push(item);
        
              continue;
            }
        
            // top-level paragraph
            if (top && (cap = this.rules.paragraph.exec(src))) {
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: 'paragraph',
                text: cap[1].charAt(cap[1].length - 1) === '\n'
                  ? cap[1].slice(0, -1)
                  : cap[1]
              });
              continue;
            }
        
            // text
            if (cap = this.rules.text.exec(src)) {
              // Top-level should never reach here.
              src = src.substring(cap[0].length);
              this.tokens.push({
                type: 'text',
                text: cap[0]
              });
              continue;
            }
        
            if (src) {
              throw new
                Error('Infinite loop on byte: ' + src.charCodeAt(0));
            }
          }
        
          return this.tokens;
        };
        
        /**
         * Inline-Level Grammar
         */
        
        var inline = {
          escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
          autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
          url: noop,
          tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
          link: /^!?\[(inside)\]\(href\)/,
          reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
          nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
          strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
          em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
          code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
          br: /^ {2,}\n(?!\s*$)/,
          del: noop,
          text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
        };
        
        inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
        inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
        
        inline.link = replace(inline.link)
          ('inside', inline._inside)
          ('href', inline._href)
          ();
        
        inline.reflink = replace(inline.reflink)
          ('inside', inline._inside)
          ();
        
        /**
         * Normal Inline Grammar
         */
        
        inline.normal = merge({}, inline);
        
        /**
         * Pedantic Inline Grammar
         */
        
        inline.pedantic = merge({}, inline.normal, {
          strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
          em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
        });
        
        /**
         * GFM Inline Grammar
         */
        
        inline.gfm = merge({}, inline.normal, {
          escape: replace(inline.escape)('])', '~|])')(),
          url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
          del: /^~~(?=\S)([\s\S]*?\S)~~/,
          text: replace(inline.text)
            (']|', '~]|')
            ('|', '|https?://|')
            ()
        });
        
        /**
         * GFM + Line Breaks Inline Grammar
         */
        
        inline.breaks = merge({}, inline.gfm, {
          br: replace(inline.br)('{2,}', '*')(),
          text: replace(inline.gfm.text)('{2,}', '*')()
        });
        
        /**
         * Inline Lexer & Compiler
         */
        
        function InlineLexer(links, options) {
          this.options = options || marked.defaults;
          this.links = links;
          this.rules = inline.normal;
          this.renderer = this.options.renderer || new Renderer;
          this.renderer.options = this.options;
        
          if (!this.links) {
            throw new
              Error('Tokens array requires a `links` property.');
          }
        
          if (this.options.gfm) {
            if (this.options.breaks) {
              this.rules = inline.breaks;
            } else {
              this.rules = inline.gfm;
            }
          } else if (this.options.pedantic) {
            this.rules = inline.pedantic;
          }
        }
        
        /**
         * Expose Inline Rules
         */
        
        InlineLexer.rules = inline;
        
        /**
         * Static Lexing/Compiling Method
         */
        
        InlineLexer.output = function(src, links, options) {
          var inline = new InlineLexer(links, options);
          return inline.output(src);
        };
        
        /**
         * Lexing/Compiling
         */
        
        InlineLexer.prototype.output = function(src) {
          var out = ''
            , link
            , text
            , href
            , cap;
        
          while (src) {
            // escape
            if (cap = this.rules.escape.exec(src)) {
              src = src.substring(cap[0].length);
              out += cap[1];
              continue;
            }
        
            // autolink
            if (cap = this.rules.autolink.exec(src)) {
              src = src.substring(cap[0].length);
              if (cap[2] === '@') {
                text = cap[1].charAt(6) === ':'
                  ? this.mangle(cap[1].substring(7))
                  : this.mangle(cap[1]);
                href = this.mangle('mailto:') + text;
              } else {
                text = escape(cap[1]);
                href = text;
              }
              out += this.renderer.link(href, null, text);
              continue;
            }
        
            // url (gfm)
            if (!this.inLink && (cap = this.rules.url.exec(src))) {
              src = src.substring(cap[0].length);
              text = escape(cap[1]);
              href = text;
              out += this.renderer.link(href, null, text);
              continue;
            }
        
            // tag
            if (cap = this.rules.tag.exec(src)) {
              if (!this.inLink && /^<a /i.test(cap[0])) {
                this.inLink = true;
              } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
                this.inLink = false;
              }
              src = src.substring(cap[0].length);
              out += this.options.sanitize
                ? escape(cap[0])
                : cap[0];
              continue;
            }
        
            // link
            if (cap = this.rules.link.exec(src)) {
              src = src.substring(cap[0].length);
              this.inLink = true;
              out += this.outputLink(cap, {
                href: cap[2],
                title: cap[3]
              });
              this.inLink = false;
              continue;
            }
        
            // reflink, nolink
            if ((cap = this.rules.reflink.exec(src))
                || (cap = this.rules.nolink.exec(src))) {
              src = src.substring(cap[0].length);
              link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
              link = this.links[link.toLowerCase()];
              if (!link || !link.href) {
                out += cap[0].charAt(0);
                src = cap[0].substring(1) + src;
                continue;
              }
              this.inLink = true;
              out += this.outputLink(cap, link);
              this.inLink = false;
              continue;
            }
        
            // strong
            if (cap = this.rules.strong.exec(src)) {
              src = src.substring(cap[0].length);
              out += this.renderer.strong(this.output(cap[2] || cap[1]));
              continue;
            }
        
            // em
            if (cap = this.rules.em.exec(src)) {
              src = src.substring(cap[0].length);
              out += this.renderer.em(this.output(cap[2] || cap[1]));
              continue;
            }
        
            // code
            if (cap = this.rules.code.exec(src)) {
              src = src.substring(cap[0].length);
              out += this.renderer.codespan(escape(cap[2], true));
              continue;
            }
        
            // br
            if (cap = this.rules.br.exec(src)) {
              src = src.substring(cap[0].length);
              out += this.renderer.br();
              continue;
            }
        
            // del (gfm)
            if (cap = this.rules.del.exec(src)) {
              src = src.substring(cap[0].length);
              out += this.renderer.del(this.output(cap[1]));
              continue;
            }
        
            // text
            if (cap = this.rules.text.exec(src)) {
              src = src.substring(cap[0].length);
              out += escape(this.smartypants(cap[0]));
              continue;
            }
        
            if (src) {
              throw new
                Error('Infinite loop on byte: ' + src.charCodeAt(0));
            }
          }
        
          return out;
        };
        
        /**
         * Compile Link
         */
        
        InlineLexer.prototype.outputLink = function(cap, link) {
          var href = escape(link.href)
            , title = link.title ? escape(link.title) : null;
        
          return cap[0].charAt(0) !== '!'
            ? this.renderer.link(href, title, this.output(cap[1]))
            : this.renderer.image(href, title, escape(cap[1]));
        };
        
        /**
         * Smartypants Transformations
         */
        
        InlineLexer.prototype.smartypants = function(text) {
          if (!this.options.smartypants) return text;
          return text
            // em-dashes
            .replace(/--/g, '\u2014')
            // opening singles
            .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
            // closing singles & apostrophes
            .replace(/'/g, '\u2019')
            // opening doubles
            .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
            // closing doubles
            .replace(/"/g, '\u201d')
            // ellipses
            .replace(/\.{3}/g, '\u2026');
        };
        
        /**
         * Mangle Links
         */
        
        InlineLexer.prototype.mangle = function(text) {
          var out = ''
            , l = text.length
            , i = 0
            , ch;
        
          for (; i < l; i++) {
            ch = text.charCodeAt(i);
            if (Math.random() > 0.5) {
              ch = 'x' + ch.toString(16);
            }
            out += '&#' + ch + ';';
          }
        
          return out;
        };
        
        /**
         * Renderer
         */
        
        function Renderer(options) {
          this.options = options || {};
        }
        
        Renderer.prototype.code = function(code, lang, escaped) {
          if (this.options.highlight) {
            var out = this.options.highlight(code, lang);
            if (out != null && out !== code) {
              escaped = true;
              code = out;
            }
          }
        
          if (!lang) {
            return '<pre><code>'
              + (escaped ? code : escape(code, true))
              + '\n</code></pre>';
          }
        
          return '<pre><code class="'
            + this.options.langPrefix
            + escape(lang, true)
            + '">'
            + (escaped ? code : escape(code, true))
            + '\n</code></pre>\n';
        };
        
        Renderer.prototype.blockquote = function(quote) {
          return '<blockquote>\n' + quote + '</blockquote>\n';
        };
        
        Renderer.prototype.html = function(html) {
          return html;
        };
        
        Renderer.prototype.heading = function(text, level, raw) {
          return '<h'
            + level
            + ' id="'
            + this.options.headerPrefix
            + raw.toLowerCase().replace(/[^\w]+/g, '-')
            + '">'
            + text
            + '</h'
            + level
            + '>\n';
        };
        
        Renderer.prototype.hr = function() {
          return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
        };
        
        Renderer.prototype.list = function(body, ordered) {
          var type = ordered ? 'ol' : 'ul';
          return '<' + type + '>\n' + body + '</' + type + '>\n';
        };
        
        Renderer.prototype.listitem = function(text) {
          return '<li>' + text + '</li>\n';
        };
        
        Renderer.prototype.paragraph = function(text) {
          return '<p>' + text + '</p>\n';
        };
        
        Renderer.prototype.table = function(header, body) {
          return '<table>\n'
            + '<thead>\n'
            + header
            + '</thead>\n'
            + '<tbody>\n'
            + body
            + '</tbody>\n'
            + '</table>\n';
        };
        
        Renderer.prototype.tablerow = function(content) {
          return '<tr>\n' + content + '</tr>\n';
        };
        
        Renderer.prototype.tablecell = function(content, flags) {
          var type = flags.header ? 'th' : 'td';
          var tag = flags.align
            ? '<' + type + ' style="text-align:' + flags.align + '">'
            : '<' + type + '>';
          return tag + content + '</' + type + '>\n';
        };
        
        // span level renderer
        Renderer.prototype.strong = function(text) {
          return '<strong>' + text + '</strong>';
        };
        
        Renderer.prototype.em = function(text) {
          return '<em>' + text + '</em>';
        };
        
        Renderer.prototype.codespan = function(text) {
          return '<code>' + text + '</code>';
        };
        
        Renderer.prototype.br = function() {
          return this.options.xhtml ? '<br/>' : '<br>';
        };
        
        Renderer.prototype.del = function(text) {
          return '<del>' + text + '</del>';
        };
        
        Renderer.prototype.link = function(href, title, text) {
          if (this.options.sanitize) {
            try {
              var prot = decodeURIComponent(unescape(href))
                .replace(/[^\w:]/g, '')
                .toLowerCase();
            } catch (e) {
              return '';
            }
            if (prot.indexOf('javascript:') === 0) {
              return '';
            }
          }
          var out = '<a href="' + href + '"';
          if (title) {
            out += ' title="' + title + '"';
          }
          out += '>' + text + '</a>';
          return out;
        };
        
        Renderer.prototype.image = function(href, title, text) {
          var out = '<img src="' + href + '" alt="' + text + '"';
          if (title) {
            out += ' title="' + title + '"';
          }
          out += this.options.xhtml ? '/>' : '>';
          return out;
        };
        
        /**
         * Parsing & Compiling
         */
        
        function Parser(options) {
          this.tokens = [];
          this.token = null;
          this.options = options || marked.defaults;
          this.options.renderer = this.options.renderer || new Renderer;
          this.renderer = this.options.renderer;
          this.renderer.options = this.options;
        }
        
        /**
         * Static Parse Method
         */
        
        Parser.parse = function(src, options, renderer) {
          var parser = new Parser(options, renderer);
          return parser.parse(src);
        };
        
        /**
         * Parse Loop
         */
        
        Parser.prototype.parse = function(src) {
          this.inline = new InlineLexer(src.links, this.options, this.renderer);
          this.tokens = src.reverse();
        
          var out = '';
          while (this.next()) {
            out += this.tok();
          }
        
          return out;
        };
        
        /**
         * Next Token
         */
        
        Parser.prototype.next = function() {
          return this.token = this.tokens.pop();
        };
        
        /**
         * Preview Next Token
         */
        
        Parser.prototype.peek = function() {
          return this.tokens[this.tokens.length - 1] || 0;
        };
        
        /**
         * Parse Text Tokens
         */
        
        Parser.prototype.parseText = function() {
          var body = this.token.text;
        
          while (this.peek().type === 'text') {
            body += '\n' + this.next().text;
          }
        
          return this.inline.output(body);
        };
        
        /**
         * Parse Current Token
         */
        
        Parser.prototype.tok = function() {
          switch (this.token.type) {
            case 'space': {
              return '';
            }
            case 'hr': {
              return this.renderer.hr();
            }
            case 'heading': {
              return this.renderer.heading(
                this.inline.output(this.token.text),
                this.token.depth,
                this.token.text);
            }
            case 'code': {
              return this.renderer.code(this.token.text,
                this.token.lang,
                this.token.escaped);
            }
            case 'table': {
              var header = ''
                , body = ''
                , i
                , row
                , cell
                , flags
                , j;
        
              // header
              cell = '';
              for (i = 0; i < this.token.header.length; i++) {
                flags = { header: true, align: this.token.align[i] };
                cell += this.renderer.tablecell(
                  this.inline.output(this.token.header[i]),
                  { header: true, align: this.token.align[i] }
                );
              }
              header += this.renderer.tablerow(cell);
        
              for (i = 0; i < this.token.cells.length; i++) {
                row = this.token.cells[i];
        
                cell = '';
                for (j = 0; j < row.length; j++) {
                  cell += this.renderer.tablecell(
                    this.inline.output(row[j]),
                    { header: false, align: this.token.align[j] }
                  );
                }
        
                body += this.renderer.tablerow(cell);
              }
              return this.renderer.table(header, body);
            }
            case 'blockquote_start': {
              var body = '';
        
              while (this.next().type !== 'blockquote_end') {
                body += this.tok();
              }
        
              return this.renderer.blockquote(body);
            }
            case 'list_start': {
              var body = ''
                , ordered = this.token.ordered;
        
              while (this.next().type !== 'list_end') {
                body += this.tok();
              }
        
              return this.renderer.list(body, ordered);
            }
            case 'list_item_start': {
              var body = '';
        
              while (this.next().type !== 'list_item_end') {
                body += this.token.type === 'text'
                  ? this.parseText()
                  : this.tok();
              }
        
              return this.renderer.listitem(body);
            }
            case 'loose_item_start': {
              var body = '';
        
              while (this.next().type !== 'list_item_end') {
                body += this.tok();
              }
        
              return this.renderer.listitem(body);
            }
            case 'html': {
              var html = !this.token.pre && !this.options.pedantic
                ? this.inline.output(this.token.text)
                : this.token.text;
              return this.renderer.html(html);
            }
            case 'paragraph': {
              return this.renderer.paragraph(this.inline.output(this.token.text));
            }
            case 'text': {
              return this.renderer.paragraph(this.parseText());
            }
          }
        };
        
        /**
         * Helpers
         */
        
        function escape(html, encode) {
          return html
            .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;');
        }
        
        function unescape(html) {
          return html.replace(/&([#\w]+);/g, function(_, n) {
            n = n.toLowerCase();
            if (n === 'colon') return ':';
            if (n.charAt(0) === '#') {
              return n.charAt(1) === 'x'
                ? String.fromCharCode(parseInt(n.substring(2), 16))
                : String.fromCharCode(+n.substring(1));
            }
            return '';
          });
        }
        
        function replace(regex, opt) {
          regex = regex.source;
          opt = opt || '';
          return function self(name, val) {
            if (!name) return new RegExp(regex, opt);
            val = val.source || val;
            val = val.replace(/(^|[^\[])\^/g, '$1');
            regex = regex.replace(name, val);
            return self;
          };
        }
        
        function noop() {}
        noop.exec = noop;
        
        function merge(obj) {
          var i = 1
            , target
            , key;
        
          for (; i < arguments.length; i++) {
            target = arguments[i];
            for (key in target) {
              if (Object.prototype.hasOwnProperty.call(target, key)) {
                obj[key] = target[key];
              }
            }
          }
        
          return obj;
        }
        
        
        /**
         * Marked
         */
        
        function marked(src, opt, callback) {
          if (callback || typeof opt === 'function') {
            if (!callback) {
              callback = opt;
              opt = null;
            }
        
            opt = merge({}, marked.defaults, opt || {});
        
            var highlight = opt.highlight
              , tokens
              , pending
              , i = 0;
        
            try {
              tokens = Lexer.lex(src, opt)
            } catch (e) {
              return callback(e);
            }
        
            pending = tokens.length;
        
            var done = function(err) {
              if (err) {
                opt.highlight = highlight;
                return callback(err);
              }
        
              var out;
        
              try {
                out = Parser.parse(tokens, opt);
              } catch (e) {
                err = e;
              }
        
              opt.highlight = highlight;
        
              return err
                ? callback(err)
                : callback(null, out);
            };
        
            if (!highlight || highlight.length < 3) {
              return done();
            }
        
            delete opt.highlight;
        
            if (!pending) return done();
        
            for (; i < tokens.length; i++) {
              (function(token) {
                if (token.type !== 'code') {
                  return --pending || done();
                }
                return highlight(token.text, token.lang, function(err, code) {
                  if (err) return done(err);
                  if (code == null || code === token.text) {
                    return --pending || done();
                  }
                  token.text = code;
                  token.escaped = true;
                  --pending || done();
                });
              })(tokens[i]);
            }
        
            return;
          }
          try {
            if (opt) opt = merge({}, marked.defaults, opt);
            return Parser.parse(Lexer.lex(src, opt), opt);
          } catch (e) {
            e.message += '\nPlease report this to https://github.com/chjj/marked.';
            if ((opt || marked.defaults).silent) {
              return '<p>An error occured:</p><pre>'
                + escape(e.message + '', true)
                + '</pre>';
            }
            throw e;
          }
        }
        
        /**
         * Options
         */
        
        marked.options =
        marked.setOptions = function(opt) {
          merge(marked.defaults, opt);
          return marked;
        };
        
        marked.defaults = {
          gfm: true,
          tables: true,
          breaks: false,
          pedantic: false,
          sanitize: false,
          smartLists: false,
          silent: false,
          highlight: null,
          langPrefix: 'lang-',
          smartypants: false,
          headerPrefix: '',
          renderer: new Renderer,
          xhtml: false
        };
        
        /**
         * Expose
         */
        
        marked.Parser = Parser;
        marked.parser = Parser.parse;
        
        marked.Renderer = Renderer;
        
        marked.Lexer = Lexer;
        marked.lexer = Lexer.lex;
        
        marked.InlineLexer = InlineLexer;
        marked.inlineLexer = InlineLexer.output;
        
        marked.parse = marked;
        
        if (typeof module !== 'undefined' && typeof exports === 'object') {
          module.exports = marked;
        } else if (typeof define === 'function' && define.amd) {
          define(function() { return marked; });
        } else {
          this.marked = marked;
        }
        
        }).call(function() {
          return this || (typeof window !== 'undefined' ? window : global);
        }());
        
    • typescript
      • core.d.ts.text
        /// <reference no-default-lib="true"/>
        
        /////////////////////////////
        /// ECMAScript APIs
        /////////////////////////////
        
        declare var NaN: number;
        declare var Infinity: number;
        
        /**
          * Evaluates JavaScript code and executes it. 
          * @param x A String value that contains valid JavaScript code.
          */
        declare function eval(x: string): any;
        
        /**
          * Converts A string to an integer.
          * @param s A string to convert into a number.
          * @param radix A value between 2 and 36 that specifies the base of the number in numString. 
          * If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal.
          * All other strings are considered decimal.
          */
        declare function parseInt(s: string, radix?: number): number;
        
        /**
          * Converts a string to a floating-point number. 
          * @param string A string that contains a floating-point number. 
          */
        declare function parseFloat(string: string): number;
        
        /**
          * Returns a Boolean value that indicates whether a value is the reserved value NaN (not a number). 
          * @param number A numeric value.
          */
        declare function isNaN(number: number): boolean;
        
        /** 
          * Determines whether a supplied number is finite.
          * @param number Any numeric value.
          */
        declare function isFinite(number: number): boolean;
        
        /**
          * Gets the unencoded version of an encoded Uniform Resource Identifier (URI).
          * @param encodedURI A value representing an encoded URI.
          */
        declare function decodeURI(encodedURI: string): string;
        
        /**
          * Gets the unencoded version of an encoded component of a Uniform Resource Identifier (URI).
          * @param encodedURIComponent A value representing an encoded URI component.
          */
        declare function decodeURIComponent(encodedURIComponent: string): string;
        
        /** 
          * Encodes a text string as a valid Uniform Resource Identifier (URI)
          * @param uri A value representing an encoded URI.
          */
        declare function encodeURI(uri: string): string;
        
        /**
          * Encodes a text string as a valid component of a Uniform Resource Identifier (URI).
          * @param uriComponent A value representing an encoded URI component.
          */
        declare function encodeURIComponent(uriComponent: string): string;
        
        interface PropertyDescriptor {
            configurable?: boolean;
            enumerable?: boolean;
            value?: any;
            writable?: boolean;
            get? (): any;
            set? (v: any): void;
        }
        
        interface PropertyDescriptorMap {
            [s: string]: PropertyDescriptor;
        }
        
        interface Object {
            /** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
            constructor: Function;
        
            /** Returns a string representation of an object. */
            toString(): string;
        
            /** Returns a date converted to a string using the current locale. */
            toLocaleString(): string;
        
            /** Returns the primitive value of the specified object. */
            valueOf(): Object;
        
            /**
              * Determines whether an object has a property with the specified name. 
              * @param v A property name.
              */
            hasOwnProperty(v: string): boolean;
        
            /**
              * Determines whether an object exists in another object's prototype chain. 
              * @param v Another object whose prototype chain is to be checked.
              */
            isPrototypeOf(v: Object): boolean;
        
            /** 
              * Determines whether a specified property is enumerable.
              * @param v A property name.
              */
            propertyIsEnumerable(v: string): boolean;
        }
        
        interface ObjectConstructor {
            new (value?: any): Object;
            (): any;
            (value: any): any;
        
            /** A reference to the prototype for a class of objects. */
            prototype: Object;
        
            /** 
              * Returns the prototype of an object. 
              * @param o The object that references the prototype.
              */
            getPrototypeOf(o: any): any;
        
            /**
              * Gets the own property descriptor of the specified object. 
              * An own property descriptor is one that is defined directly on the object and is not inherited from the object's prototype. 
              * @param o Object that contains the property.
              * @param p Name of the property.
            */
            getOwnPropertyDescriptor(o: any, p: string): PropertyDescriptor;
        
            /** 
              * Returns the names of the own properties of an object. The own properties of an object are those that are defined directly 
              * on that object, and are not inherited from the object's prototype. The properties of an object include both fields (objects) and functions.
              * @param o Object that contains the own properties.
              */
            getOwnPropertyNames(o: any): string[];
        
            /** 
              * Creates an object that has the specified prototype, and that optionally contains specified properties.
              * @param o Object to use as a prototype. May be null
              * @param properties JavaScript object that contains one or more property descriptors. 
              */
            create(o: any, properties?: PropertyDescriptorMap): any;
        
            /**
              * Adds a property to an object, or modifies attributes of an existing property. 
              * @param o Object on which to add or modify the property. This can be a native JavaScript object (that is, a user-defined object or a built in object) or a DOM object.
              * @param p The property name.
              * @param attributes Descriptor for the property. It can be for a data property or an accessor property.
              */
            defineProperty(o: any, p: string, attributes: PropertyDescriptor): any;
        
            /**
              * Adds one or more properties to an object, and/or modifies attributes of existing properties. 
              * @param o Object on which to add or modify the properties. This can be a native JavaScript object or a DOM object.
              * @param properties JavaScript object that contains one or more descriptor objects. Each descriptor object describes a data property or an accessor property.
              */
            defineProperties(o: any, properties: PropertyDescriptorMap): any;
        
            /**
              * Prevents the modification of attributes of existing properties, and prevents the addition of new properties.
              * @param o Object on which to lock the attributes. 
              */
            seal<T>(o: T): T;
        
            /**
              * Prevents the modification of existing property attributes and values, and prevents the addition of new properties.
              * @param o Object on which to lock the attributes.
              */
            freeze<T>(o: T): T;
        
            /**
              * Prevents the addition of new properties to an object.
              * @param o Object to make non-extensible. 
              */
            preventExtensions<T>(o: T): T;
        
            /**
              * Returns true if existing property attributes cannot be modified in an object and new properties cannot be added to the object.
              * @param o Object to test. 
              */
            isSealed(o: any): boolean;
        
            /**
              * Returns true if existing property attributes and values cannot be modified in an object, and new properties cannot be added to the object.
              * @param o Object to test.  
              */
            isFrozen(o: any): boolean;
        
            /**
              * Returns a value that indicates whether new properties can be added to an object.
              * @param o Object to test. 
              */
            isExtensible(o: any): boolean;
        
            /**
              * Returns the names of the enumerable properties and methods of an object.
              * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
              */
            keys(o: any): string[];
        }
        
        /**
          * Provides functionality common to all JavaScript objects.
          */
        declare var Object: ObjectConstructor;
        
        /**
          * Creates a new function.
          */
        interface Function {
            /**
              * Calls the function, substituting the specified object for the this value of the function, and the specified array for the arguments of the function.
              * @param thisArg The object to be used as the this object.
              * @param argArray A set of arguments to be passed to the function.
              */
            apply(thisArg: any, argArray?: any): any;
        
            /**
              * Calls a method of an object, substituting another object for the current object.
              * @param thisArg The object to be used as the current object.
              * @param argArray A list of arguments to be passed to the method.
              */
            call(thisArg: any, ...argArray: any[]): any;
        
            /**
              * For a given function, creates a bound function that has the same body as the original function. 
              * The this object of the bound function is associated with the specified object, and has the specified initial parameters.
              * @param thisArg An object to which the this keyword can refer inside the new function.
              * @param argArray A list of arguments to be passed to the new function.
              */
            bind(thisArg: any, ...argArray: any[]): any;
        
            prototype: any;
            length: number;
        
            // Non-standard extensions
            arguments: any;
            caller: Function;
        }
        
        interface FunctionConstructor {
            /**
              * Creates a new function.
              * @param args A list of arguments the function accepts.
              */
            new (...args: string[]): Function;
            (...args: string[]): Function;
            prototype: Function;
        }
        
        declare var Function: FunctionConstructor;
        
        interface IArguments {
            [index: number]: any;
            length: number;
            callee: Function;
        }
        
        interface String {
            /** Returns a string representation of a string. */
            toString(): string;
        
            /**
              * Returns the character at the specified index.
              * @param pos The zero-based index of the desired character.
              */
            charAt(pos: number): string;
        
            /** 
              * Returns the Unicode value of the character at the specified location.
              * @param index The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.
              */
            charCodeAt(index: number): number;
        
            /**
              * Returns a string that contains the concatenation of two or more strings.
              * @param strings The strings to append to the end of the string.  
              */
            concat(...strings: string[]): string;
        
            /**
              * Returns the position of the first occurrence of a substring. 
              * @param searchString The substring to search for in the string
              * @param position The index at which to begin searching the String object. If omitted, search starts at the beginning of the string.
              */
            indexOf(searchString: string, position?: number): number;
        
            /**
              * Returns the last occurrence of a substring in the string.
              * @param searchString The substring to search for.
              * @param position The index at which to begin searching. If omitted, the search begins at the end of the string.
              */
            lastIndexOf(searchString: string, position?: number): number;
        
            /**
              * Determines whether two strings are equivalent in the current locale.
              * @param that String to compare to target string
              */
            localeCompare(that: string): number;
        
            /** 
              * Matches a string with a regular expression, and returns an array containing the results of that search.
              * @param regexp A variable name or string literal containing the regular expression pattern and flags.
              */
            match(regexp: string): RegExpMatchArray;
        
            /** 
              * Matches a string with a regular expression, and returns an array containing the results of that search.
              * @param regexp A regular expression object that contains the regular expression pattern and applicable flags. 
              */
            match(regexp: RegExp): RegExpMatchArray;
        
            /**
              * Replaces text in a string, using a regular expression or search string.
              * @param searchValue A String object or string literal that represents the regular expression
              * @param replaceValue A String object or string literal containing the text to replace for every successful match of rgExp in stringObj.
              */
            replace(searchValue: string, replaceValue: string): string;
        
            /**
              * Replaces text in a string, using a regular expression or search string.
              * @param searchValue A String object or string literal that represents the regular expression
              * @param replaceValue A function that returns the replacement text.
              */
            replace(searchValue: string, replaceValue: (substring: string, ...args: any[]) => string): string;
        
            /**
              * Replaces text in a string, using a regular expression or search string.
              * @param searchValue A Regular Expression object containing the regular expression pattern and applicable flags
              * @param replaceValue A String object or string literal containing the text to replace for every successful match of rgExp in stringObj.
              */
            replace(searchValue: RegExp, replaceValue: string): string;
        
            /**
              * Replaces text in a string, using a regular expression or search string.
              * @param searchValue A Regular Expression object containing the regular expression pattern and applicable flags
              * @param replaceValue A function that returns the replacement text.
              */
            replace(searchValue: RegExp, replaceValue: (substring: string, ...args: any[]) => string): string;
        
            /**
              * Finds the first substring match in a regular expression search.
              * @param regexp The regular expression pattern and applicable flags. 
              */
            search(regexp: string): number;
        
            /**
              * Finds the first substring match in a regular expression search.
              * @param regexp The regular expression pattern and applicable flags. 
              */
            search(regexp: RegExp): number;
        
            /**
              * Returns a section of a string.
              * @param start The index to the beginning of the specified portion of stringObj. 
              * @param end The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end. 
              * If this value is not specified, the substring continues to the end of stringObj.
              */
            slice(start?: number, end?: number): string;
        
            /**
              * Split a string into substrings using the specified separator and return them as an array.
              * @param separator A string that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned. 
              * @param limit A value used to limit the number of elements returned in the array.
              */
            split(separator: string, limit?: number): string[];
        
            /**
              * Split a string into substrings using the specified separator and return them as an array.
              * @param separator A Regular Express that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned. 
              * @param limit A value used to limit the number of elements returned in the array.
              */
            split(separator: RegExp, limit?: number): string[];
        
            /**
              * Returns the substring at the specified location within a String object. 
              * @param start The zero-based index number indicating the beginning of the substring.
              * @param end Zero-based index number indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.
              * If end is omitted, the characters from start through the end of the original string are returned.
              */
            substring(start: number, end?: number): string;
        
            /** Converts all the alphabetic characters in a string to lowercase. */
            toLowerCase(): string;
        
            /** Converts all alphabetic characters to lowercase, taking into account the host environment's current locale. */
            toLocaleLowerCase(): string;
        
            /** Converts all the alphabetic characters in a string to uppercase. */
            toUpperCase(): string;
        
            /** Returns a string where all alphabetic characters have been converted to uppercase, taking into account the host environment's current locale. */
            toLocaleUpperCase(): string;
        
            /** Removes the leading and trailing white space and line terminator characters from a string. */
            trim(): string;
        
            /** Returns the length of a String object. */
            length: number;
        
            // IE extensions
            /**
              * Gets a substring beginning at the specified location and having the specified length.
              * @param from The starting position of the desired substring. The index of the first character in the string is zero.
              * @param length The number of characters to include in the returned substring.
              */
            substr(from: number, length?: number): string;
        
            /** Returns the primitive value of the specified object. */
            valueOf(): string;
        
            [index: number]: string;
        }
        
        interface StringConstructor {
            new (value?: any): String;
            (value?: any): string;
            prototype: String;
            fromCharCode(...codes: number[]): string;
        }
        
        /** 
          * Allows manipulation and formatting of text strings and determination and location of substrings within strings. 
          */
        declare var String: StringConstructor;
        
        interface Boolean {
            /** Returns the primitive value of the specified object. */
            valueOf(): boolean;
        }
        
        interface BooleanConstructor {
            new (value?: any): Boolean;
            (value?: any): boolean;
            prototype: Boolean;
        }
        
        declare var Boolean: BooleanConstructor;
        
        interface Number {
            /**
              * Returns a string representation of an object.
              * @param radix Specifies a radix for converting numeric values to strings. This value is only used for numbers.
              */
            toString(radix?: number): string;
        
            /** 
              * Returns a string representing a number in fixed-point notation.
              * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
              */
            toFixed(fractionDigits?: number): string;
        
            /**
              * Returns a string containing a number represented in exponential notation.
              * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
              */
            toExponential(fractionDigits?: number): string;
        
            /**
              * Returns a string containing a number represented either in exponential or fixed-point notation with a specified number of digits.
              * @param precision Number of significant digits. Must be in the range 1 - 21, inclusive.
              */
            toPrecision(precision?: number): string;
        
            /** Returns the primitive value of the specified object. */
            valueOf(): number;
        }
        
        interface NumberConstructor {
            new (value?: any): Number;
            (value?: any): number;
            prototype: Number;
        
            /** The largest number that can be represented in JavaScript. Equal to approximately 1.79E+308. */
            MAX_VALUE: number;
        
            /** The closest number to zero that can be represented in JavaScript. Equal to approximately 5.00E-324. */
            MIN_VALUE: number;
        
            /** 
              * A value that is not a number.
              * In equality comparisons, NaN does not equal any value, including itself. To test whether a value is equivalent to NaN, use the isNaN function.
              */
            NaN: number;
        
            /** 
              * A value that is less than the largest negative number that can be represented in JavaScript.
              * JavaScript displays NEGATIVE_INFINITY values as -infinity. 
              */
            NEGATIVE_INFINITY: number;
        
            /**
              * A value greater than the largest number that can be represented in JavaScript. 
              * JavaScript displays POSITIVE_INFINITY values as infinity. 
              */
            POSITIVE_INFINITY: number;
        }
        
        /** An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers. */
        declare var Number: NumberConstructor;
        
        interface TemplateStringsArray extends Array<string> {
            raw: string[];
        }
        
        interface Math {
            /** The mathematical constant e. This is Euler's number, the base of natural logarithms. */
            E: number;
            /** The natural logarithm of 10. */
            LN10: number;
            /** The natural logarithm of 2. */
            LN2: number;
            /** The base-2 logarithm of e. */
            LOG2E: number;
            /** The base-10 logarithm of e. */
            LOG10E: number;
            /** Pi. This is the ratio of the circumference of a circle to its diameter. */
            PI: number;
            /** The square root of 0.5, or, equivalently, one divided by the square root of 2. */
            SQRT1_2: number;
            /** The square root of 2. */
            SQRT2: number;
            /**
              * Returns the absolute value of a number (the value without regard to whether it is positive or negative). 
              * For example, the absolute value of -5 is the same as the absolute value of 5.
              * @param x A numeric expression for which the absolute value is needed.
              */
            abs(x: number): number;
            /**
              * Returns the arc cosine (or inverse cosine) of a number. 
              * @param x A numeric expression.
              */
            acos(x: number): number;
            /** 
              * Returns the arcsine of a number. 
              * @param x A numeric expression.
              */
            asin(x: number): number;
            /**
              * Returns the arctangent of a number. 
              * @param x A numeric expression for which the arctangent is needed.
              */
            atan(x: number): number;
            /**
              * Returns the angle (in radians) from the X axis to a point.
              * @param y A numeric expression representing the cartesian y-coordinate.
              * @param x A numeric expression representing the cartesian x-coordinate.
              */
            atan2(y: number, x: number): number;
            /**
              * Returns the smallest number greater than or equal to its numeric argument. 
              * @param x A numeric expression.
              */
            ceil(x: number): number;
            /**
              * Returns the cosine of a number. 
              * @param x A numeric expression that contains an angle measured in radians.
              */
            cos(x: number): number;
            /**
              * Returns e (the base of natural logarithms) raised to a power. 
              * @param x A numeric expression representing the power of e.
              */
            exp(x: number): number;
            /**
              * Returns the greatest number less than or equal to its numeric argument. 
              * @param x A numeric expression.
              */
            floor(x: number): number;
            /**
              * Returns the natural logarithm (base e) of a number. 
              * @param x A numeric expression.
              */
            log(x: number): number;
            /**
              * Returns the larger of a set of supplied numeric expressions. 
              * @param values Numeric expressions to be evaluated.
              */
            max(...values: number[]): number;
            /**
              * Returns the smaller of a set of supplied numeric expressions. 
              * @param values Numeric expressions to be evaluated.
              */
            min(...values: number[]): number;
            /**
              * Returns the value of a base expression taken to a specified power. 
              * @param x The base value of the expression.
              * @param y The exponent value of the expression.
              */
            pow(x: number, y: number): number;
            /** Returns a pseudorandom number between 0 and 1. */
            random(): number;
            /** 
              * Returns a supplied numeric expression rounded to the nearest number.
              * @param x The value to be rounded to the nearest number.
              */
            round(x: number): number;
            /**
              * Returns the sine of a number.
              * @param x A numeric expression that contains an angle measured in radians.
              */
            sin(x: number): number;
            /**
              * Returns the square root of a number.
              * @param x A numeric expression.
              */
            sqrt(x: number): number;
            /**
              * Returns the tangent of a number.
              * @param x A numeric expression that contains an angle measured in radians.
              */
            tan(x: number): number;
        }
        /** An intrinsic object that provides basic mathematics functionality and constants. */
        declare var Math: Math;
        
        /** Enables basic storage and retrieval of dates and times. */
        interface Date {
            /** Returns a string representation of a date. The format of the string depends on the locale. */
            toString(): string;
            /** Returns a date as a string value. */
            toDateString(): string;
            /** Returns a time as a string value. */
            toTimeString(): string;
            /** Returns a value as a string value appropriate to the host environment's current locale. */
            toLocaleString(): string;
            /** Returns a date as a string value appropriate to the host environment's current locale. */
            toLocaleDateString(): string;
            /** Returns a time as a string value appropriate to the host environment's current locale. */
            toLocaleTimeString(): string;
            /** Returns the stored time value in milliseconds since midnight, January 1, 1970 UTC. */
            valueOf(): number;
            /** Gets the time value in milliseconds. */
            getTime(): number;
            /** Gets the year, using local time. */
            getFullYear(): number;
            /** Gets the year using Universal Coordinated Time (UTC). */
            getUTCFullYear(): number;
            /** Gets the month, using local time. */
            getMonth(): number;
            /** Gets the month of a Date object using Universal Coordinated Time (UTC). */
            getUTCMonth(): number;
            /** Gets the day-of-the-month, using local time. */
            getDate(): number;
            /** Gets the day-of-the-month, using Universal Coordinated Time (UTC). */
            getUTCDate(): number;
            /** Gets the day of the week, using local time. */
            getDay(): number;
            /** Gets the day of the week using Universal Coordinated Time (UTC). */
            getUTCDay(): number;
            /** Gets the hours in a date, using local time. */
            getHours(): number;
            /** Gets the hours value in a Date object using Universal Coordinated Time (UTC). */
            getUTCHours(): number;
            /** Gets the minutes of a Date object, using local time. */
            getMinutes(): number;
            /** Gets the minutes of a Date object using Universal Coordinated Time (UTC). */
            getUTCMinutes(): number;
            /** Gets the seconds of a Date object, using local time. */
            getSeconds(): number;
            /** Gets the seconds of a Date object using Universal Coordinated Time (UTC). */
            getUTCSeconds(): number;
            /** Gets the milliseconds of a Date, using local time. */
            getMilliseconds(): number;
            /** Gets the milliseconds of a Date object using Universal Coordinated Time (UTC). */
            getUTCMilliseconds(): number;
            /** Gets the difference in minutes between the time on the local computer and Universal Coordinated Time (UTC). */
            getTimezoneOffset(): number;
            /** 
              * Sets the date and time value in the Date object.
              * @param time A numeric value representing the number of elapsed milliseconds since midnight, January 1, 1970 GMT. 
              */
            setTime(time: number): number;
            /**
              * Sets the milliseconds value in the Date object using local time. 
              * @param ms A numeric value equal to the millisecond value.
              */
            setMilliseconds(ms: number): number;
            /** 
              * Sets the milliseconds value in the Date object using Universal Coordinated Time (UTC).
              * @param ms A numeric value equal to the millisecond value. 
              */
            setUTCMilliseconds(ms: number): number;
        
            /**
              * Sets the seconds value in the Date object using local time. 
              * @param sec A numeric value equal to the seconds value.
              * @param ms A numeric value equal to the milliseconds value.
              */
            setSeconds(sec: number, ms?: number): number;
            /**
              * Sets the seconds value in the Date object using Universal Coordinated Time (UTC).
              * @param sec A numeric value equal to the seconds value.
              * @param ms A numeric value equal to the milliseconds value.
              */
            setUTCSeconds(sec: number, ms?: number): number;
            /**
              * Sets the minutes value in the Date object using local time. 
              * @param min A numeric value equal to the minutes value. 
              * @param sec A numeric value equal to the seconds value. 
              * @param ms A numeric value equal to the milliseconds value.
              */
            setMinutes(min: number, sec?: number, ms?: number): number;
            /**
              * Sets the minutes value in the Date object using Universal Coordinated Time (UTC).
              * @param min A numeric value equal to the minutes value. 
              * @param sec A numeric value equal to the seconds value. 
              * @param ms A numeric value equal to the milliseconds value.
              */
            setUTCMinutes(min: number, sec?: number, ms?: number): number;
            /**
              * Sets the hour value in the Date object using local time.
              * @param hours A numeric value equal to the hours value.
              * @param min A numeric value equal to the minutes value.
              * @param sec A numeric value equal to the seconds value. 
              * @param ms A numeric value equal to the milliseconds value.
              */
            setHours(hours: number, min?: number, sec?: number, ms?: number): number;
            /**
              * Sets the hours value in the Date object using Universal Coordinated Time (UTC).
              * @param hours A numeric value equal to the hours value.
              * @param min A numeric value equal to the minutes value.
              * @param sec A numeric value equal to the seconds value. 
              * @param ms A numeric value equal to the milliseconds value.
              */
            setUTCHours(hours: number, min?: number, sec?: number, ms?: number): number;
            /**
              * Sets the numeric day-of-the-month value of the Date object using local time. 
              * @param date A numeric value equal to the day of the month.
              */
            setDate(date: number): number;
            /** 
              * Sets the numeric day of the month in the Date object using Universal Coordinated Time (UTC).
              * @param date A numeric value equal to the day of the month. 
              */
            setUTCDate(date: number): number;
            /** 
              * Sets the month value in the Date object using local time. 
              * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively. 
              * @param date A numeric value representing the day of the month. If this value is not supplied, the value from a call to the getDate method is used.
              */
            setMonth(month: number, date?: number): number;
            /**
              * Sets the month value in the Date object using Universal Coordinated Time (UTC).
              * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively.
              * @param date A numeric value representing the day of the month. If it is not supplied, the value from a call to the getUTCDate method is used.
              */
            setUTCMonth(month: number, date?: number): number;
            /**
              * Sets the year of the Date object using local time.
              * @param year A numeric value for the year.
              * @param month A zero-based numeric value for the month (0 for January, 11 for December). Must be specified if numDate is specified.
              * @param date A numeric value equal for the day of the month.
              */
            setFullYear(year: number, month?: number, date?: number): number;
            /**
              * Sets the year value in the Date object using Universal Coordinated Time (UTC).
              * @param year A numeric value equal to the year.
              * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively. Must be supplied if numDate is supplied.
              * @param date A numeric value equal to the day of the month.
              */
            setUTCFullYear(year: number, month?: number, date?: number): number;
            /** Returns a date converted to a string using Universal Coordinated Time (UTC). */
            toUTCString(): string;
            /** Returns a date as a string value in ISO format. */
            toISOString(): string;
            /** Used by the JSON.stringify method to enable the transformation of an object's data for JavaScript Object Notation (JSON) serialization. */
            toJSON(key?: any): string;
        }
        
        interface DateConstructor {
            new (): Date;
            new (value: number): Date;
            new (value: string): Date;
            new (year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date;
            (): string;
            prototype: Date;
            /**
              * Parses a string containing a date, and returns the number of milliseconds between that date and midnight, January 1, 1970.
              * @param s A date string
              */
            parse(s: string): number;
            /**
              * Returns the number of milliseconds between midnight, January 1, 1970 Universal Coordinated Time (UTC) (or GMT) and the specified date. 
              * @param year The full year designation is required for cross-century date accuracy. If year is between 0 and 99 is used, then year is assumed to be 1900 + year.
              * @param month The month as an number between 0 and 11 (January to December).
              * @param date The date as an number between 1 and 31.
              * @param hours Must be supplied if minutes is supplied. An number from 0 to 23 (midnight to 11pm) that specifies the hour.
              * @param minutes Must be supplied if seconds is supplied. An number from 0 to 59 that specifies the minutes.
              * @param seconds Must be supplied if milliseconds is supplied. An number from 0 to 59 that specifies the seconds.
              * @param ms An number from 0 to 999 that specifies the milliseconds.
              */
            UTC(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number;
            now(): number;
        }
        
        declare var Date: DateConstructor;
        
        interface RegExpMatchArray extends Array<string> {
            index?: number;
            input?: string;
        }
        
        interface RegExpExecArray extends Array<string> {
            index: number;
            input: string;
        }
        
        interface RegExp {
            /** 
              * Executes a search on a string using a regular expression pattern, and returns an array containing the results of that search.
              * @param string The String object or string literal on which to perform the search.
              */
            exec(string: string): RegExpExecArray;
        
            /** 
              * Returns a Boolean value that indicates whether or not a pattern exists in a searched string.
              * @param string String on which to perform the search.
              */
            test(string: string): boolean;
        
            /** Returns a copy of the text of the regular expression pattern. Read-only. The regExp argument is a Regular expression object. It can be a variable name or a literal. */
            source: string;
        
            /** Returns a Boolean value indicating the state of the global flag (g) used with a regular expression. Default is false. Read-only. */
            global: boolean;
        
            /** Returns a Boolean value indicating the state of the ignoreCase flag (i) used with a regular expression. Default is false. Read-only. */
            ignoreCase: boolean;
        
            /** Returns a Boolean value indicating the state of the multiline flag (m) used with a regular expression. Default is false. Read-only. */
            multiline: boolean;
        
            lastIndex: number;
        
            // Non-standard extensions
            compile(): RegExp;
        }
        
        interface RegExpConstructor {
            new (pattern: string, flags?: string): RegExp;
            (pattern: string, flags?: string): RegExp;
            prototype: RegExp;
        
            // Non-standard extensions
            $1: string;
            $2: string;
            $3: string;
            $4: string;
            $5: string;
            $6: string;
            $7: string;
            $8: string;
            $9: string;
            lastMatch: string;
        }
        
        declare var RegExp: RegExpConstructor;
        
        interface Error {
            name: string;
            message: string;
        }
        
        interface ErrorConstructor {
            new (message?: string): Error;
            (message?: string): Error;
            prototype: Error;
        }
        
        declare var Error: ErrorConstructor;
        
        interface EvalError extends Error {
        }
        
        interface EvalErrorConstructor {
            new (message?: string): EvalError;
            (message?: string): EvalError;
            prototype: EvalError;
        }
        
        declare var EvalError: EvalErrorConstructor;
        
        interface RangeError extends Error {
        }
        
        interface RangeErrorConstructor {
            new (message?: string): RangeError;
            (message?: string): RangeError;
            prototype: RangeError;
        }
        
        declare var RangeError: RangeErrorConstructor;
        
        interface ReferenceError extends Error {
        }
        
        interface ReferenceErrorConstructor {
            new (message?: string): ReferenceError;
            (message?: string): ReferenceError;
            prototype: ReferenceError;
        }
        
        declare var ReferenceError: ReferenceErrorConstructor;
        
        interface SyntaxError extends Error {
        }
        
        interface SyntaxErrorConstructor {
            new (message?: string): SyntaxError;
            (message?: string): SyntaxError;
            prototype: SyntaxError;
        }
        
        declare var SyntaxError: SyntaxErrorConstructor;
        
        interface TypeError extends Error {
        }
        
        interface TypeErrorConstructor {
            new (message?: string): TypeError;
            (message?: string): TypeError;
            prototype: TypeError;
        }
        
        declare var TypeError: TypeErrorConstructor;
        
        interface URIError extends Error {
        }
        
        interface URIErrorConstructor {
            new (message?: string): URIError;
            (message?: string): URIError;
            prototype: URIError;
        }
        
        declare var URIError: URIErrorConstructor;
        
        interface JSON {
            /**
              * Converts a JavaScript Object Notation (JSON) string into an object.
              * @param text A valid JSON string.
              * @param reviver A function that transforms the results. This function is called for each member of the object. 
              * If a member contains nested objects, the nested objects are transformed before the parent object is. 
              */
            parse(text: string, reviver?: (key: any, value: any) => any): any;
            /**
              * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
              * @param value A JavaScript value, usually an object or array, to be converted.
              */
            stringify(value: any): string;
            /**
              * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
              * @param value A JavaScript value, usually an object or array, to be converted.
              * @param replacer A function that transforms the results.
              */
            stringify(value: any, replacer: (key: string, value: any) => any): string;
            /**
              * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
              * @param value A JavaScript value, usually an object or array, to be converted.
              * @param replacer Array that transforms the results.
              */
            stringify(value: any, replacer: any[]): string;
            /**
              * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
              * @param value A JavaScript value, usually an object or array, to be converted.
              * @param replacer A function that transforms the results.
              * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
              */
            stringify(value: any, replacer: (key: string, value: any) => any, space: any): string;
            /**
              * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
              * @param value A JavaScript value, usually an object or array, to be converted.
              * @param replacer Array that transforms the results.
              * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
              */
            stringify(value: any, replacer: any[], space: any): string;
        }
        /**
          * An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
          */
        declare var JSON: JSON;
        
        
        /////////////////////////////
        /// ECMAScript Array API (specially handled by compiler)
        /////////////////////////////
        
        interface Array<T> {
            /**
              * Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.
              */
            length: number;
            /**
              * Returns a string representation of an array.
              */
            toString(): string;
            toLocaleString(): string;
            /**
              * Appends new elements to an array, and returns the new length of the array.
              * @param items New elements of the Array.
              */
            push(...items: T[]): number;
            /**
              * Removes the last element from an array and returns it.
              */
            pop(): T;
            /**
              * Combines two or more arrays.
              * @param items Additional items to add to the end of array1.
              */
            concat<U extends T[]>(...items: U[]): T[];
            /**
              * Combines two or more arrays.
              * @param items Additional items to add to the end of array1.
              */
            concat(...items: T[]): T[];
            /**
              * Adds all the elements of an array separated by the specified separator string.
              * @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.
              */
            join(separator?: string): string;
            /**
              * Reverses the elements in an Array. 
              */
            reverse(): T[];
            /**
              * Removes the first element from an array and returns it.
              */
            shift(): T;
            /** 
              * Returns a section of an array.
              * @param start The beginning of the specified portion of the array.
              * @param end The end of the specified portion of the array.
              */
            slice(start?: number, end?: number): T[];
        
            /**
              * Sorts an array.
              * @param compareFn The name of the function used to determine the order of the elements. If omitted, the elements are sorted in ascending, ASCII character order.
              */
            sort(compareFn?: (a: T, b: T) => number): T[];
        
            /**
              * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
              * @param start The zero-based location in the array from which to start removing elements.
              */
            splice(start: number): T[];
        
            /**
              * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
              * @param start The zero-based location in the array from which to start removing elements.
              * @param deleteCount The number of elements to remove.
              * @param items Elements to insert into the array in place of the deleted elements.
              */
            splice(start: number, deleteCount: number, ...items: T[]): T[];
        
            /**
              * Inserts new elements at the start of an array.
              * @param items  Elements to insert at the start of the Array.
              */
            unshift(...items: T[]): number;
        
            /**
              * Returns the index of the first occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
              */
            indexOf(searchElement: T, fromIndex?: number): number;
        
            /**
              * Returns the index of the last occurrence of a specified value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array.
              */
            lastIndexOf(searchElement: T, fromIndex?: number): number;
        
            /**
              * Determines whether all the members of an array satisfy the specified test.
              * @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
              */
            every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;
        
            /**
              * Determines whether the specified callback function returns true for any element of an array.
              * @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
              */
            some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;
        
            /**
              * Performs the specified action for each element in an array.
              * @param callbackfn  A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array. 
              * @param thisArg  An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
              */
            forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
        
            /**
              * Calls a defined callback function on each element of an array, and returns an array that contains the results.
              * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
              */
            map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
        
            /**
              * Returns the elements of an array that meet the condition specified in a callback function. 
              * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
              */
            filter(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): T[];
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
              */
            reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T;
            /**
              * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
              */
            reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
              */
            reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T;
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
              */
            reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
        
            [n: number]: T;
        }
        
        interface ArrayConstructor {
            new (arrayLength?: number): any[];
            new <T>(arrayLength: number): T[];
            new <T>(...items: T[]): T[];
            (arrayLength?: number): any[];
            <T>(arrayLength: number): T[];
            <T>(...items: T[]): T[];
            isArray(arg: any): boolean;
            prototype: Array<any>;
        }
        
        declare var Array: ArrayConstructor;
        
        interface TypedPropertyDescriptor<T> {
            enumerable?: boolean;
            configurable?: boolean;
            writable?: boolean;
            value?: T;
            get?: () => T;
            set?: (value: T) => void;
        }
        
        declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
        declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
        declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
        declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
        
      • dom.generated.d.ts.text
        /////////////////////////////
        /// IE DOM APIs
        /////////////////////////////
        
        interface Algorithm {
            name?: string;
        }
        
        interface AriaRequestEventInit extends EventInit {
            attributeName?: string;
            attributeValue?: string;
        }
        
        interface ClipboardEventInit extends EventInit {
            data?: string;
            dataType?: string;
        }
        
        interface CommandEventInit extends EventInit {
            commandName?: string;
            detail?: string;
        }
        
        interface CompositionEventInit extends UIEventInit {
            data?: string;
        }
        
        interface ConfirmSiteSpecificExceptionsInformation extends ExceptionInformation {
            arrayOfDomainStrings?: string[];
        }
        
        interface CustomEventInit extends EventInit {
            detail?: any;
        }
        
        interface DeviceAccelerationDict {
            x?: number;
            y?: number;
            z?: number;
        }
        
        interface DeviceRotationRateDict {
            alpha?: number;
            beta?: number;
            gamma?: number;
        }
        
        interface EventInit {
            bubbles?: boolean;
            cancelable?: boolean;
        }
        
        interface ExceptionInformation {
            domain?: string;
        }
        
        interface FocusEventInit extends UIEventInit {
            relatedTarget?: EventTarget;
        }
        
        interface HashChangeEventInit extends EventInit {
            newURL?: string;
            oldURL?: string;
        }
        
        interface KeyAlgorithm {
            name?: string;
        }
        
        interface KeyboardEventInit extends SharedKeyboardAndMouseEventInit {
            key?: string;
            location?: number;
            repeat?: boolean;
        }
        
        interface MouseEventInit extends SharedKeyboardAndMouseEventInit {
            screenX?: number;
            screenY?: number;
            clientX?: number;
            clientY?: number;
            button?: number;
            buttons?: number;
            relatedTarget?: EventTarget;
        }
        
        interface MsZoomToOptions {
            contentX?: number;
            contentY?: number;
            viewportX?: string;
            viewportY?: string;
            scaleFactor?: number;
            animate?: string;
        }
        
        interface MutationObserverInit {
            childList?: boolean;
            attributes?: boolean;
            characterData?: boolean;
            subtree?: boolean;
            attributeOldValue?: boolean;
            characterDataOldValue?: boolean;
            attributeFilter?: string[];
        }
        
        interface ObjectURLOptions {
            oneTimeOnly?: boolean;
        }
        
        interface PointerEventInit extends MouseEventInit {
            pointerId?: number;
            width?: number;
            height?: number;
            pressure?: number;
            tiltX?: number;
            tiltY?: number;
            pointerType?: string;
            isPrimary?: boolean;
        }
        
        interface PositionOptions {
            enableHighAccuracy?: boolean;
            timeout?: number;
            maximumAge?: number;
        }
        
        interface SharedKeyboardAndMouseEventInit extends UIEventInit {
            ctrlKey?: boolean;
            shiftKey?: boolean;
            altKey?: boolean;
            metaKey?: boolean;
            keyModifierStateAltGraph?: boolean;
            keyModifierStateCapsLock?: boolean;
            keyModifierStateFn?: boolean;
            keyModifierStateFnLock?: boolean;
            keyModifierStateHyper?: boolean;
            keyModifierStateNumLock?: boolean;
            keyModifierStateOS?: boolean;
            keyModifierStateScrollLock?: boolean;
            keyModifierStateSuper?: boolean;
            keyModifierStateSymbol?: boolean;
            keyModifierStateSymbolLock?: boolean;
        }
        
        interface StoreExceptionsInformation extends ExceptionInformation {
            siteName?: string;
            explanationString?: string;
            detailURI?: string;
        }
        
        interface StoreSiteSpecificExceptionsInformation extends StoreExceptionsInformation {
            arrayOfDomainStrings?: string[];
        }
        
        interface UIEventInit extends EventInit {
            view?: Window;
            detail?: number;
        }
        
        interface WebGLContextAttributes {
            alpha?: boolean;
            depth?: boolean;
            stencil?: boolean;
            antialias?: boolean;
            premultipliedAlpha?: boolean;
            preserveDrawingBuffer?: boolean;
        }
        
        interface WebGLContextEventInit extends EventInit {
            statusMessage?: string;
        }
        
        interface WheelEventInit extends MouseEventInit {
            deltaX?: number;
            deltaY?: number;
            deltaZ?: number;
            deltaMode?: number;
        }
        
        interface EventListener {
            (evt: Event): void;
        }
        
        interface ANGLE_instanced_arrays {
            drawArraysInstancedANGLE(mode: number, first: number, count: number, primcount: number): void;
            drawElementsInstancedANGLE(mode: number, count: number, type: number, offset: number, primcount: number): void;
            vertexAttribDivisorANGLE(index: number, divisor: number): void;
            VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: number;
        }
        
        declare var ANGLE_instanced_arrays: {
            prototype: ANGLE_instanced_arrays;
            new(): ANGLE_instanced_arrays;
            VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: number;
        }
        
        interface AnalyserNode extends AudioNode {
            fftSize: number;
            frequencyBinCount: number;
            maxDecibels: number;
            minDecibels: number;
            smoothingTimeConstant: number;
            getByteFrequencyData(array: Uint8Array): void;
            getByteTimeDomainData(array: Uint8Array): void;
            getFloatFrequencyData(array: any): void;
            getFloatTimeDomainData(array: any): void;
        }
        
        declare var AnalyserNode: {
            prototype: AnalyserNode;
            new(): AnalyserNode;
        }
        
        interface AnimationEvent extends Event {
            animationName: string;
            elapsedTime: number;
            initAnimationEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, animationNameArg: string, elapsedTimeArg: number): void;
        }
        
        declare var AnimationEvent: {
            prototype: AnimationEvent;
            new(): AnimationEvent;
        }
        
        interface ApplicationCache extends EventTarget {
            oncached: (ev: Event) => any;
            onchecking: (ev: Event) => any;
            ondownloading: (ev: Event) => any;
            onerror: (ev: Event) => any;
            onnoupdate: (ev: Event) => any;
            onobsolete: (ev: Event) => any;
            onprogress: (ev: ProgressEvent) => any;
            onupdateready: (ev: Event) => any;
            status: number;
            abort(): void;
            swapCache(): void;
            update(): void;
            CHECKING: number;
            DOWNLOADING: number;
            IDLE: number;
            OBSOLETE: number;
            UNCACHED: number;
            UPDATEREADY: number;
            addEventListener(type: "cached", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "checking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "downloading", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "noupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "obsolete", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "updateready", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var ApplicationCache: {
            prototype: ApplicationCache;
            new(): ApplicationCache;
            CHECKING: number;
            DOWNLOADING: number;
            IDLE: number;
            OBSOLETE: number;
            UNCACHED: number;
            UPDATEREADY: number;
        }
        
        interface AriaRequestEvent extends Event {
            attributeName: string;
            attributeValue: string;
        }
        
        declare var AriaRequestEvent: {
            prototype: AriaRequestEvent;
            new(type: string, eventInitDict?: AriaRequestEventInit): AriaRequestEvent;
        }
        
        interface Attr extends Node {
            name: string;
            ownerElement: Element;
            specified: boolean;
            value: string;
        }
        
        declare var Attr: {
            prototype: Attr;
            new(): Attr;
        }
        
        interface AudioBuffer {
            duration: number;
            length: number;
            numberOfChannels: number;
            sampleRate: number;
            getChannelData(channel: number): any;
        }
        
        declare var AudioBuffer: {
            prototype: AudioBuffer;
            new(): AudioBuffer;
        }
        
        interface AudioBufferSourceNode extends AudioNode {
            buffer: AudioBuffer;
            loop: boolean;
            loopEnd: number;
            loopStart: number;
            onended: (ev: Event) => any;
            playbackRate: AudioParam;
            start(when?: number, offset?: number, duration?: number): void;
            stop(when?: number): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var AudioBufferSourceNode: {
            prototype: AudioBufferSourceNode;
            new(): AudioBufferSourceNode;
        }
        
        interface AudioContext extends EventTarget {
            currentTime: number;
            destination: AudioDestinationNode;
            listener: AudioListener;
            sampleRate: number;
            createAnalyser(): AnalyserNode;
            createBiquadFilter(): BiquadFilterNode;
            createBuffer(numberOfChannels: number, length: number, sampleRate: number): AudioBuffer;
            createBufferSource(): AudioBufferSourceNode;
            createChannelMerger(numberOfInputs?: number): ChannelMergerNode;
            createChannelSplitter(numberOfOutputs?: number): ChannelSplitterNode;
            createConvolver(): ConvolverNode;
            createDelay(maxDelayTime?: number): DelayNode;
            createDynamicsCompressor(): DynamicsCompressorNode;
            createGain(): GainNode;
            createMediaElementSource(mediaElement: HTMLMediaElement): MediaElementAudioSourceNode;
            createOscillator(): OscillatorNode;
            createPanner(): PannerNode;
            createPeriodicWave(real: any, imag: any): PeriodicWave;
            createScriptProcessor(bufferSize?: number, numberOfInputChannels?: number, numberOfOutputChannels?: number): ScriptProcessorNode;
            createStereoPanner(): StereoPannerNode;
            createWaveShaper(): WaveShaperNode;
            decodeAudioData(audioData: ArrayBuffer, successCallback: DecodeSuccessCallback, errorCallback?: DecodeErrorCallback): void;
        }
        
        declare var AudioContext: {
            prototype: AudioContext;
            new(): AudioContext;
        }
        
        interface AudioDestinationNode extends AudioNode {
            maxChannelCount: number;
        }
        
        declare var AudioDestinationNode: {
            prototype: AudioDestinationNode;
            new(): AudioDestinationNode;
        }
        
        interface AudioListener {
            dopplerFactor: number;
            speedOfSound: number;
            setOrientation(x: number, y: number, z: number, xUp: number, yUp: number, zUp: number): void;
            setPosition(x: number, y: number, z: number): void;
            setVelocity(x: number, y: number, z: number): void;
        }
        
        declare var AudioListener: {
            prototype: AudioListener;
            new(): AudioListener;
        }
        
        interface AudioNode extends EventTarget {
            channelCount: number;
            channelCountMode: string;
            channelInterpretation: string;
            context: AudioContext;
            numberOfInputs: number;
            numberOfOutputs: number;
            connect(destination: AudioNode, output?: number, input?: number): void;
            disconnect(output?: number): void;
        }
        
        declare var AudioNode: {
            prototype: AudioNode;
            new(): AudioNode;
        }
        
        interface AudioParam {
            defaultValue: number;
            value: number;
            cancelScheduledValues(startTime: number): void;
            exponentialRampToValueAtTime(value: number, endTime: number): void;
            linearRampToValueAtTime(value: number, endTime: number): void;
            setTargetAtTime(target: number, startTime: number, timeConstant: number): void;
            setValueAtTime(value: number, startTime: number): void;
            setValueCurveAtTime(values: any, startTime: number, duration: number): void;
        }
        
        declare var AudioParam: {
            prototype: AudioParam;
            new(): AudioParam;
        }
        
        interface AudioProcessingEvent extends Event {
            inputBuffer: AudioBuffer;
            outputBuffer: AudioBuffer;
            playbackTime: number;
        }
        
        declare var AudioProcessingEvent: {
            prototype: AudioProcessingEvent;
            new(): AudioProcessingEvent;
        }
        
        interface AudioTrack {
            enabled: boolean;
            id: string;
            kind: string;
            label: string;
            language: string;
            sourceBuffer: SourceBuffer;
        }
        
        declare var AudioTrack: {
            prototype: AudioTrack;
            new(): AudioTrack;
        }
        
        interface AudioTrackList extends EventTarget {
            length: number;
            onaddtrack: (ev: TrackEvent) => any;
            onchange: (ev: Event) => any;
            onremovetrack: (ev: TrackEvent) => any;
            getTrackById(id: string): AudioTrack;
            item(index: number): AudioTrack;
            addEventListener(type: "addtrack", listener: (ev: TrackEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "removetrack", listener: (ev: TrackEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
            [index: number]: AudioTrack;
        }
        
        declare var AudioTrackList: {
            prototype: AudioTrackList;
            new(): AudioTrackList;
        }
        
        interface BarProp {
            visible: boolean;
        }
        
        declare var BarProp: {
            prototype: BarProp;
            new(): BarProp;
        }
        
        interface BeforeUnloadEvent extends Event {
            returnValue: any;
        }
        
        declare var BeforeUnloadEvent: {
            prototype: BeforeUnloadEvent;
            new(): BeforeUnloadEvent;
        }
        
        interface BiquadFilterNode extends AudioNode {
            Q: AudioParam;
            detune: AudioParam;
            frequency: AudioParam;
            gain: AudioParam;
            type: string;
            getFrequencyResponse(frequencyHz: any, magResponse: any, phaseResponse: any): void;
        }
        
        declare var BiquadFilterNode: {
            prototype: BiquadFilterNode;
            new(): BiquadFilterNode;
        }
        
        interface Blob {
            size: number;
            type: string;
            msClose(): void;
            msDetachStream(): any;
            slice(start?: number, end?: number, contentType?: string): Blob;
        }
        
        declare var Blob: {
            prototype: Blob;
            new (blobParts?: any[], options?: BlobPropertyBag): Blob;
        }
        
        interface CDATASection extends Text {
        }
        
        declare var CDATASection: {
            prototype: CDATASection;
            new(): CDATASection;
        }
        
        interface CSS {
            supports(property: string, value?: string): boolean;
        }
        declare var CSS: CSS;
        
        interface CSSConditionRule extends CSSGroupingRule {
            conditionText: string;
        }
        
        declare var CSSConditionRule: {
            prototype: CSSConditionRule;
            new(): CSSConditionRule;
        }
        
        interface CSSFontFaceRule extends CSSRule {
            style: CSSStyleDeclaration;
        }
        
        declare var CSSFontFaceRule: {
            prototype: CSSFontFaceRule;
            new(): CSSFontFaceRule;
        }
        
        interface CSSGroupingRule extends CSSRule {
            cssRules: CSSRuleList;
            deleteRule(index?: number): void;
            insertRule(rule: string, index?: number): number;
        }
        
        declare var CSSGroupingRule: {
            prototype: CSSGroupingRule;
            new(): CSSGroupingRule;
        }
        
        interface CSSImportRule extends CSSRule {
            href: string;
            media: MediaList;
            styleSheet: CSSStyleSheet;
        }
        
        declare var CSSImportRule: {
            prototype: CSSImportRule;
            new(): CSSImportRule;
        }
        
        interface CSSKeyframeRule extends CSSRule {
            keyText: string;
            style: CSSStyleDeclaration;
        }
        
        declare var CSSKeyframeRule: {
            prototype: CSSKeyframeRule;
            new(): CSSKeyframeRule;
        }
        
        interface CSSKeyframesRule extends CSSRule {
            cssRules: CSSRuleList;
            name: string;
            appendRule(rule: string): void;
            deleteRule(rule: string): void;
            findRule(rule: string): CSSKeyframeRule;
        }
        
        declare var CSSKeyframesRule: {
            prototype: CSSKeyframesRule;
            new(): CSSKeyframesRule;
        }
        
        interface CSSMediaRule extends CSSConditionRule {
            media: MediaList;
        }
        
        declare var CSSMediaRule: {
            prototype: CSSMediaRule;
            new(): CSSMediaRule;
        }
        
        interface CSSNamespaceRule extends CSSRule {
            namespaceURI: string;
            prefix: string;
        }
        
        declare var CSSNamespaceRule: {
            prototype: CSSNamespaceRule;
            new(): CSSNamespaceRule;
        }
        
        interface CSSPageRule extends CSSRule {
            pseudoClass: string;
            selector: string;
            selectorText: string;
            style: CSSStyleDeclaration;
        }
        
        declare var CSSPageRule: {
            prototype: CSSPageRule;
            new(): CSSPageRule;
        }
        
        interface CSSRule {
            cssText: string;
            parentRule: CSSRule;
            parentStyleSheet: CSSStyleSheet;
            type: number;
            CHARSET_RULE: number;
            FONT_FACE_RULE: number;
            IMPORT_RULE: number;
            KEYFRAMES_RULE: number;
            KEYFRAME_RULE: number;
            MEDIA_RULE: number;
            NAMESPACE_RULE: number;
            PAGE_RULE: number;
            STYLE_RULE: number;
            SUPPORTS_RULE: number;
            UNKNOWN_RULE: number;
            VIEWPORT_RULE: number;
        }
        
        declare var CSSRule: {
            prototype: CSSRule;
            new(): CSSRule;
            CHARSET_RULE: number;
            FONT_FACE_RULE: number;
            IMPORT_RULE: number;
            KEYFRAMES_RULE: number;
            KEYFRAME_RULE: number;
            MEDIA_RULE: number;
            NAMESPACE_RULE: number;
            PAGE_RULE: number;
            STYLE_RULE: number;
            SUPPORTS_RULE: number;
            UNKNOWN_RULE: number;
            VIEWPORT_RULE: number;
        }
        
        interface CSSRuleList {
            length: number;
            item(index: number): CSSRule;
            [index: number]: CSSRule;
        }
        
        declare var CSSRuleList: {
            prototype: CSSRuleList;
            new(): CSSRuleList;
        }
        
        interface CSSStyleDeclaration {
            alignContent: string;
            alignItems: string;
            alignSelf: string;
            alignmentBaseline: string;
            animation: string;
            animationDelay: string;
            animationDirection: string;
            animationDuration: string;
            animationFillMode: string;
            animationIterationCount: string;
            animationName: string;
            animationPlayState: string;
            animationTimingFunction: string;
            backfaceVisibility: string;
            background: string;
            backgroundAttachment: string;
            backgroundClip: string;
            backgroundColor: string;
            backgroundImage: string;
            backgroundOrigin: string;
            backgroundPosition: string;
            backgroundPositionX: string;
            backgroundPositionY: string;
            backgroundRepeat: string;
            backgroundSize: string;
            baselineShift: string;
            border: string;
            borderBottom: string;
            borderBottomColor: string;
            borderBottomLeftRadius: string;
            borderBottomRightRadius: string;
            borderBottomStyle: string;
            borderBottomWidth: string;
            borderCollapse: string;
            borderColor: string;
            borderImage: string;
            borderImageOutset: string;
            borderImageRepeat: string;
            borderImageSlice: string;
            borderImageSource: string;
            borderImageWidth: string;
            borderLeft: string;
            borderLeftColor: string;
            borderLeftStyle: string;
            borderLeftWidth: string;
            borderRadius: string;
            borderRight: string;
            borderRightColor: string;
            borderRightStyle: string;
            borderRightWidth: string;
            borderSpacing: string;
            borderStyle: string;
            borderTop: string;
            borderTopColor: string;
            borderTopLeftRadius: string;
            borderTopRightRadius: string;
            borderTopStyle: string;
            borderTopWidth: string;
            borderWidth: string;
            bottom: string;
            boxShadow: string;
            boxSizing: string;
            breakAfter: string;
            breakBefore: string;
            breakInside: string;
            captionSide: string;
            clear: string;
            clip: string;
            clipPath: string;
            clipRule: string;
            color: string;
            colorInterpolationFilters: string;
            columnCount: any;
            columnFill: string;
            columnGap: any;
            columnRule: string;
            columnRuleColor: any;
            columnRuleStyle: string;
            columnRuleWidth: any;
            columnSpan: string;
            columnWidth: any;
            columns: string;
            content: string;
            counterIncrement: string;
            counterReset: string;
            cssFloat: string;
            cssText: string;
            cursor: string;
            direction: string;
            display: string;
            dominantBaseline: string;
            emptyCells: string;
            enableBackground: string;
            fill: string;
            fillOpacity: string;
            fillRule: string;
            filter: string;
            flex: string;
            flexBasis: string;
            flexDirection: string;
            flexFlow: string;
            flexGrow: string;
            flexShrink: string;
            flexWrap: string;
            floodColor: string;
            floodOpacity: string;
            font: string;
            fontFamily: string;
            fontFeatureSettings: string;
            fontSize: string;
            fontSizeAdjust: string;
            fontStretch: string;
            fontStyle: string;
            fontVariant: string;
            fontWeight: string;
            glyphOrientationHorizontal: string;
            glyphOrientationVertical: string;
            height: string;
            imeMode: string;
            justifyContent: string;
            kerning: string;
            left: string;
            length: number;
            letterSpacing: string;
            lightingColor: string;
            lineHeight: string;
            listStyle: string;
            listStyleImage: string;
            listStylePosition: string;
            listStyleType: string;
            margin: string;
            marginBottom: string;
            marginLeft: string;
            marginRight: string;
            marginTop: string;
            marker: string;
            markerEnd: string;
            markerMid: string;
            markerStart: string;
            mask: string;
            maxHeight: string;
            maxWidth: string;
            minHeight: string;
            minWidth: string;
            msContentZoomChaining: string;
            msContentZoomLimit: string;
            msContentZoomLimitMax: any;
            msContentZoomLimitMin: any;
            msContentZoomSnap: string;
            msContentZoomSnapPoints: string;
            msContentZoomSnapType: string;
            msContentZooming: string;
            msFlowFrom: string;
            msFlowInto: string;
            msFontFeatureSettings: string;
            msGridColumn: any;
            msGridColumnAlign: string;
            msGridColumnSpan: any;
            msGridColumns: string;
            msGridRow: any;
            msGridRowAlign: string;
            msGridRowSpan: any;
            msGridRows: string;
            msHighContrastAdjust: string;
            msHyphenateLimitChars: string;
            msHyphenateLimitLines: any;
            msHyphenateLimitZone: any;
            msHyphens: string;
            msImeAlign: string;
            msOverflowStyle: string;
            msScrollChaining: string;
            msScrollLimit: string;
            msScrollLimitXMax: any;
            msScrollLimitXMin: any;
            msScrollLimitYMax: any;
            msScrollLimitYMin: any;
            msScrollRails: string;
            msScrollSnapPointsX: string;
            msScrollSnapPointsY: string;
            msScrollSnapType: string;
            msScrollSnapX: string;
            msScrollSnapY: string;
            msScrollTranslation: string;
            msTextCombineHorizontal: string;
            msTextSizeAdjust: any;
            msTouchAction: string;
            msTouchSelect: string;
            msUserSelect: string;
            msWrapFlow: string;
            msWrapMargin: any;
            msWrapThrough: string;
            opacity: string;
            order: string;
            orphans: string;
            outline: string;
            outlineColor: string;
            outlineStyle: string;
            outlineWidth: string;
            overflow: string;
            overflowX: string;
            overflowY: string;
            padding: string;
            paddingBottom: string;
            paddingLeft: string;
            paddingRight: string;
            paddingTop: string;
            pageBreakAfter: string;
            pageBreakBefore: string;
            pageBreakInside: string;
            parentRule: CSSRule;
            perspective: string;
            perspectiveOrigin: string;
            pointerEvents: string;
            position: string;
            quotes: string;
            right: string;
            rubyAlign: string;
            rubyOverhang: string;
            rubyPosition: string;
            stopColor: string;
            stopOpacity: string;
            stroke: string;
            strokeDasharray: string;
            strokeDashoffset: string;
            strokeLinecap: string;
            strokeLinejoin: string;
            strokeMiterlimit: string;
            strokeOpacity: string;
            strokeWidth: string;
            tableLayout: string;
            textAlign: string;
            textAlignLast: string;
            textAnchor: string;
            textDecoration: string;
            textFillColor: string;
            textIndent: string;
            textJustify: string;
            textKashida: string;
            textKashidaSpace: string;
            textOverflow: string;
            textShadow: string;
            textTransform: string;
            textUnderlinePosition: string;
            top: string;
            touchAction: string;
            transform: string;
            transformOrigin: string;
            transformStyle: string;
            transition: string;
            transitionDelay: string;
            transitionDuration: string;
            transitionProperty: string;
            transitionTimingFunction: string;
            unicodeBidi: string;
            verticalAlign: string;
            visibility: string;
            webkitAlignContent: string;
            webkitAlignItems: string;
            webkitAlignSelf: string;
            webkitAnimation: string;
            webkitAnimationDelay: string;
            webkitAnimationDirection: string;
            webkitAnimationDuration: string;
            webkitAnimationFillMode: string;
            webkitAnimationIterationCount: string;
            webkitAnimationName: string;
            webkitAnimationPlayState: string;
            webkitAnimationTimingFunction: string;
            webkitAppearance: string;
            webkitBackfaceVisibility: string;
            webkitBackground: string;
            webkitBackgroundAttachment: string;
            webkitBackgroundClip: string;
            webkitBackgroundColor: string;
            webkitBackgroundImage: string;
            webkitBackgroundOrigin: string;
            webkitBackgroundPosition: string;
            webkitBackgroundPositionX: string;
            webkitBackgroundPositionY: string;
            webkitBackgroundRepeat: string;
            webkitBackgroundSize: string;
            webkitBorderBottomLeftRadius: string;
            webkitBorderBottomRightRadius: string;
            webkitBorderImage: string;
            webkitBorderImageOutset: string;
            webkitBorderImageRepeat: string;
            webkitBorderImageSlice: string;
            webkitBorderImageSource: string;
            webkitBorderImageWidth: string;
            webkitBorderRadius: string;
            webkitBorderTopLeftRadius: string;
            webkitBorderTopRightRadius: string;
            webkitBoxAlign: string;
            webkitBoxDirection: string;
            webkitBoxFlex: string;
            webkitBoxOrdinalGroup: string;
            webkitBoxOrient: string;
            webkitBoxPack: string;
            webkitBoxSizing: string;
            webkitColumnBreakAfter: string;
            webkitColumnBreakBefore: string;
            webkitColumnBreakInside: string;
            webkitColumnCount: any;
            webkitColumnGap: any;
            webkitColumnRule: string;
            webkitColumnRuleColor: any;
            webkitColumnRuleStyle: string;
            webkitColumnRuleWidth: any;
            webkitColumnSpan: string;
            webkitColumnWidth: any;
            webkitColumns: string;
            webkitFilter: string;
            webkitFlex: string;
            webkitFlexBasis: string;
            webkitFlexDirection: string;
            webkitFlexFlow: string;
            webkitFlexGrow: string;
            webkitFlexShrink: string;
            webkitFlexWrap: string;
            webkitJustifyContent: string;
            webkitOrder: string;
            webkitPerspective: string;
            webkitPerspectiveOrigin: string;
            webkitTapHighlightColor: string;
            webkitTextFillColor: string;
            webkitTextSizeAdjust: any;
            webkitTransform: string;
            webkitTransformOrigin: string;
            webkitTransformStyle: string;
            webkitTransition: string;
            webkitTransitionDelay: string;
            webkitTransitionDuration: string;
            webkitTransitionProperty: string;
            webkitTransitionTimingFunction: string;
            webkitUserSelect: string;
            webkitWritingMode: string;
            whiteSpace: string;
            widows: string;
            width: string;
            wordBreak: string;
            wordSpacing: string;
            wordWrap: string;
            writingMode: string;
            zIndex: string;
            zoom: string;
            getPropertyPriority(propertyName: string): string;
            getPropertyValue(propertyName: string): string;
            item(index: number): string;
            removeProperty(propertyName: string): string;
            setProperty(propertyName: string, value: string, priority?: string): void;
            [index: number]: string;
        }
        
        declare var CSSStyleDeclaration: {
            prototype: CSSStyleDeclaration;
            new(): CSSStyleDeclaration;
        }
        
        interface CSSStyleRule extends CSSRule {
            readOnly: boolean;
            selectorText: string;
            style: CSSStyleDeclaration;
        }
        
        declare var CSSStyleRule: {
            prototype: CSSStyleRule;
            new(): CSSStyleRule;
        }
        
        interface CSSStyleSheet extends StyleSheet {
            cssRules: CSSRuleList;
            cssText: string;
            href: string;
            id: string;
            imports: StyleSheetList;
            isAlternate: boolean;
            isPrefAlternate: boolean;
            ownerRule: CSSRule;
            owningElement: Element;
            pages: StyleSheetPageList;
            readOnly: boolean;
            rules: CSSRuleList;
            addImport(bstrURL: string, lIndex?: number): number;
            addPageRule(bstrSelector: string, bstrStyle: string, lIndex?: number): number;
            addRule(bstrSelector: string, bstrStyle?: string, lIndex?: number): number;
            deleteRule(index?: number): void;
            insertRule(rule: string, index?: number): number;
            removeImport(lIndex: number): void;
            removeRule(lIndex: number): void;
        }
        
        declare var CSSStyleSheet: {
            prototype: CSSStyleSheet;
            new(): CSSStyleSheet;
        }
        
        interface CSSSupportsRule extends CSSConditionRule {
        }
        
        declare var CSSSupportsRule: {
            prototype: CSSSupportsRule;
            new(): CSSSupportsRule;
        }
        
        interface CanvasGradient {
            addColorStop(offset: number, color: string): void;
        }
        
        declare var CanvasGradient: {
            prototype: CanvasGradient;
            new(): CanvasGradient;
        }
        
        interface CanvasPattern {
        }
        
        declare var CanvasPattern: {
            prototype: CanvasPattern;
            new(): CanvasPattern;
        }
        
        interface CanvasRenderingContext2D {
            canvas: HTMLCanvasElement;
            fillStyle: any;
            font: string;
            globalAlpha: number;
            globalCompositeOperation: string;
            lineCap: string;
            lineDashOffset: number;
            lineJoin: string;
            lineWidth: number;
            miterLimit: number;
            msFillRule: string;
            msImageSmoothingEnabled: boolean;
            shadowBlur: number;
            shadowColor: string;
            shadowOffsetX: number;
            shadowOffsetY: number;
            strokeStyle: any;
            textAlign: string;
            textBaseline: string;
            arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void;
            arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void;
            beginPath(): void;
            bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
            clearRect(x: number, y: number, w: number, h: number): void;
            clip(fillRule?: string): void;
            closePath(): void;
            createImageData(imageDataOrSw: number, sh?: number): ImageData;
            createImageData(imageDataOrSw: ImageData, sh?: number): ImageData;
            createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient;
            createPattern(image: HTMLImageElement, repetition: string): CanvasPattern;
            createPattern(image: HTMLCanvasElement, repetition: string): CanvasPattern;
            createPattern(image: HTMLVideoElement, repetition: string): CanvasPattern;
            createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient;
            drawImage(image: HTMLImageElement, offsetX: number, offsetY: number, width?: number, height?: number, canvasOffsetX?: number, canvasOffsetY?: number, canvasImageWidth?: number, canvasImageHeight?: number): void;
            drawImage(image: HTMLCanvasElement, offsetX: number, offsetY: number, width?: number, height?: number, canvasOffsetX?: number, canvasOffsetY?: number, canvasImageWidth?: number, canvasImageHeight?: number): void;
            drawImage(image: HTMLVideoElement, offsetX: number, offsetY: number, width?: number, height?: number, canvasOffsetX?: number, canvasOffsetY?: number, canvasImageWidth?: number, canvasImageHeight?: number): void;
            fill(fillRule?: string): void;
            fillRect(x: number, y: number, w: number, h: number): void;
            fillText(text: string, x: number, y: number, maxWidth?: number): void;
            getImageData(sx: number, sy: number, sw: number, sh: number): ImageData;
            getLineDash(): number[];
            isPointInPath(x: number, y: number, fillRule?: string): boolean;
            lineTo(x: number, y: number): void;
            measureText(text: string): TextMetrics;
            moveTo(x: number, y: number): void;
            putImageData(imagedata: ImageData, dx: number, dy: number, dirtyX?: number, dirtyY?: number, dirtyWidth?: number, dirtyHeight?: number): void;
            quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;
            rect(x: number, y: number, w: number, h: number): void;
            restore(): void;
            rotate(angle: number): void;
            save(): void;
            scale(x: number, y: number): void;
            setLineDash(segments: number[]): void;
            setTransform(m11: number, m12: number, m21: number, m22: number, dx: number, dy: number): void;
            stroke(): void;
            strokeRect(x: number, y: number, w: number, h: number): void;
            strokeText(text: string, x: number, y: number, maxWidth?: number): void;
            transform(m11: number, m12: number, m21: number, m22: number, dx: number, dy: number): void;
            translate(x: number, y: number): void;
        }
        
        declare var CanvasRenderingContext2D: {
            prototype: CanvasRenderingContext2D;
            new(): CanvasRenderingContext2D;
        }
        
        interface ChannelMergerNode extends AudioNode {
        }
        
        declare var ChannelMergerNode: {
            prototype: ChannelMergerNode;
            new(): ChannelMergerNode;
        }
        
        interface ChannelSplitterNode extends AudioNode {
        }
        
        declare var ChannelSplitterNode: {
            prototype: ChannelSplitterNode;
            new(): ChannelSplitterNode;
        }
        
        interface CharacterData extends Node, ChildNode {
            data: string;
            length: number;
            appendData(arg: string): void;
            deleteData(offset: number, count: number): void;
            insertData(offset: number, arg: string): void;
            replaceData(offset: number, count: number, arg: string): void;
            substringData(offset: number, count: number): string;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var CharacterData: {
            prototype: CharacterData;
            new(): CharacterData;
        }
        
        interface ClientRect {
            bottom: number;
            height: number;
            left: number;
            right: number;
            top: number;
            width: number;
        }
        
        declare var ClientRect: {
            prototype: ClientRect;
            new(): ClientRect;
        }
        
        interface ClientRectList {
            length: number;
            item(index: number): ClientRect;
            [index: number]: ClientRect;
        }
        
        declare var ClientRectList: {
            prototype: ClientRectList;
            new(): ClientRectList;
        }
        
        interface ClipboardEvent extends Event {
            clipboardData: DataTransfer;
        }
        
        declare var ClipboardEvent: {
            prototype: ClipboardEvent;
            new(type: string, eventInitDict?: ClipboardEventInit): ClipboardEvent;
        }
        
        interface CloseEvent extends Event {
            code: number;
            reason: string;
            wasClean: boolean;
            initCloseEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, wasCleanArg: boolean, codeArg: number, reasonArg: string): void;
        }
        
        declare var CloseEvent: {
            prototype: CloseEvent;
            new(): CloseEvent;
        }
        
        interface CommandEvent extends Event {
            commandName: string;
            detail: string;
        }
        
        declare var CommandEvent: {
            prototype: CommandEvent;
            new(type: string, eventInitDict?: CommandEventInit): CommandEvent;
        }
        
        interface Comment extends CharacterData {
            text: string;
        }
        
        declare var Comment: {
            prototype: Comment;
            new(): Comment;
        }
        
        interface CompositionEvent extends UIEvent {
            data: string;
            locale: string;
            initCompositionEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, dataArg: string, locale: string): void;
        }
        
        declare var CompositionEvent: {
            prototype: CompositionEvent;
            new(typeArg: string, eventInitDict?: CompositionEventInit): CompositionEvent;
        }
        
        interface Console {
            assert(test?: boolean, message?: string, ...optionalParams: any[]): void;
            clear(): void;
            count(countTitle?: string): void;
            debug(message?: string, ...optionalParams: any[]): void;
            dir(value?: any, ...optionalParams: any[]): void;
            dirxml(value: any): void;
            error(message?: any, ...optionalParams: any[]): void;
            group(groupTitle?: string): void;
            groupCollapsed(groupTitle?: string): void;
            groupEnd(): void;
            info(message?: any, ...optionalParams: any[]): void;
            log(message?: any, ...optionalParams: any[]): void;
            msIsIndependentlyComposed(element: Element): boolean;
            profile(reportName?: string): void;
            profileEnd(): void;
            select(element: Element): void;
            time(timerName?: string): void;
            timeEnd(timerName?: string): void;
            trace(): void;
            warn(message?: any, ...optionalParams: any[]): void;
        }
        
        declare var Console: {
            prototype: Console;
            new(): Console;
        }
        
        interface ConvolverNode extends AudioNode {
            buffer: AudioBuffer;
            normalize: boolean;
        }
        
        declare var ConvolverNode: {
            prototype: ConvolverNode;
            new(): ConvolverNode;
        }
        
        interface Coordinates {
            accuracy: number;
            altitude: number;
            altitudeAccuracy: number;
            heading: number;
            latitude: number;
            longitude: number;
            speed: number;
        }
        
        declare var Coordinates: {
            prototype: Coordinates;
            new(): Coordinates;
        }
        
        interface Crypto extends Object, RandomSource {
            subtle: SubtleCrypto;
        }
        
        declare var Crypto: {
            prototype: Crypto;
            new(): Crypto;
        }
        
        interface CryptoKey {
            algorithm: KeyAlgorithm;
            extractable: boolean;
            type: string;
            usages: string[];
        }
        
        declare var CryptoKey: {
            prototype: CryptoKey;
            new(): CryptoKey;
        }
        
        interface CryptoKeyPair {
            privateKey: CryptoKey;
            publicKey: CryptoKey;
        }
        
        declare var CryptoKeyPair: {
            prototype: CryptoKeyPair;
            new(): CryptoKeyPair;
        }
        
        interface CustomEvent extends Event {
            detail: any;
            initCustomEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, detailArg: any): void;
        }
        
        declare var CustomEvent: {
            prototype: CustomEvent;
            new(typeArg: string, eventInitDict?: CustomEventInit): CustomEvent;
        }
        
        interface DOMError {
            name: string;
            toString(): string;
        }
        
        declare var DOMError: {
            prototype: DOMError;
            new(): DOMError;
        }
        
        interface DOMException {
            code: number;
            message: string;
            name: string;
            toString(): string;
            ABORT_ERR: number;
            DATA_CLONE_ERR: number;
            DOMSTRING_SIZE_ERR: number;
            HIERARCHY_REQUEST_ERR: number;
            INDEX_SIZE_ERR: number;
            INUSE_ATTRIBUTE_ERR: number;
            INVALID_ACCESS_ERR: number;
            INVALID_CHARACTER_ERR: number;
            INVALID_MODIFICATION_ERR: number;
            INVALID_NODE_TYPE_ERR: number;
            INVALID_STATE_ERR: number;
            NAMESPACE_ERR: number;
            NETWORK_ERR: number;
            NOT_FOUND_ERR: number;
            NOT_SUPPORTED_ERR: number;
            NO_DATA_ALLOWED_ERR: number;
            NO_MODIFICATION_ALLOWED_ERR: number;
            PARSE_ERR: number;
            QUOTA_EXCEEDED_ERR: number;
            SECURITY_ERR: number;
            SERIALIZE_ERR: number;
            SYNTAX_ERR: number;
            TIMEOUT_ERR: number;
            TYPE_MISMATCH_ERR: number;
            URL_MISMATCH_ERR: number;
            VALIDATION_ERR: number;
            WRONG_DOCUMENT_ERR: number;
        }
        
        declare var DOMException: {
            prototype: DOMException;
            new(): DOMException;
            ABORT_ERR: number;
            DATA_CLONE_ERR: number;
            DOMSTRING_SIZE_ERR: number;
            HIERARCHY_REQUEST_ERR: number;
            INDEX_SIZE_ERR: number;
            INUSE_ATTRIBUTE_ERR: number;
            INVALID_ACCESS_ERR: number;
            INVALID_CHARACTER_ERR: number;
            INVALID_MODIFICATION_ERR: number;
            INVALID_NODE_TYPE_ERR: number;
            INVALID_STATE_ERR: number;
            NAMESPACE_ERR: number;
            NETWORK_ERR: number;
            NOT_FOUND_ERR: number;
            NOT_SUPPORTED_ERR: number;
            NO_DATA_ALLOWED_ERR: number;
            NO_MODIFICATION_ALLOWED_ERR: number;
            PARSE_ERR: number;
            QUOTA_EXCEEDED_ERR: number;
            SECURITY_ERR: number;
            SERIALIZE_ERR: number;
            SYNTAX_ERR: number;
            TIMEOUT_ERR: number;
            TYPE_MISMATCH_ERR: number;
            URL_MISMATCH_ERR: number;
            VALIDATION_ERR: number;
            WRONG_DOCUMENT_ERR: number;
        }
        
        interface DOMImplementation {
            createDocument(namespaceURI: string, qualifiedName: string, doctype: DocumentType): Document;
            createDocumentType(qualifiedName: string, publicId: string, systemId: string): DocumentType;
            createHTMLDocument(title: string): Document;
            hasFeature(feature: string, version: string): boolean;
        }
        
        declare var DOMImplementation: {
            prototype: DOMImplementation;
            new(): DOMImplementation;
        }
        
        interface DOMParser {
            parseFromString(source: string, mimeType: string): Document;
        }
        
        declare var DOMParser: {
            prototype: DOMParser;
            new(): DOMParser;
        }
        
        interface DOMSettableTokenList extends DOMTokenList {
            value: string;
        }
        
        declare var DOMSettableTokenList: {
            prototype: DOMSettableTokenList;
            new(): DOMSettableTokenList;
        }
        
        interface DOMStringList {
            length: number;
            contains(str: string): boolean;
            item(index: number): string;
            [index: number]: string;
        }
        
        declare var DOMStringList: {
            prototype: DOMStringList;
            new(): DOMStringList;
        }
        
        interface DOMStringMap {
            [name: string]: string;
        }
        
        declare var DOMStringMap: {
            prototype: DOMStringMap;
            new(): DOMStringMap;
        }
        
        interface DOMTokenList {
            length: number;
            add(...token: string[]): void;
            contains(token: string): boolean;
            item(index: number): string;
            remove(...token: string[]): void;
            toString(): string;
            toggle(token: string, force?: boolean): boolean;
            [index: number]: string;
        }
        
        declare var DOMTokenList: {
            prototype: DOMTokenList;
            new(): DOMTokenList;
        }
        
        interface DataCue extends TextTrackCue {
            data: ArrayBuffer;
        }
        
        declare var DataCue: {
            prototype: DataCue;
            new(): DataCue;
        }
        
        interface DataTransfer {
            dropEffect: string;
            effectAllowed: string;
            files: FileList;
            items: DataTransferItemList;
            types: DOMStringList;
            clearData(format?: string): boolean;
            getData(format: string): string;
            setData(format: string, data: string): boolean;
        }
        
        declare var DataTransfer: {
            prototype: DataTransfer;
            new(): DataTransfer;
        }
        
        interface DataTransferItem {
            kind: string;
            type: string;
            getAsFile(): File;
            getAsString(_callback: FunctionStringCallback): void;
        }
        
        declare var DataTransferItem: {
            prototype: DataTransferItem;
            new(): DataTransferItem;
        }
        
        interface DataTransferItemList {
            length: number;
            add(data: File): DataTransferItem;
            clear(): void;
            item(index: number): File;
            remove(index: number): void;
            [index: number]: File;
        }
        
        declare var DataTransferItemList: {
            prototype: DataTransferItemList;
            new(): DataTransferItemList;
        }
        
        interface DeferredPermissionRequest {
            id: number;
            type: string;
            uri: string;
            allow(): void;
            deny(): void;
        }
        
        declare var DeferredPermissionRequest: {
            prototype: DeferredPermissionRequest;
            new(): DeferredPermissionRequest;
        }
        
        interface DelayNode extends AudioNode {
            delayTime: AudioParam;
        }
        
        declare var DelayNode: {
            prototype: DelayNode;
            new(): DelayNode;
        }
        
        interface DeviceAcceleration {
            x: number;
            y: number;
            z: number;
        }
        
        declare var DeviceAcceleration: {
            prototype: DeviceAcceleration;
            new(): DeviceAcceleration;
        }
        
        interface DeviceMotionEvent extends Event {
            acceleration: DeviceAcceleration;
            accelerationIncludingGravity: DeviceAcceleration;
            interval: number;
            rotationRate: DeviceRotationRate;
            initDeviceMotionEvent(type: string, bubbles: boolean, cancelable: boolean, acceleration: DeviceAccelerationDict, accelerationIncludingGravity: DeviceAccelerationDict, rotationRate: DeviceRotationRateDict, interval: number): void;
        }
        
        declare var DeviceMotionEvent: {
            prototype: DeviceMotionEvent;
            new(): DeviceMotionEvent;
        }
        
        interface DeviceOrientationEvent extends Event {
            absolute: boolean;
            alpha: number;
            beta: number;
            gamma: number;
            initDeviceOrientationEvent(type: string, bubbles: boolean, cancelable: boolean, alpha: number, beta: number, gamma: number, absolute: boolean): void;
        }
        
        declare var DeviceOrientationEvent: {
            prototype: DeviceOrientationEvent;
            new(): DeviceOrientationEvent;
        }
        
        interface DeviceRotationRate {
            alpha: number;
            beta: number;
            gamma: number;
        }
        
        declare var DeviceRotationRate: {
            prototype: DeviceRotationRate;
            new(): DeviceRotationRate;
        }
        
        interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEvent {
            /**
              * Sets or gets the URL for the current document. 
              */
            URL: string;
            /**
              * Gets the URL for the document, stripped of any character encoding.
              */
            URLUnencoded: string;
            /**
              * Gets the object that has the focus when the parent document has focus.
              */
            activeElement: Element;
            /**
              * Sets or gets the color of all active links in the document.
              */
            alinkColor: string;
            /**
              * Returns a reference to the collection of elements contained by the object.
              */
            all: HTMLCollection;
            /**
              * Retrieves a collection of all a objects that have a name and/or id property. Objects in this collection are in HTML source order.
              */
            anchors: HTMLCollection;
            /**
              * Retrieves a collection of all applet objects in the document.
              */
            applets: HTMLCollection;
            /**
              * Deprecated. Sets or retrieves a value that indicates the background color behind the object. 
              */
            bgColor: string;
            /**
              * Specifies the beginning and end of the document body.
              */
            body: HTMLElement;
            characterSet: string;
            /**
              * Gets or sets the character set used to encode the object.
              */
            charset: string;
            /**
              * Gets a value that indicates whether standards-compliant mode is switched on for the object.
              */
            compatMode: string;
            cookie: string;
            /**
              * Gets the default character set from the current regional language settings.
              */
            defaultCharset: string;
            defaultView: Window;
            /**
              * Sets or gets a value that indicates whether the document can be edited.
              */
            designMode: string;
            /**
              * Sets or retrieves a value that indicates the reading order of the object. 
              */
            dir: string;
            /**
              * Gets an object representing the document type declaration associated with the current document. 
              */
            doctype: DocumentType;
            /**
              * Gets a reference to the root node of the document. 
              */
            documentElement: HTMLElement;
            /**
              * Sets or gets the security domain of the document. 
              */
            domain: string;
            /**
              * Retrieves a collection of all embed objects in the document.
              */
            embeds: HTMLCollection;
            /**
              * Sets or gets the foreground (text) color of the document.
              */
            fgColor: string;
            /**
              * Retrieves a collection, in source order, of all form objects in the document.
              */
            forms: HTMLCollection;
            fullscreenElement: Element;
            fullscreenEnabled: boolean;
            head: HTMLHeadElement;
            hidden: boolean;
            /**
              * Retrieves a collection, in source order, of img objects in the document.
              */
            images: HTMLCollection;
            /**
              * Gets the implementation object of the current document. 
              */
            implementation: DOMImplementation;
            /**
              * Returns the character encoding used to create the webpage that is loaded into the document object.
              */
            inputEncoding: string;
            /**
              * Gets the date that the page was last modified, if the page supplies one. 
              */
            lastModified: string;
            /**
              * Sets or gets the color of the document links. 
              */
            linkColor: string;
            /**
              * Retrieves a collection of all a objects that specify the href property and all area objects in the document.
              */
            links: HTMLCollection;
            /**
              * Contains information about the current URL. 
              */
            location: Location;
            media: string;
            msCSSOMElementFloatMetrics: boolean;
            msCapsLockWarningOff: boolean;
            msHidden: boolean;
            msVisibilityState: string;
            /**
              * Fires when the user aborts the download.
              * @param ev The event.
              */
            onabort: (ev: Event) => any;
            /**
              * Fires when the object is set as the active element.
              * @param ev The event.
              */
            onactivate: (ev: UIEvent) => any;
            /**
              * Fires immediately before the object is set as the active element.
              * @param ev The event.
              */
            onbeforeactivate: (ev: UIEvent) => any;
            /**
              * Fires immediately before the activeElement is changed from the current object to another object in the parent document.
              * @param ev The event.
              */
            onbeforedeactivate: (ev: UIEvent) => any;
            /** 
              * Fires when the object loses the input focus. 
              * @param ev The focus event.
              */
            onblur: (ev: FocusEvent) => any;
            /**
              * Occurs when playback is possible, but would require further buffering. 
              * @param ev The event.
              */
            oncanplay: (ev: Event) => any;
            oncanplaythrough: (ev: Event) => any;
            /**
              * Fires when the contents of the object or selection have changed. 
              * @param ev The event.
              */
            onchange: (ev: Event) => any;
            /**
              * Fires when the user clicks the left mouse button on the object
              * @param ev The mouse event.
              */
            onclick: (ev: MouseEvent) => any;
            /**
              * Fires when the user clicks the right mouse button in the client area, opening the context menu. 
              * @param ev The mouse event.
              */
            oncontextmenu: (ev: PointerEvent) => any;
            /**
              * Fires when the user double-clicks the object.
              * @param ev The mouse event.
              */
            ondblclick: (ev: MouseEvent) => any;
            /**
              * Fires when the activeElement is changed from the current object to another object in the parent document.
              * @param ev The UI Event
              */
            ondeactivate: (ev: UIEvent) => any;
            /**
              * Fires on the source object continuously during a drag operation.
              * @param ev The event.
              */
            ondrag: (ev: DragEvent) => any;
            /**
              * Fires on the source object when the user releases the mouse at the close of a drag operation.
              * @param ev The event.
              */
            ondragend: (ev: DragEvent) => any;
            /** 
              * Fires on the target element when the user drags the object to a valid drop target.
              * @param ev The drag event.
              */
            ondragenter: (ev: DragEvent) => any;
            /** 
              * Fires on the target object when the user moves the mouse out of a valid drop target during a drag operation.
              * @param ev The drag event.
              */
            ondragleave: (ev: DragEvent) => any;
            /**
              * Fires on the target element continuously while the user drags the object over a valid drop target.
              * @param ev The event.
              */
            ondragover: (ev: DragEvent) => any;
            /**
              * Fires on the source object when the user starts to drag a text selection or selected object. 
              * @param ev The event.
              */
            ondragstart: (ev: DragEvent) => any;
            ondrop: (ev: DragEvent) => any;
            /**
              * Occurs when the duration attribute is updated. 
              * @param ev The event.
              */
            ondurationchange: (ev: Event) => any;
            /**
              * Occurs when the media element is reset to its initial state. 
              * @param ev The event.
              */
            onemptied: (ev: Event) => any;
            /**
              * Occurs when the end of playback is reached. 
              * @param ev The event
              */
            onended: (ev: Event) => any;
            /**
              * Fires when an error occurs during object loading.
              * @param ev The event.
              */
            onerror: (ev: Event) => any;
            /**
              * Fires when the object receives focus. 
              * @param ev The event.
              */
            onfocus: (ev: FocusEvent) => any;
            onfullscreenchange: (ev: Event) => any;
            onfullscreenerror: (ev: Event) => any;
            oninput: (ev: Event) => any;
            /**
              * Fires when the user presses a key.
              * @param ev The keyboard event
              */
            onkeydown: (ev: KeyboardEvent) => any;
            /**
              * Fires when the user presses an alphanumeric key.
              * @param ev The event.
              */
            onkeypress: (ev: KeyboardEvent) => any;
            /**
              * Fires when the user releases a key.
              * @param ev The keyboard event
              */
            onkeyup: (ev: KeyboardEvent) => any;
            /**
              * Fires immediately after the browser loads the object. 
              * @param ev The event.
              */
            onload: (ev: Event) => any;
            /**
              * Occurs when media data is loaded at the current playback position. 
              * @param ev The event.
              */
            onloadeddata: (ev: Event) => any;
            /**
              * Occurs when the duration and dimensions of the media have been determined.
              * @param ev The event.
              */
            onloadedmetadata: (ev: Event) => any;
            /**
              * Occurs when Internet Explorer begins looking for media data. 
              * @param ev The event.
              */
            onloadstart: (ev: Event) => any;
            /**
              * Fires when the user clicks the object with either mouse button. 
              * @param ev The mouse event.
              */
            onmousedown: (ev: MouseEvent) => any;
            /**
              * Fires when the user moves the mouse over the object. 
              * @param ev The mouse event.
              */
            onmousemove: (ev: MouseEvent) => any;
            /**
              * Fires when the user moves the mouse pointer outside the boundaries of the object. 
              * @param ev The mouse event.
              */
            onmouseout: (ev: MouseEvent) => any;
            /**
              * Fires when the user moves the mouse pointer into the object.
              * @param ev The mouse event.
              */
            onmouseover: (ev: MouseEvent) => any;
            /**
              * Fires when the user releases a mouse button while the mouse is over the object. 
              * @param ev The mouse event.
              */
            onmouseup: (ev: MouseEvent) => any;
            /**
              * Fires when the wheel button is rotated. 
              * @param ev The mouse event
              */
            onmousewheel: (ev: MouseWheelEvent) => any;
            onmscontentzoom: (ev: UIEvent) => any;
            onmsgesturechange: (ev: MSGestureEvent) => any;
            onmsgesturedoubletap: (ev: MSGestureEvent) => any;
            onmsgestureend: (ev: MSGestureEvent) => any;
            onmsgesturehold: (ev: MSGestureEvent) => any;
            onmsgesturestart: (ev: MSGestureEvent) => any;
            onmsgesturetap: (ev: MSGestureEvent) => any;
            onmsinertiastart: (ev: MSGestureEvent) => any;
            onmsmanipulationstatechanged: (ev: MSManipulationEvent) => any;
            onmspointercancel: (ev: MSPointerEvent) => any;
            onmspointerdown: (ev: MSPointerEvent) => any;
            onmspointerenter: (ev: MSPointerEvent) => any;
            onmspointerleave: (ev: MSPointerEvent) => any;
            onmspointermove: (ev: MSPointerEvent) => any;
            onmspointerout: (ev: MSPointerEvent) => any;
            onmspointerover: (ev: MSPointerEvent) => any;
            onmspointerup: (ev: MSPointerEvent) => any;
            /**
              * Occurs when an item is removed from a Jump List of a webpage running in Site Mode. 
              * @param ev The event.
              */
            onmssitemodejumplistitemremoved: (ev: MSSiteModeEvent) => any;
            /**
              * Occurs when a user clicks a button in a Thumbnail Toolbar of a webpage running in Site Mode.
              * @param ev The event.
              */
            onmsthumbnailclick: (ev: MSSiteModeEvent) => any;
            /**
              * Occurs when playback is paused.
              * @param ev The event.
              */
            onpause: (ev: Event) => any;
            /**
              * Occurs when the play method is requested. 
              * @param ev The event.
              */
            onplay: (ev: Event) => any;
            /**
              * Occurs when the audio or video has started playing. 
              * @param ev The event.
              */
            onplaying: (ev: Event) => any;
            onpointerlockchange: (ev: Event) => any;
            onpointerlockerror: (ev: Event) => any;
            /**
              * Occurs to indicate progress while downloading media data. 
              * @param ev The event.
              */
            onprogress: (ev: ProgressEvent) => any;
            /**
              * Occurs when the playback rate is increased or decreased. 
              * @param ev The event.
              */
            onratechange: (ev: Event) => any;
            /**
              * Fires when the state of the object has changed.
              * @param ev The event
              */
            onreadystatechange: (ev: ProgressEvent) => any;
            /**
              * Fires when the user resets a form. 
              * @param ev The event.
              */
            onreset: (ev: Event) => any;
            /**
              * Fires when the user repositions the scroll box in the scroll bar on the object. 
              * @param ev The event.
              */
            onscroll: (ev: UIEvent) => any;
            /**
              * Occurs when the seek operation ends. 
              * @param ev The event.
              */
            onseeked: (ev: Event) => any;
            /**
              * Occurs when the current playback position is moved. 
              * @param ev The event.
              */
            onseeking: (ev: Event) => any;
            /**
              * Fires when the current selection changes.
              * @param ev The event.
              */
            onselect: (ev: UIEvent) => any;
            onselectstart: (ev: Event) => any;
            /**
              * Occurs when the download has stopped. 
              * @param ev The event.
              */
            onstalled: (ev: Event) => any;
            /**
              * Fires when the user clicks the Stop button or leaves the Web page.
              * @param ev The event.
              */
            onstop: (ev: Event) => any;
            onsubmit: (ev: Event) => any;
            /**
              * Occurs if the load operation has been intentionally halted. 
              * @param ev The event.
              */
            onsuspend: (ev: Event) => any;
            /**
              * Occurs to indicate the current playback position.
              * @param ev The event.
              */
            ontimeupdate: (ev: Event) => any;
            ontouchcancel: (ev: TouchEvent) => any;
            ontouchend: (ev: TouchEvent) => any;
            ontouchmove: (ev: TouchEvent) => any;
            ontouchstart: (ev: TouchEvent) => any;
            /**
              * Occurs when the volume is changed, or playback is muted or unmuted.
              * @param ev The event.
              */
            onvolumechange: (ev: Event) => any;
            /**
              * Occurs when playback stops because the next frame of a video resource is not available. 
              * @param ev The event.
              */
            onwaiting: (ev: Event) => any;
            onwebkitfullscreenchange: (ev: Event) => any;
            onwebkitfullscreenerror: (ev: Event) => any;
            plugins: HTMLCollection;
            pointerLockElement: Element;
            /**
              * Retrieves a value that indicates the current state of the object.
              */
            readyState: string;
            /**
              * Gets the URL of the location that referred the user to the current page.
              */
            referrer: string;
            /**
              * Gets the root svg element in the document hierarchy.
              */
            rootElement: SVGSVGElement;
            /**
              * Retrieves a collection of all script objects in the document.
              */
            scripts: HTMLCollection;
            security: string;
            /**
              * Retrieves a collection of styleSheet objects representing the style sheets that correspond to each instance of a link or style object in the document.
              */
            styleSheets: StyleSheetList;
            /**
              * Contains the title of the document.
              */
            title: string;
            visibilityState: string;
            /** 
              * Sets or gets the color of the links that the user has visited.
              */
            vlinkColor: string;
            webkitCurrentFullScreenElement: Element;
            webkitFullscreenElement: Element;
            webkitFullscreenEnabled: boolean;
            webkitIsFullScreen: boolean;
            xmlEncoding: string;
            xmlStandalone: boolean;
            /**
              * Gets or sets the version attribute specified in the declaration of an XML document.
              */
            xmlVersion: string;
            adoptNode(source: Node): Node;
            captureEvents(): void;
            clear(): void;
            /**
              * Closes an output stream and forces the sent data to display.
              */
            close(): void;
            /**
              * Creates an attribute object with a specified name.
              * @param name String that sets the attribute object's name.
              */
            createAttribute(name: string): Attr;
            createAttributeNS(namespaceURI: string, qualifiedName: string): Attr;
            createCDATASection(data: string): CDATASection;
            /**
              * Creates a comment object with the specified data.
              * @param data Sets the comment object's data.
              */
            createComment(data: string): Comment;
            /**
              * Creates a new document.
              */
            createDocumentFragment(): DocumentFragment;
            /**
              * Creates an instance of the element for the specified tag.
              * @param tagName The name of an element.
              */
            createElement(tagName: "a"): HTMLAnchorElement;
            createElement(tagName: "abbr"): HTMLPhraseElement;
            createElement(tagName: "acronym"): HTMLPhraseElement;
            createElement(tagName: "address"): HTMLBlockElement;
            createElement(tagName: "applet"): HTMLAppletElement;
            createElement(tagName: "area"): HTMLAreaElement;
            createElement(tagName: "audio"): HTMLAudioElement;
            createElement(tagName: "b"): HTMLPhraseElement;
            createElement(tagName: "base"): HTMLBaseElement;
            createElement(tagName: "basefont"): HTMLBaseFontElement;
            createElement(tagName: "bdo"): HTMLPhraseElement;
            createElement(tagName: "big"): HTMLPhraseElement;
            createElement(tagName: "blockquote"): HTMLBlockElement;
            createElement(tagName: "body"): HTMLBodyElement;
            createElement(tagName: "br"): HTMLBRElement;
            createElement(tagName: "button"): HTMLButtonElement;
            createElement(tagName: "canvas"): HTMLCanvasElement;
            createElement(tagName: "caption"): HTMLTableCaptionElement;
            createElement(tagName: "center"): HTMLBlockElement;
            createElement(tagName: "cite"): HTMLPhraseElement;
            createElement(tagName: "code"): HTMLPhraseElement;
            createElement(tagName: "col"): HTMLTableColElement;
            createElement(tagName: "colgroup"): HTMLTableColElement;
            createElement(tagName: "datalist"): HTMLDataListElement;
            createElement(tagName: "dd"): HTMLDDElement;
            createElement(tagName: "del"): HTMLModElement;
            createElement(tagName: "dfn"): HTMLPhraseElement;
            createElement(tagName: "dir"): HTMLDirectoryElement;
            createElement(tagName: "div"): HTMLDivElement;
            createElement(tagName: "dl"): HTMLDListElement;
            createElement(tagName: "dt"): HTMLDTElement;
            createElement(tagName: "em"): HTMLPhraseElement;
            createElement(tagName: "embed"): HTMLEmbedElement;
            createElement(tagName: "fieldset"): HTMLFieldSetElement;
            createElement(tagName: "font"): HTMLFontElement;
            createElement(tagName: "form"): HTMLFormElement;
            createElement(tagName: "frame"): HTMLFrameElement;
            createElement(tagName: "frameset"): HTMLFrameSetElement;
            createElement(tagName: "h1"): HTMLHeadingElement;
            createElement(tagName: "h2"): HTMLHeadingElement;
            createElement(tagName: "h3"): HTMLHeadingElement;
            createElement(tagName: "h4"): HTMLHeadingElement;
            createElement(tagName: "h5"): HTMLHeadingElement;
            createElement(tagName: "h6"): HTMLHeadingElement;
            createElement(tagName: "head"): HTMLHeadElement;
            createElement(tagName: "hr"): HTMLHRElement;
            createElement(tagName: "html"): HTMLHtmlElement;
            createElement(tagName: "i"): HTMLPhraseElement;
            createElement(tagName: "iframe"): HTMLIFrameElement;
            createElement(tagName: "img"): HTMLImageElement;
            createElement(tagName: "input"): HTMLInputElement;
            createElement(tagName: "ins"): HTMLModElement;
            createElement(tagName: "isindex"): HTMLIsIndexElement;
            createElement(tagName: "kbd"): HTMLPhraseElement;
            createElement(tagName: "keygen"): HTMLBlockElement;
            createElement(tagName: "label"): HTMLLabelElement;
            createElement(tagName: "legend"): HTMLLegendElement;
            createElement(tagName: "li"): HTMLLIElement;
            createElement(tagName: "link"): HTMLLinkElement;
            createElement(tagName: "listing"): HTMLBlockElement;
            createElement(tagName: "map"): HTMLMapElement;
            createElement(tagName: "marquee"): HTMLMarqueeElement;
            createElement(tagName: "menu"): HTMLMenuElement;
            createElement(tagName: "meta"): HTMLMetaElement;
            createElement(tagName: "nextid"): HTMLNextIdElement;
            createElement(tagName: "nobr"): HTMLPhraseElement;
            createElement(tagName: "object"): HTMLObjectElement;
            createElement(tagName: "ol"): HTMLOListElement;
            createElement(tagName: "optgroup"): HTMLOptGroupElement;
            createElement(tagName: "option"): HTMLOptionElement;
            createElement(tagName: "p"): HTMLParagraphElement;
            createElement(tagName: "param"): HTMLParamElement;
            createElement(tagName: "plaintext"): HTMLBlockElement;
            createElement(tagName: "pre"): HTMLPreElement;
            createElement(tagName: "progress"): HTMLProgressElement;
            createElement(tagName: "q"): HTMLQuoteElement;
            createElement(tagName: "rt"): HTMLPhraseElement;
            createElement(tagName: "ruby"): HTMLPhraseElement;
            createElement(tagName: "s"): HTMLPhraseElement;
            createElement(tagName: "samp"): HTMLPhraseElement;
            createElement(tagName: "script"): HTMLScriptElement;
            createElement(tagName: "select"): HTMLSelectElement;
            createElement(tagName: "small"): HTMLPhraseElement;
            createElement(tagName: "source"): HTMLSourceElement;
            createElement(tagName: "span"): HTMLSpanElement;
            createElement(tagName: "strike"): HTMLPhraseElement;
            createElement(tagName: "strong"): HTMLPhraseElement;
            createElement(tagName: "style"): HTMLStyleElement;
            createElement(tagName: "sub"): HTMLPhraseElement;
            createElement(tagName: "sup"): HTMLPhraseElement;
            createElement(tagName: "table"): HTMLTableElement;
            createElement(tagName: "tbody"): HTMLTableSectionElement;
            createElement(tagName: "td"): HTMLTableDataCellElement;
            createElement(tagName: "textarea"): HTMLTextAreaElement;
            createElement(tagName: "tfoot"): HTMLTableSectionElement;
            createElement(tagName: "th"): HTMLTableHeaderCellElement;
            createElement(tagName: "thead"): HTMLTableSectionElement;
            createElement(tagName: "title"): HTMLTitleElement;
            createElement(tagName: "tr"): HTMLTableRowElement;
            createElement(tagName: "track"): HTMLTrackElement;
            createElement(tagName: "tt"): HTMLPhraseElement;
            createElement(tagName: "u"): HTMLPhraseElement;
            createElement(tagName: "ul"): HTMLUListElement;
            createElement(tagName: "var"): HTMLPhraseElement;
            createElement(tagName: "video"): HTMLVideoElement;
            createElement(tagName: "x-ms-webview"): MSHTMLWebViewElement;
            createElement(tagName: "xmp"): HTMLBlockElement;
            createElement(tagName: string): HTMLElement;
            createElementNS(namespaceURI: string, qualifiedName: string): Element;
            createExpression(expression: string, resolver: XPathNSResolver): XPathExpression;
            createNSResolver(nodeResolver: Node): XPathNSResolver;
            /**
              * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document. 
              * @param root The root element or node to start traversing on.
              * @param whatToShow The type of nodes or elements to appear in the node list
              * @param filter A custom NodeFilter function to use. For more information, see filter. Use null for no filter.
              * @param entityReferenceExpansion A flag that specifies whether entity reference nodes are expanded.
              */
            createNodeIterator(root: Node, whatToShow?: number, filter?: NodeFilter, entityReferenceExpansion?: boolean): NodeIterator;
            createProcessingInstruction(target: string, data: string): ProcessingInstruction;
            /**
              *  Returns an empty range object that has both of its boundary points positioned at the beginning of the document. 
              */
            createRange(): Range;
            /**
              * Creates a text string from the specified value. 
              * @param data String that specifies the nodeValue property of the text node.
              */
            createTextNode(data: string): Text;
            createTouch(view: any, target: EventTarget, identifier: number, pageX: number, pageY: number, screenX: number, screenY: number): Touch;
            createTouchList(...touches: Touch[]): TouchList;
            /**
              * Creates a TreeWalker object that you can use to traverse filtered lists of nodes or elements in a document.
              * @param root The root element or node to start traversing on.
              * @param whatToShow The type of nodes or elements to appear in the node list. For more information, see whatToShow.
              * @param filter A custom NodeFilter function to use.
              * @param entityReferenceExpansion A flag that specifies whether entity reference nodes are expanded.
              */
            createTreeWalker(root: Node, whatToShow?: number, filter?: NodeFilter, entityReferenceExpansion?: boolean): TreeWalker;
            /**
              * Returns the element for the specified x coordinate and the specified y coordinate. 
              * @param x The x-offset
              * @param y The y-offset
              */
            elementFromPoint(x: number, y: number): Element;
            evaluate(expression: string, contextNode: Node, resolver: XPathNSResolver, type: number, result: XPathResult): XPathResult;
            /**
              * Executes a command on the current document, current selection, or the given range.
              * @param commandId String that specifies the command to execute. This command can be any of the command identifiers that can be executed in script.
              * @param showUI Display the user interface, defaults to false.
              * @param value Value to assign.
              */
            execCommand(commandId: string, showUI?: boolean, value?: any): boolean;
            /**
              * Displays help information for the given command identifier.
              * @param commandId Displays help information for the given command identifier.
              */
            execCommandShowHelp(commandId: string): boolean;
            exitFullscreen(): void;
            exitPointerLock(): void;
            /**
              * Causes the element to receive the focus and executes the code specified by the onfocus event.
              */
            focus(): void;
            /**
              * Returns a reference to the first object with the specified value of the ID or NAME attribute.
              * @param elementId String that specifies the ID value. Case-insensitive.
              */
            getElementById(elementId: string): HTMLElement;
            getElementsByClassName(classNames: string): NodeList;
            /**
              * Gets a collection of objects based on the value of the NAME or ID attribute.
              * @param elementName Gets a collection of objects based on the value of the NAME or ID attribute.
              */
            getElementsByName(elementName: string): NodeList;
            /**
              * Retrieves a collection of objects based on the specified element name.
              * @param name Specifies the name of an element.
              */
            getElementsByTagName(tagname: "a"): NodeListOf<HTMLAnchorElement>;
            getElementsByTagName(tagname: "abbr"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "acronym"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "address"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(tagname: "applet"): NodeListOf<HTMLAppletElement>;
            getElementsByTagName(tagname: "area"): NodeListOf<HTMLAreaElement>;
            getElementsByTagName(tagname: "article"): NodeListOf<HTMLElement>;
            getElementsByTagName(tagname: "aside"): NodeListOf<HTMLElement>;
            getElementsByTagName(tagname: "audio"): NodeListOf<HTMLAudioElement>;
            getElementsByTagName(tagname: "b"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "base"): NodeListOf<HTMLBaseElement>;
            getElementsByTagName(tagname: "basefont"): NodeListOf<HTMLBaseFontElement>;
            getElementsByTagName(tagname: "bdo"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "big"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "blockquote"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(tagname: "body"): NodeListOf<HTMLBodyElement>;
            getElementsByTagName(tagname: "br"): NodeListOf<HTMLBRElement>;
            getElementsByTagName(tagname: "button"): NodeListOf<HTMLButtonElement>;
            getElementsByTagName(tagname: "canvas"): NodeListOf<HTMLCanvasElement>;
            getElementsByTagName(tagname: "caption"): NodeListOf<HTMLTableCaptionElement>;
            getElementsByTagName(tagname: "center"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(tagname: "circle"): NodeListOf<SVGCircleElement>;
            getElementsByTagName(tagname: "cite"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "clippath"): NodeListOf<SVGClipPathElement>;
            getElementsByTagName(tagname: "code"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "col"): NodeListOf<HTMLTableColElement>;
            getElementsByTagName(tagname: "colgroup"): NodeListOf<HTMLTableColElement>;
            getElementsByTagName(tagname: "datalist"): NodeListOf<HTMLDataListElement>;
            getElementsByTagName(tagname: "dd"): NodeListOf<HTMLDDElement>;
            getElementsByTagName(tagname: "defs"): NodeListOf<SVGDefsElement>;
            getElementsByTagName(tagname: "del"): NodeListOf<HTMLModElement>;
            getElementsByTagName(tagname: "desc"): NodeListOf<SVGDescElement>;
            getElementsByTagName(tagname: "dfn"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "dir"): NodeListOf<HTMLDirectoryElement>;
            getElementsByTagName(tagname: "div"): NodeListOf<HTMLDivElement>;
            getElementsByTagName(tagname: "dl"): NodeListOf<HTMLDListElement>;
            getElementsByTagName(tagname: "dt"): NodeListOf<HTMLDTElement>;
            getElementsByTagName(tagname: "ellipse"): NodeListOf<SVGEllipseElement>;
            getElementsByTagName(tagname: "em"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "embed"): NodeListOf<HTMLEmbedElement>;
            getElementsByTagName(tagname: "feblend"): NodeListOf<SVGFEBlendElement>;
            getElementsByTagName(tagname: "fecolormatrix"): NodeListOf<SVGFEColorMatrixElement>;
            getElementsByTagName(tagname: "fecomponenttransfer"): NodeListOf<SVGFEComponentTransferElement>;
            getElementsByTagName(tagname: "fecomposite"): NodeListOf<SVGFECompositeElement>;
            getElementsByTagName(tagname: "feconvolvematrix"): NodeListOf<SVGFEConvolveMatrixElement>;
            getElementsByTagName(tagname: "fediffuselighting"): NodeListOf<SVGFEDiffuseLightingElement>;
            getElementsByTagName(tagname: "fedisplacementmap"): NodeListOf<SVGFEDisplacementMapElement>;
            getElementsByTagName(tagname: "fedistantlight"): NodeListOf<SVGFEDistantLightElement>;
            getElementsByTagName(tagname: "feflood"): NodeListOf<SVGFEFloodElement>;
            getElementsByTagName(tagname: "fefunca"): NodeListOf<SVGFEFuncAElement>;
            getElementsByTagName(tagname: "fefuncb"): NodeListOf<SVGFEFuncBElement>;
            getElementsByTagName(tagname: "fefuncg"): NodeListOf<SVGFEFuncGElement>;
            getElementsByTagName(tagname: "fefuncr"): NodeListOf<SVGFEFuncRElement>;
            getElementsByTagName(tagname: "fegaussianblur"): NodeListOf<SVGFEGaussianBlurElement>;
            getElementsByTagName(tagname: "feimage"): NodeListOf<SVGFEImageElement>;
            getElementsByTagName(tagname: "femerge"): NodeListOf<SVGFEMergeElement>;
            getElementsByTagName(tagname: "femergenode"): NodeListOf<SVGFEMergeNodeElement>;
            getElementsByTagName(tagname: "femorphology"): NodeListOf<SVGFEMorphologyElement>;
            getElementsByTagName(tagname: "feoffset"): NodeListOf<SVGFEOffsetElement>;
            getElementsByTagName(tagname: "fepointlight"): NodeListOf<SVGFEPointLightElement>;
            getElementsByTagName(tagname: "fespecularlighting"): NodeListOf<SVGFESpecularLightingElement>;
            getElementsByTagName(tagname: "fespotlight"): NodeListOf<SVGFESpotLightElement>;
            getElementsByTagName(tagname: "fetile"): NodeListOf<SVGFETileElement>;
            getElementsByTagName(tagname: "feturbulence"): NodeListOf<SVGFETurbulenceElement>;
            getElementsByTagName(tagname: "fieldset"): NodeListOf<HTMLFieldSetElement>;
            getElementsByTagName(tagname: "figcaption"): NodeListOf<HTMLElement>;
            getElementsByTagName(tagname: "figure"): NodeListOf<HTMLElement>;
            getElementsByTagName(tagname: "filter"): NodeListOf<SVGFilterElement>;
            getElementsByTagName(tagname: "font"): NodeListOf<HTMLFontElement>;
            getElementsByTagName(tagname: "footer"): NodeListOf<HTMLElement>;
            getElementsByTagName(tagname: "foreignobject"): NodeListOf<SVGForeignObjectElement>;
            getElementsByTagName(tagname: "form"): NodeListOf<HTMLFormElement>;
            getElementsByTagName(tagname: "frame"): NodeListOf<HTMLFrameElement>;
            getElementsByTagName(tagname: "frameset"): NodeListOf<HTMLFrameSetElement>;
            getElementsByTagName(tagname: "g"): NodeListOf<SVGGElement>;
            getElementsByTagName(tagname: "h1"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(tagname: "h2"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(tagname: "h3"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(tagname: "h4"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(tagname: "h5"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(tagname: "h6"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(tagname: "head"): NodeListOf<HTMLHeadElement>;
            getElementsByTagName(tagname: "header"): NodeListOf<HTMLElement>;
            getElementsByTagName(tagname: "hgroup"): NodeListOf<HTMLElement>;
            getElementsByTagName(tagname: "hr"): NodeListOf<HTMLHRElement>;
            getElementsByTagName(tagname: "html"): NodeListOf<HTMLHtmlElement>;
            getElementsByTagName(tagname: "i"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "iframe"): NodeListOf<HTMLIFrameElement>;
            getElementsByTagName(tagname: "image"): NodeListOf<SVGImageElement>;
            getElementsByTagName(tagname: "img"): NodeListOf<HTMLImageElement>;
            getElementsByTagName(tagname: "input"): NodeListOf<HTMLInputElement>;
            getElementsByTagName(tagname: "ins"): NodeListOf<HTMLModElement>;
            getElementsByTagName(tagname: "isindex"): NodeListOf<HTMLIsIndexElement>;
            getElementsByTagName(tagname: "kbd"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "keygen"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(tagname: "label"): NodeListOf<HTMLLabelElement>;
            getElementsByTagName(tagname: "legend"): NodeListOf<HTMLLegendElement>;
            getElementsByTagName(tagname: "li"): NodeListOf<HTMLLIElement>;
            getElementsByTagName(tagname: "line"): NodeListOf<SVGLineElement>;
            getElementsByTagName(tagname: "lineargradient"): NodeListOf<SVGLinearGradientElement>;
            getElementsByTagName(tagname: "link"): NodeListOf<HTMLLinkElement>;
            getElementsByTagName(tagname: "listing"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(tagname: "map"): NodeListOf<HTMLMapElement>;
            getElementsByTagName(tagname: "mark"): NodeListOf<HTMLElement>;
            getElementsByTagName(tagname: "marker"): NodeListOf<SVGMarkerElement>;
            getElementsByTagName(tagname: "marquee"): NodeListOf<HTMLMarqueeElement>;
            getElementsByTagName(tagname: "mask"): NodeListOf<SVGMaskElement>;
            getElementsByTagName(tagname: "menu"): NodeListOf<HTMLMenuElement>;
            getElementsByTagName(tagname: "meta"): NodeListOf<HTMLMetaElement>;
            getElementsByTagName(tagname: "metadata"): NodeListOf<SVGMetadataElement>;
            getElementsByTagName(tagname: "nav"): NodeListOf<HTMLElement>;
            getElementsByTagName(tagname: "nextid"): NodeListOf<HTMLNextIdElement>;
            getElementsByTagName(tagname: "nobr"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "noframes"): NodeListOf<HTMLElement>;
            getElementsByTagName(tagname: "noscript"): NodeListOf<HTMLElement>;
            getElementsByTagName(tagname: "object"): NodeListOf<HTMLObjectElement>;
            getElementsByTagName(tagname: "ol"): NodeListOf<HTMLOListElement>;
            getElementsByTagName(tagname: "optgroup"): NodeListOf<HTMLOptGroupElement>;
            getElementsByTagName(tagname: "option"): NodeListOf<HTMLOptionElement>;
            getElementsByTagName(tagname: "p"): NodeListOf<HTMLParagraphElement>;
            getElementsByTagName(tagname: "param"): NodeListOf<HTMLParamElement>;
            getElementsByTagName(tagname: "path"): NodeListOf<SVGPathElement>;
            getElementsByTagName(tagname: "pattern"): NodeListOf<SVGPatternElement>;
            getElementsByTagName(tagname: "plaintext"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(tagname: "polygon"): NodeListOf<SVGPolygonElement>;
            getElementsByTagName(tagname: "polyline"): NodeListOf<SVGPolylineElement>;
            getElementsByTagName(tagname: "pre"): NodeListOf<HTMLPreElement>;
            getElementsByTagName(tagname: "progress"): NodeListOf<HTMLProgressElement>;
            getElementsByTagName(tagname: "q"): NodeListOf<HTMLQuoteElement>;
            getElementsByTagName(tagname: "radialgradient"): NodeListOf<SVGRadialGradientElement>;
            getElementsByTagName(tagname: "rect"): NodeListOf<SVGRectElement>;
            getElementsByTagName(tagname: "rt"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "ruby"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "s"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "samp"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "script"): NodeListOf<HTMLScriptElement>;
            getElementsByTagName(tagname: "section"): NodeListOf<HTMLElement>;
            getElementsByTagName(tagname: "select"): NodeListOf<HTMLSelectElement>;
            getElementsByTagName(tagname: "small"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "source"): NodeListOf<HTMLSourceElement>;
            getElementsByTagName(tagname: "span"): NodeListOf<HTMLSpanElement>;
            getElementsByTagName(tagname: "stop"): NodeListOf<SVGStopElement>;
            getElementsByTagName(tagname: "strike"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "strong"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "style"): NodeListOf<HTMLStyleElement>;
            getElementsByTagName(tagname: "sub"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "sup"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "svg"): NodeListOf<SVGSVGElement>;
            getElementsByTagName(tagname: "switch"): NodeListOf<SVGSwitchElement>;
            getElementsByTagName(tagname: "symbol"): NodeListOf<SVGSymbolElement>;
            getElementsByTagName(tagname: "table"): NodeListOf<HTMLTableElement>;
            getElementsByTagName(tagname: "tbody"): NodeListOf<HTMLTableSectionElement>;
            getElementsByTagName(tagname: "td"): NodeListOf<HTMLTableDataCellElement>;
            getElementsByTagName(tagname: "text"): NodeListOf<SVGTextElement>;
            getElementsByTagName(tagname: "textpath"): NodeListOf<SVGTextPathElement>;
            getElementsByTagName(tagname: "textarea"): NodeListOf<HTMLTextAreaElement>;
            getElementsByTagName(tagname: "tfoot"): NodeListOf<HTMLTableSectionElement>;
            getElementsByTagName(tagname: "th"): NodeListOf<HTMLTableHeaderCellElement>;
            getElementsByTagName(tagname: "thead"): NodeListOf<HTMLTableSectionElement>;
            getElementsByTagName(tagname: "title"): NodeListOf<HTMLTitleElement>;
            getElementsByTagName(tagname: "tr"): NodeListOf<HTMLTableRowElement>;
            getElementsByTagName(tagname: "track"): NodeListOf<HTMLTrackElement>;
            getElementsByTagName(tagname: "tspan"): NodeListOf<SVGTSpanElement>;
            getElementsByTagName(tagname: "tt"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "u"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "ul"): NodeListOf<HTMLUListElement>;
            getElementsByTagName(tagname: "use"): NodeListOf<SVGUseElement>;
            getElementsByTagName(tagname: "var"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(tagname: "video"): NodeListOf<HTMLVideoElement>;
            getElementsByTagName(tagname: "view"): NodeListOf<SVGViewElement>;
            getElementsByTagName(tagname: "wbr"): NodeListOf<HTMLElement>;
            getElementsByTagName(tagname: "x-ms-webview"): NodeListOf<MSHTMLWebViewElement>;
            getElementsByTagName(tagname: "xmp"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(tagname: string): NodeList;
            getElementsByTagNameNS(namespaceURI: string, localName: string): NodeList;
            /**
              * Returns an object representing the current selection of the document that is loaded into the object displaying a webpage.
              */
            getSelection(): Selection;
            /**
              * Gets a value indicating whether the object currently has focus.
              */
            hasFocus(): boolean;
            importNode(importedNode: Node, deep: boolean): Node;
            msElementsFromPoint(x: number, y: number): NodeList;
            msElementsFromRect(left: number, top: number, width: number, height: number): NodeList;
            msGetPrintDocumentForNamedFlow(flowName: string): Document;
            msSetPrintDocumentUriForNamedFlow(flowName: string, uri: string): void;
            /**
              * Opens a new window and loads a document specified by a given URL. Also, opens a new window that uses the url parameter and the name parameter to collect the output of the write method and the writeln method.
              * @param url Specifies a MIME type for the document.
              * @param name Specifies the name of the window. This name is used as the value for the TARGET attribute on a form or an anchor element.
              * @param features Contains a list of items separated by commas. Each item consists of an option and a value, separated by an equals sign (for example, "fullscreen=yes, toolbar=yes"). The following values are supported.
              * @param replace Specifies whether the existing entry for the document is replaced in the history list.
              */
            open(url?: string, name?: string, features?: string, replace?: boolean): Document | Window;
            /** 
              * Returns a Boolean value that indicates whether a specified command can be successfully executed using execCommand, given the current state of the document.
              * @param commandId Specifies a command identifier.
              */
            queryCommandEnabled(commandId: string): boolean;
            /**
              * Returns a Boolean value that indicates whether the specified command is in the indeterminate state.
              * @param commandId String that specifies a command identifier.
              */
            queryCommandIndeterm(commandId: string): boolean;
            /**
              * Returns a Boolean value that indicates the current state of the command.
              * @param commandId String that specifies a command identifier.
              */
            queryCommandState(commandId: string): boolean;
            /**
              * Returns a Boolean value that indicates whether the current command is supported on the current range.
              * @param commandId Specifies a command identifier.
              */
            queryCommandSupported(commandId: string): boolean;
            /**
              * Retrieves the string associated with a command.
              * @param commandId String that contains the identifier of a command. This can be any command identifier given in the list of Command Identifiers. 
              */
            queryCommandText(commandId: string): string;
            /**
              * Returns the current value of the document, range, or current selection for the given command.
              * @param commandId String that specifies a command identifier.
              */
            queryCommandValue(commandId: string): string;
            releaseEvents(): void;
            /**
              * Allows updating the print settings for the page.
              */
            updateSettings(): void;
            webkitCancelFullScreen(): void;
            webkitExitFullscreen(): void;
            /**
              * Writes one or more HTML expressions to a document in the specified window. 
              * @param content Specifies the text and HTML tags to write.
              */
            write(...content: string[]): void;
            /**
              * Writes one or more HTML expressions, followed by a carriage return, to a document in the specified window. 
              * @param content The text and HTML tags to write.
              */
            writeln(...content: string[]): void;
            addEventListener(type: "MSContentZoom", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSManipulationStateChanged", listener: (ev: MSManipulationEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "fullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "fullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mssitemodejumplistitemremoved", listener: (ev: MSSiteModeEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "msthumbnailclick", listener: (ev: MSSiteModeEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerlockchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerlockerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "stop", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "touchcancel", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchend", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchmove", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchstart", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var Document: {
            prototype: Document;
            new(): Document;
        }
        
        interface DocumentFragment extends Node, NodeSelector {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var DocumentFragment: {
            prototype: DocumentFragment;
            new(): DocumentFragment;
        }
        
        interface DocumentType extends Node, ChildNode {
            entities: NamedNodeMap;
            internalSubset: string;
            name: string;
            notations: NamedNodeMap;
            publicId: string;
            systemId: string;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var DocumentType: {
            prototype: DocumentType;
            new(): DocumentType;
        }
        
        interface DragEvent extends MouseEvent {
            dataTransfer: DataTransfer;
            initDragEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget, dataTransferArg: DataTransfer): void;
            msConvertURL(file: File, targetType: string, targetURL?: string): void;
        }
        
        declare var DragEvent: {
            prototype: DragEvent;
            new(): DragEvent;
        }
        
        interface DynamicsCompressorNode extends AudioNode {
            attack: AudioParam;
            knee: AudioParam;
            ratio: AudioParam;
            reduction: AudioParam;
            release: AudioParam;
            threshold: AudioParam;
        }
        
        declare var DynamicsCompressorNode: {
            prototype: DynamicsCompressorNode;
            new(): DynamicsCompressorNode;
        }
        
        interface EXT_texture_filter_anisotropic {
            MAX_TEXTURE_MAX_ANISOTROPY_EXT: number;
            TEXTURE_MAX_ANISOTROPY_EXT: number;
        }
        
        declare var EXT_texture_filter_anisotropic: {
            prototype: EXT_texture_filter_anisotropic;
            new(): EXT_texture_filter_anisotropic;
            MAX_TEXTURE_MAX_ANISOTROPY_EXT: number;
            TEXTURE_MAX_ANISOTROPY_EXT: number;
        }
        
        interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelector, ChildNode {
            classList: DOMTokenList;
            clientHeight: number;
            clientLeft: number;
            clientTop: number;
            clientWidth: number;
            msContentZoomFactor: number;
            msRegionOverflow: string;
            onariarequest: (ev: AriaRequestEvent) => any;
            oncommand: (ev: CommandEvent) => any;
            ongotpointercapture: (ev: PointerEvent) => any;
            onlostpointercapture: (ev: PointerEvent) => any;
            onmsgesturechange: (ev: MSGestureEvent) => any;
            onmsgesturedoubletap: (ev: MSGestureEvent) => any;
            onmsgestureend: (ev: MSGestureEvent) => any;
            onmsgesturehold: (ev: MSGestureEvent) => any;
            onmsgesturestart: (ev: MSGestureEvent) => any;
            onmsgesturetap: (ev: MSGestureEvent) => any;
            onmsgotpointercapture: (ev: MSPointerEvent) => any;
            onmsinertiastart: (ev: MSGestureEvent) => any;
            onmslostpointercapture: (ev: MSPointerEvent) => any;
            onmspointercancel: (ev: MSPointerEvent) => any;
            onmspointerdown: (ev: MSPointerEvent) => any;
            onmspointerenter: (ev: MSPointerEvent) => any;
            onmspointerleave: (ev: MSPointerEvent) => any;
            onmspointermove: (ev: MSPointerEvent) => any;
            onmspointerout: (ev: MSPointerEvent) => any;
            onmspointerover: (ev: MSPointerEvent) => any;
            onmspointerup: (ev: MSPointerEvent) => any;
            ontouchcancel: (ev: TouchEvent) => any;
            ontouchend: (ev: TouchEvent) => any;
            ontouchmove: (ev: TouchEvent) => any;
            ontouchstart: (ev: TouchEvent) => any;
            onwebkitfullscreenchange: (ev: Event) => any;
            onwebkitfullscreenerror: (ev: Event) => any;
            scrollHeight: number;
            scrollLeft: number;
            scrollTop: number;
            scrollWidth: number;
            tagName: string;
            getAttribute(name?: string): string;
            getAttributeNS(namespaceURI: string, localName: string): string;
            getAttributeNode(name: string): Attr;
            getAttributeNodeNS(namespaceURI: string, localName: string): Attr;
            getBoundingClientRect(): ClientRect;
            getClientRects(): ClientRectList;
            getElementsByTagName(name: "a"): NodeListOf<HTMLAnchorElement>;
            getElementsByTagName(name: "abbr"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "acronym"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "address"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "applet"): NodeListOf<HTMLAppletElement>;
            getElementsByTagName(name: "area"): NodeListOf<HTMLAreaElement>;
            getElementsByTagName(name: "article"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "aside"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "audio"): NodeListOf<HTMLAudioElement>;
            getElementsByTagName(name: "b"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "base"): NodeListOf<HTMLBaseElement>;
            getElementsByTagName(name: "basefont"): NodeListOf<HTMLBaseFontElement>;
            getElementsByTagName(name: "bdo"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "big"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "blockquote"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "body"): NodeListOf<HTMLBodyElement>;
            getElementsByTagName(name: "br"): NodeListOf<HTMLBRElement>;
            getElementsByTagName(name: "button"): NodeListOf<HTMLButtonElement>;
            getElementsByTagName(name: "canvas"): NodeListOf<HTMLCanvasElement>;
            getElementsByTagName(name: "caption"): NodeListOf<HTMLTableCaptionElement>;
            getElementsByTagName(name: "center"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "circle"): NodeListOf<SVGCircleElement>;
            getElementsByTagName(name: "cite"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "clippath"): NodeListOf<SVGClipPathElement>;
            getElementsByTagName(name: "code"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "col"): NodeListOf<HTMLTableColElement>;
            getElementsByTagName(name: "colgroup"): NodeListOf<HTMLTableColElement>;
            getElementsByTagName(name: "datalist"): NodeListOf<HTMLDataListElement>;
            getElementsByTagName(name: "dd"): NodeListOf<HTMLDDElement>;
            getElementsByTagName(name: "defs"): NodeListOf<SVGDefsElement>;
            getElementsByTagName(name: "del"): NodeListOf<HTMLModElement>;
            getElementsByTagName(name: "desc"): NodeListOf<SVGDescElement>;
            getElementsByTagName(name: "dfn"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "dir"): NodeListOf<HTMLDirectoryElement>;
            getElementsByTagName(name: "div"): NodeListOf<HTMLDivElement>;
            getElementsByTagName(name: "dl"): NodeListOf<HTMLDListElement>;
            getElementsByTagName(name: "dt"): NodeListOf<HTMLDTElement>;
            getElementsByTagName(name: "ellipse"): NodeListOf<SVGEllipseElement>;
            getElementsByTagName(name: "em"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "embed"): NodeListOf<HTMLEmbedElement>;
            getElementsByTagName(name: "feblend"): NodeListOf<SVGFEBlendElement>;
            getElementsByTagName(name: "fecolormatrix"): NodeListOf<SVGFEColorMatrixElement>;
            getElementsByTagName(name: "fecomponenttransfer"): NodeListOf<SVGFEComponentTransferElement>;
            getElementsByTagName(name: "fecomposite"): NodeListOf<SVGFECompositeElement>;
            getElementsByTagName(name: "feconvolvematrix"): NodeListOf<SVGFEConvolveMatrixElement>;
            getElementsByTagName(name: "fediffuselighting"): NodeListOf<SVGFEDiffuseLightingElement>;
            getElementsByTagName(name: "fedisplacementmap"): NodeListOf<SVGFEDisplacementMapElement>;
            getElementsByTagName(name: "fedistantlight"): NodeListOf<SVGFEDistantLightElement>;
            getElementsByTagName(name: "feflood"): NodeListOf<SVGFEFloodElement>;
            getElementsByTagName(name: "fefunca"): NodeListOf<SVGFEFuncAElement>;
            getElementsByTagName(name: "fefuncb"): NodeListOf<SVGFEFuncBElement>;
            getElementsByTagName(name: "fefuncg"): NodeListOf<SVGFEFuncGElement>;
            getElementsByTagName(name: "fefuncr"): NodeListOf<SVGFEFuncRElement>;
            getElementsByTagName(name: "fegaussianblur"): NodeListOf<SVGFEGaussianBlurElement>;
            getElementsByTagName(name: "feimage"): NodeListOf<SVGFEImageElement>;
            getElementsByTagName(name: "femerge"): NodeListOf<SVGFEMergeElement>;
            getElementsByTagName(name: "femergenode"): NodeListOf<SVGFEMergeNodeElement>;
            getElementsByTagName(name: "femorphology"): NodeListOf<SVGFEMorphologyElement>;
            getElementsByTagName(name: "feoffset"): NodeListOf<SVGFEOffsetElement>;
            getElementsByTagName(name: "fepointlight"): NodeListOf<SVGFEPointLightElement>;
            getElementsByTagName(name: "fespecularlighting"): NodeListOf<SVGFESpecularLightingElement>;
            getElementsByTagName(name: "fespotlight"): NodeListOf<SVGFESpotLightElement>;
            getElementsByTagName(name: "fetile"): NodeListOf<SVGFETileElement>;
            getElementsByTagName(name: "feturbulence"): NodeListOf<SVGFETurbulenceElement>;
            getElementsByTagName(name: "fieldset"): NodeListOf<HTMLFieldSetElement>;
            getElementsByTagName(name: "figcaption"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "figure"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "filter"): NodeListOf<SVGFilterElement>;
            getElementsByTagName(name: "font"): NodeListOf<HTMLFontElement>;
            getElementsByTagName(name: "footer"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "foreignobject"): NodeListOf<SVGForeignObjectElement>;
            getElementsByTagName(name: "form"): NodeListOf<HTMLFormElement>;
            getElementsByTagName(name: "frame"): NodeListOf<HTMLFrameElement>;
            getElementsByTagName(name: "frameset"): NodeListOf<HTMLFrameSetElement>;
            getElementsByTagName(name: "g"): NodeListOf<SVGGElement>;
            getElementsByTagName(name: "h1"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h2"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h3"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h4"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h5"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "h6"): NodeListOf<HTMLHeadingElement>;
            getElementsByTagName(name: "head"): NodeListOf<HTMLHeadElement>;
            getElementsByTagName(name: "header"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "hgroup"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "hr"): NodeListOf<HTMLHRElement>;
            getElementsByTagName(name: "html"): NodeListOf<HTMLHtmlElement>;
            getElementsByTagName(name: "i"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "iframe"): NodeListOf<HTMLIFrameElement>;
            getElementsByTagName(name: "image"): NodeListOf<SVGImageElement>;
            getElementsByTagName(name: "img"): NodeListOf<HTMLImageElement>;
            getElementsByTagName(name: "input"): NodeListOf<HTMLInputElement>;
            getElementsByTagName(name: "ins"): NodeListOf<HTMLModElement>;
            getElementsByTagName(name: "isindex"): NodeListOf<HTMLIsIndexElement>;
            getElementsByTagName(name: "kbd"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "keygen"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "label"): NodeListOf<HTMLLabelElement>;
            getElementsByTagName(name: "legend"): NodeListOf<HTMLLegendElement>;
            getElementsByTagName(name: "li"): NodeListOf<HTMLLIElement>;
            getElementsByTagName(name: "line"): NodeListOf<SVGLineElement>;
            getElementsByTagName(name: "lineargradient"): NodeListOf<SVGLinearGradientElement>;
            getElementsByTagName(name: "link"): NodeListOf<HTMLLinkElement>;
            getElementsByTagName(name: "listing"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "map"): NodeListOf<HTMLMapElement>;
            getElementsByTagName(name: "mark"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "marker"): NodeListOf<SVGMarkerElement>;
            getElementsByTagName(name: "marquee"): NodeListOf<HTMLMarqueeElement>;
            getElementsByTagName(name: "mask"): NodeListOf<SVGMaskElement>;
            getElementsByTagName(name: "menu"): NodeListOf<HTMLMenuElement>;
            getElementsByTagName(name: "meta"): NodeListOf<HTMLMetaElement>;
            getElementsByTagName(name: "metadata"): NodeListOf<SVGMetadataElement>;
            getElementsByTagName(name: "nav"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "nextid"): NodeListOf<HTMLNextIdElement>;
            getElementsByTagName(name: "nobr"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "noframes"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "noscript"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "object"): NodeListOf<HTMLObjectElement>;
            getElementsByTagName(name: "ol"): NodeListOf<HTMLOListElement>;
            getElementsByTagName(name: "optgroup"): NodeListOf<HTMLOptGroupElement>;
            getElementsByTagName(name: "option"): NodeListOf<HTMLOptionElement>;
            getElementsByTagName(name: "p"): NodeListOf<HTMLParagraphElement>;
            getElementsByTagName(name: "param"): NodeListOf<HTMLParamElement>;
            getElementsByTagName(name: "path"): NodeListOf<SVGPathElement>;
            getElementsByTagName(name: "pattern"): NodeListOf<SVGPatternElement>;
            getElementsByTagName(name: "plaintext"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: "polygon"): NodeListOf<SVGPolygonElement>;
            getElementsByTagName(name: "polyline"): NodeListOf<SVGPolylineElement>;
            getElementsByTagName(name: "pre"): NodeListOf<HTMLPreElement>;
            getElementsByTagName(name: "progress"): NodeListOf<HTMLProgressElement>;
            getElementsByTagName(name: "q"): NodeListOf<HTMLQuoteElement>;
            getElementsByTagName(name: "radialgradient"): NodeListOf<SVGRadialGradientElement>;
            getElementsByTagName(name: "rect"): NodeListOf<SVGRectElement>;
            getElementsByTagName(name: "rt"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "ruby"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "s"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "samp"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "script"): NodeListOf<HTMLScriptElement>;
            getElementsByTagName(name: "section"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "select"): NodeListOf<HTMLSelectElement>;
            getElementsByTagName(name: "small"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "source"): NodeListOf<HTMLSourceElement>;
            getElementsByTagName(name: "span"): NodeListOf<HTMLSpanElement>;
            getElementsByTagName(name: "stop"): NodeListOf<SVGStopElement>;
            getElementsByTagName(name: "strike"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "strong"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "style"): NodeListOf<HTMLStyleElement>;
            getElementsByTagName(name: "sub"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "sup"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "svg"): NodeListOf<SVGSVGElement>;
            getElementsByTagName(name: "switch"): NodeListOf<SVGSwitchElement>;
            getElementsByTagName(name: "symbol"): NodeListOf<SVGSymbolElement>;
            getElementsByTagName(name: "table"): NodeListOf<HTMLTableElement>;
            getElementsByTagName(name: "tbody"): NodeListOf<HTMLTableSectionElement>;
            getElementsByTagName(name: "td"): NodeListOf<HTMLTableDataCellElement>;
            getElementsByTagName(name: "text"): NodeListOf<SVGTextElement>;
            getElementsByTagName(name: "textpath"): NodeListOf<SVGTextPathElement>;
            getElementsByTagName(name: "textarea"): NodeListOf<HTMLTextAreaElement>;
            getElementsByTagName(name: "tfoot"): NodeListOf<HTMLTableSectionElement>;
            getElementsByTagName(name: "th"): NodeListOf<HTMLTableHeaderCellElement>;
            getElementsByTagName(name: "thead"): NodeListOf<HTMLTableSectionElement>;
            getElementsByTagName(name: "title"): NodeListOf<HTMLTitleElement>;
            getElementsByTagName(name: "tr"): NodeListOf<HTMLTableRowElement>;
            getElementsByTagName(name: "track"): NodeListOf<HTMLTrackElement>;
            getElementsByTagName(name: "tspan"): NodeListOf<SVGTSpanElement>;
            getElementsByTagName(name: "tt"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "u"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "ul"): NodeListOf<HTMLUListElement>;
            getElementsByTagName(name: "use"): NodeListOf<SVGUseElement>;
            getElementsByTagName(name: "var"): NodeListOf<HTMLPhraseElement>;
            getElementsByTagName(name: "video"): NodeListOf<HTMLVideoElement>;
            getElementsByTagName(name: "view"): NodeListOf<SVGViewElement>;
            getElementsByTagName(name: "wbr"): NodeListOf<HTMLElement>;
            getElementsByTagName(name: "x-ms-webview"): NodeListOf<MSHTMLWebViewElement>;
            getElementsByTagName(name: "xmp"): NodeListOf<HTMLBlockElement>;
            getElementsByTagName(name: string): NodeList;
            getElementsByTagNameNS(namespaceURI: string, localName: string): NodeList;
            hasAttribute(name: string): boolean;
            hasAttributeNS(namespaceURI: string, localName: string): boolean;
            msGetRegionContent(): MSRangeCollection;
            msGetUntransformedBounds(): ClientRect;
            msMatchesSelector(selectors: string): boolean;
            msReleasePointerCapture(pointerId: number): void;
            msSetPointerCapture(pointerId: number): void;
            msZoomTo(args: MsZoomToOptions): void;
            releasePointerCapture(pointerId: number): void;
            removeAttribute(name?: string): void;
            removeAttributeNS(namespaceURI: string, localName: string): void;
            removeAttributeNode(oldAttr: Attr): Attr;
            requestFullscreen(): void;
            requestPointerLock(): void;
            setAttribute(name?: string, value?: string): void;
            setAttributeNS(namespaceURI: string, qualifiedName: string, value: string): void;
            setAttributeNode(newAttr: Attr): Attr;
            setAttributeNodeNS(newAttr: Attr): Attr;
            setPointerCapture(pointerId: number): void;
            webkitMatchesSelector(selectors: string): boolean;
            webkitRequestFullScreen(): void;
            webkitRequestFullscreen(): void;
            addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGotPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSLostPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchcancel", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchend", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchmove", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchstart", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var Element: {
            prototype: Element;
            new(): Element;
        }
        
        interface ErrorEvent extends Event {
            colno: number;
            error: any;
            filename: string;
            lineno: number;
            message: string;
            initErrorEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, messageArg: string, filenameArg: string, linenoArg: number): void;
        }
        
        declare var ErrorEvent: {
            prototype: ErrorEvent;
            new(): ErrorEvent;
        }
        
        interface Event {
            bubbles: boolean;
            cancelBubble: boolean;
            cancelable: boolean;
            currentTarget: EventTarget;
            defaultPrevented: boolean;
            eventPhase: number;
            isTrusted: boolean;
            returnValue: boolean;
            srcElement: Element;
            target: EventTarget;
            timeStamp: number;
            type: string;
            initEvent(eventTypeArg: string, canBubbleArg: boolean, cancelableArg: boolean): void;
            preventDefault(): void;
            stopImmediatePropagation(): void;
            stopPropagation(): void;
            AT_TARGET: number;
            BUBBLING_PHASE: number;
            CAPTURING_PHASE: number;
        }
        
        declare var Event: {
            prototype: Event;
            new(type: string, eventInitDict?: EventInit): Event;
            AT_TARGET: number;
            BUBBLING_PHASE: number;
            CAPTURING_PHASE: number;
        }
        
        interface EventTarget {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
            dispatchEvent(evt: Event): boolean;
            removeEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var EventTarget: {
            prototype: EventTarget;
            new(): EventTarget;
        }
        
        interface External {
        }
        
        declare var External: {
            prototype: External;
            new(): External;
        }
        
        interface File extends Blob {
            lastModifiedDate: any;
            name: string;
        }
        
        declare var File: {
            prototype: File;
            new(): File;
        }
        
        interface FileList {
            length: number;
            item(index: number): File;
            [index: number]: File;
        }
        
        declare var FileList: {
            prototype: FileList;
            new(): FileList;
        }
        
        interface FileReader extends EventTarget, MSBaseReader {
            error: DOMError;
            readAsArrayBuffer(blob: Blob): void;
            readAsBinaryString(blob: Blob): void;
            readAsDataURL(blob: Blob): void;
            readAsText(blob: Blob, encoding?: string): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var FileReader: {
            prototype: FileReader;
            new(): FileReader;
        }
        
        interface FocusEvent extends UIEvent {
            relatedTarget: EventTarget;
            initFocusEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, relatedTargetArg: EventTarget): void;
        }
        
        declare var FocusEvent: {
            prototype: FocusEvent;
            new(typeArg: string, eventInitDict?: FocusEventInit): FocusEvent;
        }
        
        interface FormData {
            append(name: any, value: any, blobName?: string): void;
        }
        
        declare var FormData: {
            prototype: FormData;
            new(): FormData;
        }
        
        interface GainNode extends AudioNode {
            gain: AudioParam;
        }
        
        declare var GainNode: {
            prototype: GainNode;
            new(): GainNode;
        }
        
        interface Gamepad {
            axes: number[];
            buttons: GamepadButton[];
            connected: boolean;
            id: string;
            index: number;
            mapping: string;
            timestamp: number;
        }
        
        declare var Gamepad: {
            prototype: Gamepad;
            new(): Gamepad;
        }
        
        interface GamepadButton {
            pressed: boolean;
            value: number;
        }
        
        declare var GamepadButton: {
            prototype: GamepadButton;
            new(): GamepadButton;
        }
        
        interface GamepadEvent extends Event {
            gamepad: Gamepad;
        }
        
        declare var GamepadEvent: {
            prototype: GamepadEvent;
            new(): GamepadEvent;
        }
        
        interface Geolocation {
            clearWatch(watchId: number): void;
            getCurrentPosition(successCallback: PositionCallback, errorCallback?: PositionErrorCallback, options?: PositionOptions): void;
            watchPosition(successCallback: PositionCallback, errorCallback?: PositionErrorCallback, options?: PositionOptions): number;
        }
        
        declare var Geolocation: {
            prototype: Geolocation;
            new(): Geolocation;
        }
        
        interface HTMLAllCollection extends HTMLCollection {
            namedItem(name: string): Element;
        }
        
        declare var HTMLAllCollection: {
            prototype: HTMLAllCollection;
            new(): HTMLAllCollection;
        }
        
        interface HTMLAnchorElement extends HTMLElement {
            Methods: string;
            /**
              * Sets or retrieves the character set used to encode the object.
              */
            charset: string;
            /**
              * Sets or retrieves the coordinates of the object.
              */
            coords: string;
            /**
              * Contains the anchor portion of the URL including the hash sign (#).
              */
            hash: string;
            /**
              * Contains the hostname and port values of the URL.
              */
            host: string;
            /**
              * Contains the hostname of a URL.
              */
            hostname: string;
            /**
              * Sets or retrieves a destination URL or an anchor point.
              */
            href: string;
            /**
              * Sets or retrieves the language code of the object.
              */
            hreflang: string;
            mimeType: string;
            /**
              * Sets or retrieves the shape of the object.
              */
            name: string;
            nameProp: string;
            /**
              * Contains the pathname of the URL.
              */
            pathname: string;
            /**
              * Sets or retrieves the port number associated with a URL.
              */
            port: string;
            /**
              * Contains the protocol of the URL.
              */
            protocol: string;
            protocolLong: string;
            /**
              * Sets or retrieves the relationship between the object and the destination of the link.
              */
            rel: string;
            /**
              * Sets or retrieves the relationship between the object and the destination of the link.
              */
            rev: string;
            /**
              * Sets or retrieves the substring of the href property that follows the question mark.
              */
            search: string;
            /**
              * Sets or retrieves the shape of the object.
              */
            shape: string;
            /**
              * Sets or retrieves the window or frame at which to target content.
              */
            target: string;
            /**
              * Retrieves or sets the text of the object as a string. 
              */
            text: string;
            type: string;
            urn: string;
            /** 
              * Returns a string representation of an object.
              */
            toString(): string;
        }
        
        declare var HTMLAnchorElement: {
            prototype: HTMLAnchorElement;
            new(): HTMLAnchorElement;
        }
        
        interface HTMLAppletElement extends HTMLElement {
            /**
              * Retrieves a string of the URL where the object tag can be found. This is often the href of the document that the object is in, or the value set by a base element.
              */
            BaseHref: string;
            align: string;
            /**
              * Sets or retrieves a text alternative to the graphic.
              */
            alt: string;
            /**
              * Gets or sets the optional alternative HTML script to execute if the object fails to load.
              */
            altHtml: string;
            /**
              * Sets or retrieves a character string that can be used to implement your own archive functionality for the object.
              */
            archive: string;
            border: string;
            code: string;
            /**
              * Sets or retrieves the URL of the component.
              */
            codeBase: string;
            /**
              * Sets or retrieves the Internet media type for the code associated with the object.
              */
            codeType: string;
            /**
              * Address of a pointer to the document this page or frame contains. If there is no document, then null will be returned.
              */
            contentDocument: Document;
            /**
              * Sets or retrieves the URL that references the data of the object.
              */
            data: string;
            /**
              * Sets or retrieves a character string that can be used to implement your own declare functionality for the object.
              */
            declare: boolean;
            form: HTMLFormElement;
            /**
              * Sets or retrieves the height of the object.
              */
            height: string;
            hspace: number;
            /**
              * Sets or retrieves the shape of the object.
              */
            name: string;
            object: string;
            /**
              * Sets or retrieves a message to be displayed while an object is loading.
              */
            standby: string;
            /**
              * Returns the content type of the object.
              */
            type: string;
            /**
              * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.
              */
            useMap: string;
            vspace: number;
            width: number;
        }
        
        declare var HTMLAppletElement: {
            prototype: HTMLAppletElement;
            new(): HTMLAppletElement;
        }
        
        interface HTMLAreaElement extends HTMLElement {
            /**
              * Sets or retrieves a text alternative to the graphic.
              */
            alt: string;
            /**
              * Sets or retrieves the coordinates of the object.
              */
            coords: string;
            /**
              * Sets or retrieves the subsection of the href property that follows the number sign (#).
              */
            hash: string;
            /**
              * Sets or retrieves the hostname and port number of the location or URL.
              */
            host: string;
            /**
              * Sets or retrieves the host name part of the location or URL. 
              */
            hostname: string;
            /**
              * Sets or retrieves a destination URL or an anchor point.
              */
            href: string;
            /**
              * Sets or gets whether clicks in this region cause action.
              */
            noHref: boolean;
            /**
              * Sets or retrieves the file name or path specified by the object.
              */
            pathname: string;
            /**
              * Sets or retrieves the port number associated with a URL.
              */
            port: string;
            /**
              * Sets or retrieves the protocol portion of a URL.
              */
            protocol: string;
            rel: string;
            /**
              * Sets or retrieves the substring of the href property that follows the question mark.
              */
            search: string;
            /**
              * Sets or retrieves the shape of the object.
              */
            shape: string;
            /**
              * Sets or retrieves the window or frame at which to target content.
              */
            target: string;
            /** 
              * Returns a string representation of an object.
              */
            toString(): string;
        }
        
        declare var HTMLAreaElement: {
            prototype: HTMLAreaElement;
            new(): HTMLAreaElement;
        }
        
        interface HTMLAreasCollection extends HTMLCollection {
            /**
              * Adds an element to the areas, controlRange, or options collection.
              */
            add(element: HTMLElement, before?: HTMLElement): void;
            add(element: HTMLElement, before?: number): void;
            /**
              * Removes an element from the collection.
              */
            remove(index?: number): void;
        }
        
        declare var HTMLAreasCollection: {
            prototype: HTMLAreasCollection;
            new(): HTMLAreasCollection;
        }
        
        interface HTMLAudioElement extends HTMLMediaElement {
        }
        
        declare var HTMLAudioElement: {
            prototype: HTMLAudioElement;
            new(): HTMLAudioElement;
        }
        
        interface HTMLBRElement extends HTMLElement {
            /**
              * Sets or retrieves the side on which floating objects are not to be positioned when any IHTMLBlockElement is inserted into the document.
              */
            clear: string;
        }
        
        declare var HTMLBRElement: {
            prototype: HTMLBRElement;
            new(): HTMLBRElement;
        }
        
        interface HTMLBaseElement extends HTMLElement {
            /**
              * Gets or sets the baseline URL on which relative links are based.
              */
            href: string;
            /**
              * Sets or retrieves the window or frame at which to target content.
              */
            target: string;
        }
        
        declare var HTMLBaseElement: {
            prototype: HTMLBaseElement;
            new(): HTMLBaseElement;
        }
        
        interface HTMLBaseFontElement extends HTMLElement, DOML2DeprecatedColorProperty {
            /**
              * Sets or retrieves the current typeface family.
              */
            face: string;
            /**
              * Sets or retrieves the font size of the object.
              */
            size: number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLBaseFontElement: {
            prototype: HTMLBaseFontElement;
            new(): HTMLBaseFontElement;
        }
        
        interface HTMLBlockElement extends HTMLElement {
            /**
              * Sets or retrieves reference information about the object.
              */
            cite: string;
            clear: string;
            /**
              * Sets or retrieves the width of the object.
              */
            width: number;
        }
        
        declare var HTMLBlockElement: {
            prototype: HTMLBlockElement;
            new(): HTMLBlockElement;
        }
        
        interface HTMLBodyElement extends HTMLElement {
            aLink: any;
            background: string;
            bgColor: any;
            bgProperties: string;
            link: any;
            noWrap: boolean;
            onafterprint: (ev: Event) => any;
            onbeforeprint: (ev: Event) => any;
            onbeforeunload: (ev: BeforeUnloadEvent) => any;
            onblur: (ev: FocusEvent) => any;
            onerror: (ev: Event) => any;
            onfocus: (ev: FocusEvent) => any;
            onhashchange: (ev: HashChangeEvent) => any;
            onload: (ev: Event) => any;
            onmessage: (ev: MessageEvent) => any;
            onoffline: (ev: Event) => any;
            ononline: (ev: Event) => any;
            onorientationchange: (ev: Event) => any;
            onpagehide: (ev: PageTransitionEvent) => any;
            onpageshow: (ev: PageTransitionEvent) => any;
            onpopstate: (ev: PopStateEvent) => any;
            onresize: (ev: UIEvent) => any;
            onstorage: (ev: StorageEvent) => any;
            onunload: (ev: Event) => any;
            text: any;
            vLink: any;
            createTextRange(): TextRange;
            addEventListener(type: "MSContentZoom", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGotPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSLostPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSManipulationStateChanged", listener: (ev: MSManipulationEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "afterprint", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeprint", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeunload", listener: (ev: BeforeUnloadEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "hashchange", listener: (ev: HashChangeEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "offline", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "online", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "orientationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pagehide", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pageshow", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "popstate", listener: (ev: PopStateEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "storage", listener: (ev: StorageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "touchcancel", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchend", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchmove", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchstart", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "unload", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLBodyElement: {
            prototype: HTMLBodyElement;
            new(): HTMLBodyElement;
        }
        
        interface HTMLButtonElement extends HTMLElement {
            /**
              * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.
              */
            autofocus: boolean;
            disabled: boolean;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /**
              * Overrides the action attribute (where the data on a form is sent) on the parent form element.
              */
            formAction: string;
            /**
              * Used to override the encoding (formEnctype attribute) specified on the form element.
              */
            formEnctype: string;
            /**
              * Overrides the submit method attribute previously specified on a form element.
              */
            formMethod: string;
            /**
              * Overrides any validation or required attributes on a form or form elements to allow it to be submitted without validation. This can be used to create a "save draft"-type submit option.
              */
            formNoValidate: string;
            /**
              * Overrides the target attribute on a form element.
              */
            formTarget: string;
            /** 
              * Sets or retrieves the name of the object.
              */
            name: string;
            status: any;
            /**
              * Gets the classification and default behavior of the button.
              */
            type: string;
            /**
              * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
              */
            validationMessage: string;
            /**
              * Returns a  ValidityState object that represents the validity states of an element.
              */
            validity: ValidityState;
            /** 
              * Sets or retrieves the default or selected value of the control.
              */
            value: string;
            /**
              * Returns whether an element will successfully validate based on forms validation rules and constraints.
              */
            willValidate: boolean;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
            /**
              * Creates a TextRange object for the element.
              */
            createTextRange(): TextRange;
            /**
              * Sets a custom error message that is displayed when a form is submitted.
              * @param error Sets a custom error message that is displayed when a form is submitted.
              */
            setCustomValidity(error: string): void;
        }
        
        declare var HTMLButtonElement: {
            prototype: HTMLButtonElement;
            new(): HTMLButtonElement;
        }
        
        interface HTMLCanvasElement extends HTMLElement {
            /**
              * Gets or sets the height of a canvas element on a document.
              */
            height: number;
            /**
              * Gets or sets the width of a canvas element on a document.
              */
            width: number;
            /**
              * Returns an object that provides methods and properties for drawing and manipulating images and graphics on a canvas element in a document. A context object includes information about colors, line widths, fonts, and other graphic parameters that can be drawn on a canvas.
              * @param contextId The identifier (ID) of the type of canvas to create. Internet Explorer 9 and Internet Explorer 10 support only a 2-D context using canvas.getContext("2d"); IE11 Preview also supports 3-D or WebGL context using canvas.getContext("experimental-webgl");
              */
            getContext(contextId: string, ...args: any[]): CanvasRenderingContext2D | WebGLRenderingContext;
            /**
              * Returns a blob object encoded as a Portable Network Graphics (PNG) format from a canvas image or drawing.
              */
            msToBlob(): Blob;
            /**
              * Returns the content of the current canvas as an image that you can use as a source for another canvas or an HTML element.
              * @param type The standard MIME type for the image format to return. If you do not specify this parameter, the default value is a PNG format image.
              */
            toDataURL(type?: string, ...args: any[]): string;
        }
        
        declare var HTMLCanvasElement: {
            prototype: HTMLCanvasElement;
            new(): HTMLCanvasElement;
        }
        
        interface HTMLCollection {
            /**
              * Sets or retrieves the number of objects in a collection.
              */
            length: number;
            /**
              * Retrieves an object from various collections.
              */
            item(nameOrIndex?: any, optionalIndex?: any): Element;
            /**
              * Retrieves a select object or an object from an options collection.
              */
            namedItem(name: string): Element;
            [index: number]: Element;
        }
        
        declare var HTMLCollection: {
            prototype: HTMLCollection;
            new(): HTMLCollection;
        }
        
        interface HTMLDDElement extends HTMLElement {
            /**
              * Sets or retrieves whether the browser automatically performs wordwrap.
              */
            noWrap: boolean;
        }
        
        declare var HTMLDDElement: {
            prototype: HTMLDDElement;
            new(): HTMLDDElement;
        }
        
        interface HTMLDListElement extends HTMLElement {
            compact: boolean;
        }
        
        declare var HTMLDListElement: {
            prototype: HTMLDListElement;
            new(): HTMLDListElement;
        }
        
        interface HTMLDTElement extends HTMLElement {
            /**
              * Sets or retrieves whether the browser automatically performs wordwrap.
              */
            noWrap: boolean;
        }
        
        declare var HTMLDTElement: {
            prototype: HTMLDTElement;
            new(): HTMLDTElement;
        }
        
        interface HTMLDataListElement extends HTMLElement {
            options: HTMLCollection;
        }
        
        declare var HTMLDataListElement: {
            prototype: HTMLDataListElement;
            new(): HTMLDataListElement;
        }
        
        interface HTMLDirectoryElement extends HTMLElement {
            compact: boolean;
        }
        
        declare var HTMLDirectoryElement: {
            prototype: HTMLDirectoryElement;
            new(): HTMLDirectoryElement;
        }
        
        interface HTMLDivElement extends HTMLElement {
            /**
              * Sets or retrieves how the object is aligned with adjacent text. 
              */
            align: string;
            /**
              * Sets or retrieves whether the browser automatically performs wordwrap.
              */
            noWrap: boolean;
        }
        
        declare var HTMLDivElement: {
            prototype: HTMLDivElement;
            new(): HTMLDivElement;
        }
        
        interface HTMLDocument extends Document {
        }
        
        declare var HTMLDocument: {
            prototype: HTMLDocument;
            new(): HTMLDocument;
        }
        
        interface HTMLElement extends Element {
            accessKey: string;
            children: HTMLCollection;
            className: string;
            contentEditable: string;
            dataset: DOMStringMap;
            dir: string;
            draggable: boolean;
            hidden: boolean;
            hideFocus: boolean;
            id: string;
            innerHTML: string;
            innerText: string;
            isContentEditable: boolean;
            lang: string;
            offsetHeight: number;
            offsetLeft: number;
            offsetParent: Element;
            offsetTop: number;
            offsetWidth: number;
            onabort: (ev: Event) => any;
            onactivate: (ev: UIEvent) => any;
            onbeforeactivate: (ev: UIEvent) => any;
            onbeforecopy: (ev: DragEvent) => any;
            onbeforecut: (ev: DragEvent) => any;
            onbeforedeactivate: (ev: UIEvent) => any;
            onbeforepaste: (ev: DragEvent) => any;
            onblur: (ev: FocusEvent) => any;
            oncanplay: (ev: Event) => any;
            oncanplaythrough: (ev: Event) => any;
            onchange: (ev: Event) => any;
            onclick: (ev: MouseEvent) => any;
            oncontextmenu: (ev: PointerEvent) => any;
            oncopy: (ev: DragEvent) => any;
            oncuechange: (ev: Event) => any;
            oncut: (ev: DragEvent) => any;
            ondblclick: (ev: MouseEvent) => any;
            ondeactivate: (ev: UIEvent) => any;
            ondrag: (ev: DragEvent) => any;
            ondragend: (ev: DragEvent) => any;
            ondragenter: (ev: DragEvent) => any;
            ondragleave: (ev: DragEvent) => any;
            ondragover: (ev: DragEvent) => any;
            ondragstart: (ev: DragEvent) => any;
            ondrop: (ev: DragEvent) => any;
            ondurationchange: (ev: Event) => any;
            onemptied: (ev: Event) => any;
            onended: (ev: Event) => any;
            onerror: (ev: Event) => any;
            onfocus: (ev: FocusEvent) => any;
            oninput: (ev: Event) => any;
            onkeydown: (ev: KeyboardEvent) => any;
            onkeypress: (ev: KeyboardEvent) => any;
            onkeyup: (ev: KeyboardEvent) => any;
            onload: (ev: Event) => any;
            onloadeddata: (ev: Event) => any;
            onloadedmetadata: (ev: Event) => any;
            onloadstart: (ev: Event) => any;
            onmousedown: (ev: MouseEvent) => any;
            onmouseenter: (ev: MouseEvent) => any;
            onmouseleave: (ev: MouseEvent) => any;
            onmousemove: (ev: MouseEvent) => any;
            onmouseout: (ev: MouseEvent) => any;
            onmouseover: (ev: MouseEvent) => any;
            onmouseup: (ev: MouseEvent) => any;
            onmousewheel: (ev: MouseWheelEvent) => any;
            onmscontentzoom: (ev: UIEvent) => any;
            onmsmanipulationstatechanged: (ev: MSManipulationEvent) => any;
            onpaste: (ev: DragEvent) => any;
            onpause: (ev: Event) => any;
            onplay: (ev: Event) => any;
            onplaying: (ev: Event) => any;
            onprogress: (ev: ProgressEvent) => any;
            onratechange: (ev: Event) => any;
            onreset: (ev: Event) => any;
            onscroll: (ev: UIEvent) => any;
            onseeked: (ev: Event) => any;
            onseeking: (ev: Event) => any;
            onselect: (ev: UIEvent) => any;
            onselectstart: (ev: Event) => any;
            onstalled: (ev: Event) => any;
            onsubmit: (ev: Event) => any;
            onsuspend: (ev: Event) => any;
            ontimeupdate: (ev: Event) => any;
            onvolumechange: (ev: Event) => any;
            onwaiting: (ev: Event) => any;
            outerHTML: string;
            outerText: string;
            spellcheck: boolean;
            style: CSSStyleDeclaration;
            tabIndex: number;
            title: string;
            blur(): void;
            click(): void;
            contains(child: HTMLElement): boolean;
            dragDrop(): boolean;
            focus(): void;
            getElementsByClassName(classNames: string): NodeList;
            insertAdjacentElement(position: string, insertedElement: Element): Element;
            insertAdjacentHTML(where: string, html: string): void;
            insertAdjacentText(where: string, text: string): void;
            msGetInputContext(): MSInputMethodContext;
            scrollIntoView(top?: boolean): void;
            setActive(): void;
            addEventListener(type: "MSContentZoom", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGotPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSLostPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSManipulationStateChanged", listener: (ev: MSManipulationEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "touchcancel", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchend", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchmove", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchstart", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLElement: {
            prototype: HTMLElement;
            new(): HTMLElement;
        }
        
        interface HTMLEmbedElement extends HTMLElement, GetSVGDocument {
            /**
              * Sets or retrieves the height of the object.
              */
            height: string;
            hidden: any;
            /**
              * Gets or sets whether the DLNA PlayTo device is available.
              */
            msPlayToDisabled: boolean;
            /**
              * Gets or sets the path to the preferred media source. This enables the Play To target device to stream the media content, which can be DRM protected, from a different location, such as a cloud media server.
              */
            msPlayToPreferredSourceUri: string;
            /**
              * Gets or sets the primary DLNA PlayTo device.
              */
            msPlayToPrimary: boolean;
            /**
              * Gets the source associated with the media element for use by the PlayToManager.
              */
            msPlayToSource: any;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * Retrieves the palette used for the embedded document.
              */
            palette: string;
            /**
              * Retrieves the URL of the plug-in used to view an embedded document.
              */
            pluginspage: string;
            readyState: string;
            /**
              * Sets or retrieves a URL to be loaded by the object.
              */
            src: string;
            /**
              * Sets or retrieves the height and width units of the embed object.
              */
            units: string;
            /**
              * Sets or retrieves the width of the object.
              */
            width: string;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLEmbedElement: {
            prototype: HTMLEmbedElement;
            new(): HTMLEmbedElement;
        }
        
        interface HTMLFieldSetElement extends HTMLElement {
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            disabled: boolean;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /**
              * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
              */
            validationMessage: string;
            /**
              * Returns a  ValidityState object that represents the validity states of an element.
              */
            validity: ValidityState;
            /**
              * Returns whether an element will successfully validate based on forms validation rules and constraints.
              */
            willValidate: boolean;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
            /**
              * Sets a custom error message that is displayed when a form is submitted.
              * @param error Sets a custom error message that is displayed when a form is submitted.
              */
            setCustomValidity(error: string): void;
        }
        
        declare var HTMLFieldSetElement: {
            prototype: HTMLFieldSetElement;
            new(): HTMLFieldSetElement;
        }
        
        interface HTMLFontElement extends HTMLElement, DOML2DeprecatedColorProperty, DOML2DeprecatedSizeProperty {
            /**
              * Sets or retrieves the current typeface family.
              */
            face: string;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLFontElement: {
            prototype: HTMLFontElement;
            new(): HTMLFontElement;
        }
        
        interface HTMLFormElement extends HTMLElement {
            /**
              * Sets or retrieves a list of character encodings for input data that must be accepted by the server processing the form.
              */
            acceptCharset: string;
            /**
              * Sets or retrieves the URL to which the form content is sent for processing.
              */
            action: string;
            /**
              * Specifies whether autocomplete is applied to an editable text field.
              */
            autocomplete: string;
            /**
              * Retrieves a collection, in source order, of all controls in a given form.
              */
            elements: HTMLCollection;
            /**
              * Sets or retrieves the MIME encoding for the form.
              */
            encoding: string;
            /**
              * Sets or retrieves the encoding type for the form.
              */
            enctype: string;
            /**
              * Sets or retrieves the number of objects in a collection.
              */
            length: number;
            /**
              * Sets or retrieves how to send the form data to the server.
              */
            method: string;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * Designates a form that is not validated when submitted.
              */
            noValidate: boolean;
            /**
              * Sets or retrieves the window or frame at which to target content.
              */
            target: string;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
            /**
              * Retrieves a form object or an object from an elements collection.
              * @param name Variant of type Number or String that specifies the object or collection to retrieve. If this parameter is a Number, it is the zero-based index of the object. If this parameter is a string, all objects with matching name or id properties are retrieved, and a collection is returned if more than one match is made.
              * @param index Variant of type Number that specifies the zero-based index of the object to retrieve when a collection is returned.
              */
            item(name?: any, index?: any): any;
            /**
              * Retrieves a form object or an object from an elements collection.
              */
            namedItem(name: string): any;
            /**
              * Fires when the user resets a form.
              */
            reset(): void;
            /**
              * Fires when a FORM is about to be submitted.
              */
            submit(): void;
            [name: string]: any;
        }
        
        declare var HTMLFormElement: {
            prototype: HTMLFormElement;
            new(): HTMLFormElement;
        }
        
        interface HTMLFrameElement extends HTMLElement, GetSVGDocument {
            /**
              * Specifies the properties of a border drawn around an object.
              */
            border: string;
            /**
              * Sets or retrieves the border color of the object.
              */
            borderColor: any;
            /**
              * Retrieves the document object of the page or frame.
              */
            contentDocument: Document;
            /**
              * Retrieves the object of the specified.
              */
            contentWindow: Window;
            /**
              * Sets or retrieves whether to display a border for the frame.
              */
            frameBorder: string;
            /**
              * Sets or retrieves the amount of additional space between the frames.
              */
            frameSpacing: any;
            /**
              * Sets or retrieves the height of the object.
              */
            height: string | number;
            /**
              * Sets or retrieves a URI to a long description of the object.
              */
            longDesc: string;
            /**
              * Sets or retrieves the top and bottom margin heights before displaying the text in a frame.
              */
            marginHeight: string;
            /**
              * Sets or retrieves the left and right margin widths before displaying the text in a frame.
              */
            marginWidth: string;
            /**
              * Sets or retrieves the frame name.
              */
            name: string;
            /**
              * Sets or retrieves whether the user can resize the frame.
              */
            noResize: boolean;
            /**
              * Raised when the object has been completely received from the server.
              */
            onload: (ev: Event) => any;
            /**
              * Sets or retrieves whether the frame can be scrolled.
              */
            scrolling: string;
            /**
              * Sets the value indicating whether the source file of a frame or iframe has specific security restrictions applied.
              */
            security: any;
            /**
              * Sets or retrieves a URL to be loaded by the object.
              */
            src: string;
            /**
              * Sets or retrieves the width of the object.
              */
            width: string | number;
            addEventListener(type: "MSContentZoom", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGotPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSLostPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSManipulationStateChanged", listener: (ev: MSManipulationEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "touchcancel", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchend", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchmove", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchstart", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLFrameElement: {
            prototype: HTMLFrameElement;
            new(): HTMLFrameElement;
        }
        
        interface HTMLFrameSetElement extends HTMLElement {
            border: string;
            /**
              * Sets or retrieves the border color of the object.
              */
            borderColor: any;
            /**
              * Sets or retrieves the frame widths of the object.
              */
            cols: string;
            /**
              * Sets or retrieves whether to display a border for the frame.
              */
            frameBorder: string;
            /**
              * Sets or retrieves the amount of additional space between the frames.
              */
            frameSpacing: any;
            name: string;
            onafterprint: (ev: Event) => any;
            onbeforeprint: (ev: Event) => any;
            onbeforeunload: (ev: BeforeUnloadEvent) => any;
            /**
              * Fires when the object loses the input focus.
              */
            onblur: (ev: FocusEvent) => any;
            onerror: (ev: Event) => any;
            /**
              * Fires when the object receives focus.
              */
            onfocus: (ev: FocusEvent) => any;
            onhashchange: (ev: HashChangeEvent) => any;
            onload: (ev: Event) => any;
            onmessage: (ev: MessageEvent) => any;
            onoffline: (ev: Event) => any;
            ononline: (ev: Event) => any;
            onorientationchange: (ev: Event) => any;
            onpagehide: (ev: PageTransitionEvent) => any;
            onpageshow: (ev: PageTransitionEvent) => any;
            onresize: (ev: UIEvent) => any;
            onstorage: (ev: StorageEvent) => any;
            onunload: (ev: Event) => any;
            /**
              * Sets or retrieves the frame heights of the object.
              */
            rows: string;
            addEventListener(type: "MSContentZoom", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGotPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSLostPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSManipulationStateChanged", listener: (ev: MSManipulationEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeprint", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeunload", listener: (ev: BeforeUnloadEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "hashchange", listener: (ev: HashChangeEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "offline", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "online", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "orientationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pagehide", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pageshow", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "storage", listener: (ev: StorageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "touchcancel", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchend", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchmove", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchstart", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "unload", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLFrameSetElement: {
            prototype: HTMLFrameSetElement;
            new(): HTMLFrameSetElement;
        }
        
        interface HTMLHRElement extends HTMLElement, DOML2DeprecatedColorProperty, DOML2DeprecatedSizeProperty {
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            /**
              * Sets or retrieves whether the horizontal rule is drawn with 3-D shading.
              */
            noShade: boolean;
            /**
              * Sets or retrieves the width of the object.
              */
            width: number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLHRElement: {
            prototype: HTMLHRElement;
            new(): HTMLHRElement;
        }
        
        interface HTMLHeadElement extends HTMLElement {
            profile: string;
        }
        
        declare var HTMLHeadElement: {
            prototype: HTMLHeadElement;
            new(): HTMLHeadElement;
        }
        
        interface HTMLHeadingElement extends HTMLElement {
            /**
              * Sets or retrieves a value that indicates the table alignment.
              */
            align: string;
            clear: string;
        }
        
        declare var HTMLHeadingElement: {
            prototype: HTMLHeadingElement;
            new(): HTMLHeadingElement;
        }
        
        interface HTMLHtmlElement extends HTMLElement {
            /**
              * Sets or retrieves the DTD version that governs the current document.
              */
            version: string;
        }
        
        declare var HTMLHtmlElement: {
            prototype: HTMLHtmlElement;
            new(): HTMLHtmlElement;
        }
        
        interface HTMLIFrameElement extends HTMLElement, GetSVGDocument {
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            allowFullscreen: boolean;
            /**
              * Specifies the properties of a border drawn around an object.
              */
            border: string;
            /**
              * Retrieves the document object of the page or frame.
              */
            contentDocument: Document;
            /**
              * Retrieves the object of the specified.
              */
            contentWindow: Window;
            /**
              * Sets or retrieves whether to display a border for the frame.
              */
            frameBorder: string;
            /**
              * Sets or retrieves the amount of additional space between the frames.
              */
            frameSpacing: any;
            /**
              * Sets or retrieves the height of the object.
              */
            height: string;
            /**
              * Sets or retrieves the horizontal margin for the object.
              */
            hspace: number;
            /**
              * Sets or retrieves a URI to a long description of the object.
              */
            longDesc: string;
            /**
              * Sets or retrieves the top and bottom margin heights before displaying the text in a frame.
              */
            marginHeight: string;
            /**
              * Sets or retrieves the left and right margin widths before displaying the text in a frame.
              */
            marginWidth: string;
            /**
              * Sets or retrieves the frame name.
              */
            name: string;
            /**
              * Sets or retrieves whether the user can resize the frame.
              */
            noResize: boolean;
            /**
              * Raised when the object has been completely received from the server.
              */
            onload: (ev: Event) => any;
            sandbox: DOMSettableTokenList;
            /**
              * Sets or retrieves whether the frame can be scrolled.
              */
            scrolling: string;
            /**
              * Sets the value indicating whether the source file of a frame or iframe has specific security restrictions applied.
              */
            security: any;
            /**
              * Sets or retrieves a URL to be loaded by the object.
              */
            src: string;
            /**
              * Sets or retrieves the vertical margin for the object.
              */
            vspace: number;
            /**
              * Sets or retrieves the width of the object.
              */
            width: string;
            addEventListener(type: "MSContentZoom", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGotPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSLostPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSManipulationStateChanged", listener: (ev: MSManipulationEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "touchcancel", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchend", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchmove", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchstart", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLIFrameElement: {
            prototype: HTMLIFrameElement;
            new(): HTMLIFrameElement;
        }
        
        interface HTMLImageElement extends HTMLElement {
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            /**
              * Sets or retrieves a text alternative to the graphic.
              */
            alt: string;
            /**
              * Specifies the properties of a border drawn around an object.
              */
            border: string;
            /**
              * Retrieves whether the object is fully loaded.
              */
            complete: boolean;
            crossOrigin: string;
            currentSrc: string;
            /**
              * Sets or retrieves the height of the object.
              */
            height: number;
            /**
              * Sets or retrieves the width of the border to draw around the object.
              */
            hspace: number;
            /**
              * Sets or retrieves whether the image is a server-side image map.
              */
            isMap: boolean;
            /**
              * Sets or retrieves a Uniform Resource Identifier (URI) to a long description of the object.
              */
            longDesc: string;
            /**
              * Gets or sets whether the DLNA PlayTo device is available.
              */
            msPlayToDisabled: boolean;
            msPlayToPreferredSourceUri: string;
            /**
              * Gets or sets the primary DLNA PlayTo device.
              */
            msPlayToPrimary: boolean;
            /**
              * Gets the source associated with the media element for use by the PlayToManager.
              */
            msPlayToSource: any;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * The original height of the image resource before sizing.
              */
            naturalHeight: number;
            /**
              * The original width of the image resource before sizing.
              */
            naturalWidth: number;
            /**
              * The address or URL of the a media resource that is to be considered.
              */
            src: string;
            srcset: string;
            /**
              * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.
              */
            useMap: string;
            /**
              * Sets or retrieves the vertical margin for the object.
              */
            vspace: number;
            /**
              * Sets or retrieves the width of the object.
              */
            width: number;
            x: number;
            y: number;
            msGetAsCastingSource(): any;
        }
        
        declare var HTMLImageElement: {
            prototype: HTMLImageElement;
            new(): HTMLImageElement;
            create(): HTMLImageElement;
        }
        
        interface HTMLInputElement extends HTMLElement {
            /**
              * Sets or retrieves a comma-separated list of content types.
              */
            accept: string;
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            /**
              * Sets or retrieves a text alternative to the graphic.
              */
            alt: string;
            /**
              * Specifies whether autocomplete is applied to an editable text field.
              */
            autocomplete: string;
            /**
              * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.
              */
            autofocus: boolean;
            /**
              * Sets or retrieves the width of the border to draw around the object.
              */
            border: string;
            /**
              * Sets or retrieves the state of the check box or radio button.
              */
            checked: boolean;
            /**
              * Retrieves whether the object is fully loaded.
              */
            complete: boolean;
            /**
              * Sets or retrieves the state of the check box or radio button.
              */
            defaultChecked: boolean;
            /**
              * Sets or retrieves the initial contents of the object.
              */
            defaultValue: string;
            disabled: boolean;
            /**
              * Returns a FileList object on a file type input object.
              */
            files: FileList;
            /**
              * Retrieves a reference to the form that the object is embedded in. 
              */
            form: HTMLFormElement;
            /**
              * Overrides the action attribute (where the data on a form is sent) on the parent form element.
              */
            formAction: string;
            /**
              * Used to override the encoding (formEnctype attribute) specified on the form element.
              */
            formEnctype: string;
            /**
              * Overrides the submit method attribute previously specified on a form element.
              */
            formMethod: string;
            /**
              * Overrides any validation or required attributes on a form or form elements to allow it to be submitted without validation. This can be used to create a "save draft"-type submit option.
              */
            formNoValidate: string;
            /**
              * Overrides the target attribute on a form element.
              */
            formTarget: string;
            /**
              * Sets or retrieves the height of the object.
              */
            height: string;
            /**
              * Sets or retrieves the width of the border to draw around the object.
              */
            hspace: number;
            indeterminate: boolean;
            /**
              * Specifies the ID of a pre-defined datalist of options for an input element.
              */
            list: HTMLElement;
            /**
              * Defines the maximum acceptable value for an input element with type="number".When used with the min and step attributes, lets you control the range and increment (such as only even numbers) that the user can enter into an input field.
              */
            max: string;
            /**
              * Sets or retrieves the maximum number of characters that the user can enter in a text control.
              */
            maxLength: number;
            /**
              * Defines the minimum acceptable value for an input element with type="number". When used with the max and step attributes, lets you control the range and increment (such as even numbers only) that the user can enter into an input field.
              */
            min: string;
            /**
              * Sets or retrieves the Boolean value indicating whether multiple items can be selected from a list.
              */
            multiple: boolean;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * Gets or sets a string containing a regular expression that the user's input must match.
              */
            pattern: string;
            /**
              * Gets or sets a text string that is displayed in an input field as a hint or prompt to users as the format or type of information they need to enter.The text appears in an input field until the user puts focus on the field.
              */
            placeholder: string;
            readOnly: boolean;
            /**
              * When present, marks an element that can't be submitted without a value.
              */
            required: boolean;
            /**
              * Gets or sets the end position or offset of a text selection.
              */
            selectionEnd: number;
            /**
              * Gets or sets the starting position or offset of a text selection.
              */
            selectionStart: number;
            size: number;
            /**
              * The address or URL of the a media resource that is to be considered.
              */
            src: string;
            status: boolean;
            /**
              * Defines an increment or jump between values that you want to allow the user to enter. When used with the max and min attributes, lets you control the range and increment (for example, allow only even numbers) that the user can enter into an input field.
              */
            step: string;
            /**
              * Returns the content type of the object.
              */
            type: string;
            /**
              * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.
              */
            useMap: string;
            /**
              * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
              */
            validationMessage: string;
            /**
              * Returns a  ValidityState object that represents the validity states of an element.
              */
            validity: ValidityState;
            /**
              * Returns the value of the data at the cursor's current position.
              */
            value: string;
            valueAsDate: Date;
            /**
              * Returns the input field value as a number.
              */
            valueAsNumber: number;
            /**
              * Sets or retrieves the vertical margin for the object.
              */
            vspace: number;
            /**
              * Sets or retrieves the width of the object.
              */
            width: string;
            /**
              * Returns whether an element will successfully validate based on forms validation rules and constraints.
              */
            willValidate: boolean;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
            /**
              * Creates a TextRange object for the element.
              */
            createTextRange(): TextRange;
            /**
              * Makes the selection equal to the current object.
              */
            select(): void;
            /**
              * Sets a custom error message that is displayed when a form is submitted.
              * @param error Sets a custom error message that is displayed when a form is submitted.
              */
            setCustomValidity(error: string): void;
            /**
              * Sets the start and end positions of a selection in a text field.
              * @param start The offset into the text field for the start of the selection.
              * @param end The offset into the text field for the end of the selection.
              */
            setSelectionRange(start: number, end: number): void;
            /**
              * Decrements a range input control's value by the value given by the Step attribute. If the optional parameter is used, it will decrement the input control's step value multiplied by the parameter's value.
              * @param n Value to decrement the value by.
              */
            stepDown(n?: number): void;
            /**
              * Increments a range input control's value by the value given by the Step attribute. If the optional parameter is used, will increment the input control's value by that value.
              * @param n Value to increment the value by.
              */
            stepUp(n?: number): void;
        }
        
        declare var HTMLInputElement: {
            prototype: HTMLInputElement;
            new(): HTMLInputElement;
        }
        
        interface HTMLIsIndexElement extends HTMLElement {
            /**
              * Sets or retrieves the URL to which the form content is sent for processing.
              */
            action: string;
            /**
              * Retrieves a reference to the form that the object is embedded in. 
              */
            form: HTMLFormElement;
            prompt: string;
        }
        
        declare var HTMLIsIndexElement: {
            prototype: HTMLIsIndexElement;
            new(): HTMLIsIndexElement;
        }
        
        interface HTMLLIElement extends HTMLElement {
            type: string;
            /**
              * Sets or retrieves the value of a list item.
              */
            value: number;
        }
        
        declare var HTMLLIElement: {
            prototype: HTMLLIElement;
            new(): HTMLLIElement;
        }
        
        interface HTMLLabelElement extends HTMLElement {
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /**
              * Sets or retrieves the object to which the given label object is assigned.
              */
            htmlFor: string;
        }
        
        declare var HTMLLabelElement: {
            prototype: HTMLLabelElement;
            new(): HTMLLabelElement;
        }
        
        interface HTMLLegendElement extends HTMLElement {
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            align: string;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
        }
        
        declare var HTMLLegendElement: {
            prototype: HTMLLegendElement;
            new(): HTMLLegendElement;
        }
        
        interface HTMLLinkElement extends HTMLElement, LinkStyle {
            /**
              * Sets or retrieves the character set used to encode the object.
              */
            charset: string;
            disabled: boolean;
            /**
              * Sets or retrieves a destination URL or an anchor point.
              */
            href: string;
            /**
              * Sets or retrieves the language code of the object.
              */
            hreflang: string;
            /**
              * Sets or retrieves the media type.
              */
            media: string;
            /**
              * Sets or retrieves the relationship between the object and the destination of the link.
              */
            rel: string;
            /**
              * Sets or retrieves the relationship between the object and the destination of the link.
              */
            rev: string;
            /**
              * Sets or retrieves the window or frame at which to target content.
              */
            target: string;
            /**
              * Sets or retrieves the MIME type of the object.
              */
            type: string;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLLinkElement: {
            prototype: HTMLLinkElement;
            new(): HTMLLinkElement;
        }
        
        interface HTMLMapElement extends HTMLElement {
            /**
              * Retrieves a collection of the area objects defined for the given map object.
              */
            areas: HTMLAreasCollection;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
        }
        
        declare var HTMLMapElement: {
            prototype: HTMLMapElement;
            new(): HTMLMapElement;
        }
        
        interface HTMLMarqueeElement extends HTMLElement {
            behavior: string;
            bgColor: any;
            direction: string;
            height: string;
            hspace: number;
            loop: number;
            onbounce: (ev: Event) => any;
            onfinish: (ev: Event) => any;
            onstart: (ev: Event) => any;
            scrollAmount: number;
            scrollDelay: number;
            trueSpeed: boolean;
            vspace: number;
            width: string;
            start(): void;
            stop(): void;
            addEventListener(type: "MSContentZoom", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGotPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSLostPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSManipulationStateChanged", listener: (ev: MSManipulationEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "bounce", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "finish", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "start", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "touchcancel", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchend", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchmove", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchstart", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLMarqueeElement: {
            prototype: HTMLMarqueeElement;
            new(): HTMLMarqueeElement;
        }
        
        interface HTMLMediaElement extends HTMLElement {
            /**
              * Returns an AudioTrackList object with the audio tracks for a given video element.
              */
            audioTracks: AudioTrackList;
            /**
              * Gets or sets a value that indicates whether to start playing the media automatically.
              */
            autoplay: boolean;
            /**
              * Gets a collection of buffered time ranges.
              */
            buffered: TimeRanges;
            /**
              * Gets or sets a flag that indicates whether the client provides a set of controls for the media (in case the developer does not include controls for the player).
              */
            controls: boolean;
            /**
              * Gets the address or URL of the current media resource that is selected by IHTMLMediaElement.
              */
            currentSrc: string;
            /**
              * Gets or sets the current playback position, in seconds.
              */
            currentTime: number;
            defaultMuted: boolean;
            /**
              * Gets or sets the default playback rate when the user is not using fast forward or reverse for a video or audio resource.
              */
            defaultPlaybackRate: number;
            /**
              * Returns the duration in seconds of the current media resource. A NaN value is returned if duration is not available, or Infinity if the media resource is streaming.
              */
            duration: number;
            /**
              * Gets information about whether the playback has ended or not.
              */
            ended: boolean;
            /**
              * Returns an object representing the current error state of the audio or video element.
              */
            error: MediaError;
            /**
              * Gets or sets a flag to specify whether playback should restart after it completes.
              */
            loop: boolean;
            /**
              * Specifies the purpose of the audio or video media, such as background audio or alerts.
              */
            msAudioCategory: string;
            /**
              * Specifies the output device id that the audio will be sent to.
              */
            msAudioDeviceType: string;
            msGraphicsTrustStatus: MSGraphicsTrust;
            /**
              * Gets the MSMediaKeys object, which is used for decrypting media data, that is associated with this media element.
              */
            msKeys: MSMediaKeys;
            /**
              * Gets or sets whether the DLNA PlayTo device is available.
              */
            msPlayToDisabled: boolean;
            /**
              * Gets or sets the path to the preferred media source. This enables the Play To target device to stream the media content, which can be DRM protected, from a different location, such as a cloud media server.
              */
            msPlayToPreferredSourceUri: string;
            /**
              * Gets or sets the primary DLNA PlayTo device.
              */
            msPlayToPrimary: boolean;
            /**
              * Gets the source associated with the media element for use by the PlayToManager.
              */
            msPlayToSource: any;
            /**
              * Specifies whether or not to enable low-latency playback on the media element.
              */
            msRealTime: boolean;
            /**
              * Gets or sets a flag that indicates whether the audio (either audio or the audio track on video media) is muted.
              */
            muted: boolean;
            /**
              * Gets the current network activity for the element.
              */
            networkState: number;
            onmsneedkey: (ev: MSMediaKeyNeededEvent) => any;
            /**
              * Gets a flag that specifies whether playback is paused.
              */
            paused: boolean;
            /**
              * Gets or sets the current rate of speed for the media resource to play. This speed is expressed as a multiple of the normal speed of the media resource.
              */
            playbackRate: number;
            /**
              * Gets TimeRanges for the current media resource that has been played.
              */
            played: TimeRanges;
            /**
              * Gets or sets the current playback position, in seconds.
              */
            preload: string;
            readyState: any;
            /**
              * Returns a TimeRanges object that represents the ranges of the current media resource that can be seeked.
              */
            seekable: TimeRanges;
            /**
              * Gets a flag that indicates whether the the client is currently moving to a new playback position in the media resource.
              */
            seeking: boolean;
            /**
              * The address or URL of the a media resource that is to be considered.
              */
            src: string;
            textTracks: TextTrackList;
            videoTracks: VideoTrackList;
            /**
              * Gets or sets the volume level for audio portions of the media element.
              */
            volume: number;
            addTextTrack(kind: string, label?: string, language?: string): TextTrack;
            /**
              * Returns a string that specifies whether the client can play a given media resource type.
              */
            canPlayType(type: string): string;
            /**
              * Fires immediately after the client loads the object.
              */
            load(): void;
            /**
              * Clears all effects from the media pipeline.
              */
            msClearEffects(): void;
            msGetAsCastingSource(): any;
            /**
              * Inserts the specified audio effect into media pipeline.
              */
            msInsertAudioEffect(activatableClassId: string, effectRequired: boolean, config?: any): void;
            msSetMediaKeys(mediaKeys: MSMediaKeys): void;
            /**
              * Specifies the media protection manager for a given media pipeline.
              */
            msSetMediaProtectionManager(mediaProtectionManager?: any): void;
            /**
              * Pauses the current playback and sets paused to TRUE. This can be used to test whether the media is playing or paused. You can also use the pause or play events to tell whether the media is playing or not.
              */
            pause(): void;
            /**
              * Loads and starts playback of a media resource.
              */
            play(): void;
            HAVE_CURRENT_DATA: number;
            HAVE_ENOUGH_DATA: number;
            HAVE_FUTURE_DATA: number;
            HAVE_METADATA: number;
            HAVE_NOTHING: number;
            NETWORK_EMPTY: number;
            NETWORK_IDLE: number;
            NETWORK_LOADING: number;
            NETWORK_NO_SOURCE: number;
            addEventListener(type: "MSContentZoom", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGotPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSLostPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSManipulationStateChanged", listener: (ev: MSManipulationEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "msneedkey", listener: (ev: MSMediaKeyNeededEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "touchcancel", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchend", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchmove", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchstart", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLMediaElement: {
            prototype: HTMLMediaElement;
            new(): HTMLMediaElement;
            HAVE_CURRENT_DATA: number;
            HAVE_ENOUGH_DATA: number;
            HAVE_FUTURE_DATA: number;
            HAVE_METADATA: number;
            HAVE_NOTHING: number;
            NETWORK_EMPTY: number;
            NETWORK_IDLE: number;
            NETWORK_LOADING: number;
            NETWORK_NO_SOURCE: number;
        }
        
        interface HTMLMenuElement extends HTMLElement {
            compact: boolean;
            type: string;
        }
        
        declare var HTMLMenuElement: {
            prototype: HTMLMenuElement;
            new(): HTMLMenuElement;
        }
        
        interface HTMLMetaElement extends HTMLElement {
            /**
              * Sets or retrieves the character set used to encode the object.
              */
            charset: string;
            /**
              * Gets or sets meta-information to associate with httpEquiv or name.
              */
            content: string;
            /**
              * Gets or sets information used to bind the value of a content attribute of a meta element to an HTTP response header.
              */
            httpEquiv: string;
            /**
              * Sets or retrieves the value specified in the content attribute of the meta object.
              */
            name: string;
            /**
              * Sets or retrieves a scheme to be used in interpreting the value of a property specified for the object.
              */
            scheme: string;
            /**
              * Sets or retrieves the URL property that will be loaded after the specified time has elapsed. 
              */
            url: string;
        }
        
        declare var HTMLMetaElement: {
            prototype: HTMLMetaElement;
            new(): HTMLMetaElement;
        }
        
        interface HTMLModElement extends HTMLElement {
            /**
              * Sets or retrieves reference information about the object.
              */
            cite: string;
            /**
              * Sets or retrieves the date and time of a modification to the object.
              */
            dateTime: string;
        }
        
        declare var HTMLModElement: {
            prototype: HTMLModElement;
            new(): HTMLModElement;
        }
        
        interface HTMLNextIdElement extends HTMLElement {
            n: string;
        }
        
        declare var HTMLNextIdElement: {
            prototype: HTMLNextIdElement;
            new(): HTMLNextIdElement;
        }
        
        interface HTMLOListElement extends HTMLElement {
            compact: boolean;
            /**
              * The starting number.
              */
            start: number;
            type: string;
        }
        
        declare var HTMLOListElement: {
            prototype: HTMLOListElement;
            new(): HTMLOListElement;
        }
        
        interface HTMLObjectElement extends HTMLElement, GetSVGDocument {
            /**
              * Retrieves a string of the URL where the object tag can be found. This is often the href of the document that the object is in, or the value set by a base element.
              */
            BaseHref: string;
            align: string;
            /**
              * Sets or retrieves a text alternative to the graphic.
              */
            alt: string;
            /**
              * Gets or sets the optional alternative HTML script to execute if the object fails to load.
              */
            altHtml: string;
            /**
              * Sets or retrieves a character string that can be used to implement your own archive functionality for the object.
              */
            archive: string;
            border: string;
            /**
              * Sets or retrieves the URL of the file containing the compiled Java class.
              */
            code: string;
            /**
              * Sets or retrieves the URL of the component.
              */
            codeBase: string;
            /**
              * Sets or retrieves the Internet media type for the code associated with the object.
              */
            codeType: string;
            /**
              * Retrieves the document object of the page or frame.
              */
            contentDocument: Document;
            /**
              * Sets or retrieves the URL that references the data of the object.
              */
            data: string;
            declare: boolean;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /**
              * Sets or retrieves the height of the object.
              */
            height: string;
            hspace: number;
            /**
              * Gets or sets whether the DLNA PlayTo device is available.
              */
            msPlayToDisabled: boolean;
            /**
              * Gets or sets the path to the preferred media source. This enables the Play To target device to stream the media content, which can be DRM protected, from a different location, such as a cloud media server.
              */
            msPlayToPreferredSourceUri: string;
            /**
              * Gets or sets the primary DLNA PlayTo device.
              */
            msPlayToPrimary: boolean;
            /**
              * Gets the source associated with the media element for use by the PlayToManager.
              */
            msPlayToSource: any;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * Retrieves the contained object.
              */
            object: any;
            readyState: number;
            /**
              * Sets or retrieves a message to be displayed while an object is loading.
              */
            standby: string;
            /**
              * Sets or retrieves the MIME type of the object.
              */
            type: string;
            /**
              * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.
              */
            useMap: string;
            /**
              * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
              */
            validationMessage: string;
            /**
              * Returns a  ValidityState object that represents the validity states of an element.
              */
            validity: ValidityState;
            vspace: number;
            /**
              * Sets or retrieves the width of the object.
              */
            width: string;
            /**
              * Returns whether an element will successfully validate based on forms validation rules and constraints.
              */
            willValidate: boolean;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
            /**
              * Sets a custom error message that is displayed when a form is submitted.
              * @param error Sets a custom error message that is displayed when a form is submitted.
              */
            setCustomValidity(error: string): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLObjectElement: {
            prototype: HTMLObjectElement;
            new(): HTMLObjectElement;
        }
        
        interface HTMLOptGroupElement extends HTMLElement {
            /**
              * Sets or retrieves the status of an option.
              */
            defaultSelected: boolean;
            disabled: boolean;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /**
              * Sets or retrieves the ordinal position of an option in a list box.
              */
            index: number;
            /**
              * Sets or retrieves a value that you can use to implement your own label functionality for the object.
              */
            label: string;
            /**
              * Sets or retrieves whether the option in the list box is the default item.
              */
            selected: boolean;
            /**
              * Sets or retrieves the text string specified by the option tag.
              */
            text: string;
            /**
              * Sets or retrieves the value which is returned to the server when the form control is submitted.
              */
            value: string;
        }
        
        declare var HTMLOptGroupElement: {
            prototype: HTMLOptGroupElement;
            new(): HTMLOptGroupElement;
        }
        
        interface HTMLOptionElement extends HTMLElement {
            /**
              * Sets or retrieves the status of an option.
              */
            defaultSelected: boolean;
            disabled: boolean;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /**
              * Sets or retrieves the ordinal position of an option in a list box.
              */
            index: number;
            /**
              * Sets or retrieves a value that you can use to implement your own label functionality for the object.
              */
            label: string;
            /**
              * Sets or retrieves whether the option in the list box is the default item.
              */
            selected: boolean;
            /**
              * Sets or retrieves the text string specified by the option tag.
              */
            text: string;
            /**
              * Sets or retrieves the value which is returned to the server when the form control is submitted.
              */
            value: string;
        }
        
        declare var HTMLOptionElement: {
            prototype: HTMLOptionElement;
            new(): HTMLOptionElement;
            create(): HTMLOptionElement;
        }
        
        interface HTMLParagraphElement extends HTMLElement {
            /**
              * Sets or retrieves how the object is aligned with adjacent text. 
              */
            align: string;
            clear: string;
        }
        
        declare var HTMLParagraphElement: {
            prototype: HTMLParagraphElement;
            new(): HTMLParagraphElement;
        }
        
        interface HTMLParamElement extends HTMLElement {
            /**
              * Sets or retrieves the name of an input parameter for an element.
              */
            name: string;
            /**
              * Sets or retrieves the content type of the resource designated by the value attribute.
              */
            type: string;
            /**
              * Sets or retrieves the value of an input parameter for an element.
              */
            value: string;
            /**
              * Sets or retrieves the data type of the value attribute.
              */
            valueType: string;
        }
        
        declare var HTMLParamElement: {
            prototype: HTMLParamElement;
            new(): HTMLParamElement;
        }
        
        interface HTMLPhraseElement extends HTMLElement {
            /**
              * Sets or retrieves reference information about the object.
              */
            cite: string;
            /**
              * Sets or retrieves the date and time of a modification to the object.
              */
            dateTime: string;
        }
        
        declare var HTMLPhraseElement: {
            prototype: HTMLPhraseElement;
            new(): HTMLPhraseElement;
        }
        
        interface HTMLPreElement extends HTMLElement {
            /**
              * Indicates a citation by rendering text in italic type.
              */
            cite: string;
            clear: string;
            /**
              * Sets or gets a value that you can use to implement your own width functionality for the object.
              */
            width: number;
        }
        
        declare var HTMLPreElement: {
            prototype: HTMLPreElement;
            new(): HTMLPreElement;
        }
        
        interface HTMLProgressElement extends HTMLElement {
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /**
              * Defines the maximum, or "done" value for a progress element.
              */
            max: number;
            /**
              * Returns the quotient of value/max when the value attribute is set (determinate progress bar), or -1 when the value attribute is missing (indeterminate progress bar).
              */
            position: number;
            /**
              * Sets or gets the current value of a progress element. The value must be a non-negative number between 0 and the max value.
              */
            value: number;
        }
        
        declare var HTMLProgressElement: {
            prototype: HTMLProgressElement;
            new(): HTMLProgressElement;
        }
        
        interface HTMLQuoteElement extends HTMLElement {
            /**
              * Sets or retrieves reference information about the object.
              */
            cite: string;
            /**
              * Sets or retrieves the date and time of a modification to the object.
              */
            dateTime: string;
        }
        
        declare var HTMLQuoteElement: {
            prototype: HTMLQuoteElement;
            new(): HTMLQuoteElement;
        }
        
        interface HTMLScriptElement extends HTMLElement {
            async: boolean;
            /**
              * Sets or retrieves the character set used to encode the object.
              */
            charset: string;
            /**
              * Sets or retrieves the status of the script.
              */
            defer: boolean;
            /**
              * Sets or retrieves the event for which the script is written. 
              */
            event: string;
            /** 
              * Sets or retrieves the object that is bound to the event script.
              */
            htmlFor: string;
            /**
              * Retrieves the URL to an external file that contains the source code or data.
              */
            src: string;
            /**
              * Retrieves or sets the text of the object as a string. 
              */
            text: string;
            /**
              * Sets or retrieves the MIME type for the associated scripting engine.
              */
            type: string;
        }
        
        declare var HTMLScriptElement: {
            prototype: HTMLScriptElement;
            new(): HTMLScriptElement;
        }
        
        interface HTMLSelectElement extends HTMLElement {
            /**
              * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.
              */
            autofocus: boolean;
            disabled: boolean;
            /**
              * Retrieves a reference to the form that the object is embedded in. 
              */
            form: HTMLFormElement;
            /**
              * Sets or retrieves the number of objects in a collection.
              */
            length: number;
            /**
              * Sets or retrieves the Boolean value indicating whether multiple items can be selected from a list.
              */
            multiple: boolean;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            options: HTMLSelectElement;
            /**
              * When present, marks an element that can't be submitted without a value.
              */
            required: boolean;
            /**
              * Sets or retrieves the index of the selected option in a select object.
              */
            selectedIndex: number;
            /**
              * Sets or retrieves the number of rows in the list box. 
              */
            size: number;
            /**
              * Retrieves the type of select control based on the value of the MULTIPLE attribute.
              */
            type: string;
            /**
              * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
              */
            validationMessage: string;
            /**
              * Returns a  ValidityState object that represents the validity states of an element.
              */
            validity: ValidityState;
            /**
              * Sets or retrieves the value which is returned to the server when the form control is submitted.
              */
            value: string;
            /**
              * Returns whether an element will successfully validate based on forms validation rules and constraints.
              */
            willValidate: boolean;
            /**
              * Adds an element to the areas, controlRange, or options collection.
              * @param element Variant of type Number that specifies the index position in the collection where the element is placed. If no value is given, the method places the element at the end of the collection.
              * @param before Variant of type Object that specifies an element to insert before, or null to append the object to the collection. 
              */
            add(element: HTMLElement, before?: HTMLElement): void;
            add(element: HTMLElement, before?: number): void;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
            /**
              * Retrieves a select object or an object from an options collection.
              * @param name Variant of type Number or String that specifies the object or collection to retrieve. If this parameter is an integer, it is the zero-based index of the object. If this parameter is a string, all objects with matching name or id properties are retrieved, and a collection is returned if more than one match is made.
              * @param index Variant of type Number that specifies the zero-based index of the object to retrieve when a collection is returned.
              */
            item(name?: any, index?: any): any;
            /**
              * Retrieves a select object or an object from an options collection.
              * @param namedItem A String that specifies the name or id property of the object to retrieve. A collection is returned if more than one match is made.
              */
            namedItem(name: string): any;
            /**
              * Removes an element from the collection.
              * @param index Number that specifies the zero-based index of the element to remove from the collection.
              */
            remove(index?: number): void;
            /**
              * Sets a custom error message that is displayed when a form is submitted.
              * @param error Sets a custom error message that is displayed when a form is submitted.
              */
            setCustomValidity(error: string): void;
            [name: string]: any;
        }
        
        declare var HTMLSelectElement: {
            prototype: HTMLSelectElement;
            new(): HTMLSelectElement;
        }
        
        interface HTMLSourceElement extends HTMLElement {
            /**
              * Gets or sets the intended media type of the media source.
             */
            media: string;
            msKeySystem: string;
            /**
              * The address or URL of the a media resource that is to be considered.
              */
            src: string;
            /**
             * Gets or sets the MIME type of a media resource.
             */
            type: string;
        }
        
        declare var HTMLSourceElement: {
            prototype: HTMLSourceElement;
            new(): HTMLSourceElement;
        }
        
        interface HTMLSpanElement extends HTMLElement {
        }
        
        declare var HTMLSpanElement: {
            prototype: HTMLSpanElement;
            new(): HTMLSpanElement;
        }
        
        interface HTMLStyleElement extends HTMLElement, LinkStyle {
            /**
              * Sets or retrieves the media type.
              */
            media: string;
            /**
              * Retrieves the CSS language in which the style sheet is written.
              */
            type: string;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLStyleElement: {
            prototype: HTMLStyleElement;
            new(): HTMLStyleElement;
        }
        
        interface HTMLTableCaptionElement extends HTMLElement {
            /**
              * Sets or retrieves the alignment of the caption or legend.
              */
            align: string;
            /**
              * Sets or retrieves whether the caption appears at the top or bottom of the table.
              */
            vAlign: string;
        }
        
        declare var HTMLTableCaptionElement: {
            prototype: HTMLTableCaptionElement;
            new(): HTMLTableCaptionElement;
        }
        
        interface HTMLTableCellElement extends HTMLElement, HTMLTableAlignment {
            /**
              * Sets or retrieves abbreviated text for the object.
              */
            abbr: string;
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            /**
              * Sets or retrieves a comma-delimited list of conceptual categories associated with the object.
              */
            axis: string;
            bgColor: any;
            /**
              * Retrieves the position of the object in the cells collection of a row.
              */
            cellIndex: number;
            /**
              * Sets or retrieves the number columns in the table that the object should span.
              */
            colSpan: number;
            /**
              * Sets or retrieves a list of header cells that provide information for the object.
              */
            headers: string;
            /**
              * Sets or retrieves the height of the object.
              */
            height: any;
            /**
              * Sets or retrieves whether the browser automatically performs wordwrap.
              */
            noWrap: boolean;
            /**
              * Sets or retrieves how many rows in a table the cell should span.
              */
            rowSpan: number;
            /**
              * Sets or retrieves the group of cells in a table to which the object's information applies.
              */
            scope: string;
            /**
              * Sets or retrieves the width of the object.
              */
            width: string;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLTableCellElement: {
            prototype: HTMLTableCellElement;
            new(): HTMLTableCellElement;
        }
        
        interface HTMLTableColElement extends HTMLElement, HTMLTableAlignment {
            /**
              * Sets or retrieves the alignment of the object relative to the display or table.
              */
            align: string;
            /**
              * Sets or retrieves the number of columns in the group.
              */
            span: number;
            /**
              * Sets or retrieves the width of the object.
              */
            width: any;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLTableColElement: {
            prototype: HTMLTableColElement;
            new(): HTMLTableColElement;
        }
        
        interface HTMLTableDataCellElement extends HTMLTableCellElement {
        }
        
        declare var HTMLTableDataCellElement: {
            prototype: HTMLTableDataCellElement;
            new(): HTMLTableDataCellElement;
        }
        
        interface HTMLTableElement extends HTMLElement {
            /**
              * Sets or retrieves a value that indicates the table alignment.
              */
            align: string;
            bgColor: any;
            /**
              * Sets or retrieves the width of the border to draw around the object.
              */
            border: string;
            /**
              * Sets or retrieves the border color of the object. 
              */
            borderColor: any;
            /**
              * Retrieves the caption object of a table.
              */
            caption: HTMLTableCaptionElement;
            /**
              * Sets or retrieves the amount of space between the border of the cell and the content of the cell.
              */
            cellPadding: string;
            /**
              * Sets or retrieves the amount of space between cells in a table.
              */
            cellSpacing: string;
            /**
              * Sets or retrieves the number of columns in the table.
              */
            cols: number;
            /**
              * Sets or retrieves the way the border frame around the table is displayed.
              */
            frame: string;
            /**
              * Sets or retrieves the height of the object.
              */
            height: any;
            /**
              * Sets or retrieves the number of horizontal rows contained in the object.
              */
            rows: HTMLCollection;
            /**
              * Sets or retrieves which dividing lines (inner borders) are displayed.
              */
            rules: string;
            /**
              * Sets or retrieves a description and/or structure of the object.
              */
            summary: string;
            /**
              * Retrieves a collection of all tBody objects in the table. Objects in this collection are in source order.
              */
            tBodies: HTMLCollection;
            /**
              * Retrieves the tFoot object of the table.
              */
            tFoot: HTMLTableSectionElement;
            /**
              * Retrieves the tHead object of the table.
              */
            tHead: HTMLTableSectionElement;
            /**
              * Sets or retrieves the width of the object.
              */
            width: string;
            /**
              * Creates an empty caption element in the table.
              */
            createCaption(): HTMLElement;
            /**
              * Creates an empty tBody element in the table.
              */
            createTBody(): HTMLElement;
            /**
              * Creates an empty tFoot element in the table.
              */
            createTFoot(): HTMLElement;
            /**
              * Returns the tHead element object if successful, or null otherwise.
              */
            createTHead(): HTMLElement;
            /**
              * Deletes the caption element and its contents from the table.
              */
            deleteCaption(): void;
            /**
              * Removes the specified row (tr) from the element and from the rows collection.
              * @param index Number that specifies the zero-based position in the rows collection of the row to remove.
              */
            deleteRow(index?: number): void;
            /**
              * Deletes the tFoot element and its contents from the table.
              */
            deleteTFoot(): void;
            /**
              * Deletes the tHead element and its contents from the table.
              */
            deleteTHead(): void;
            /**
              * Creates a new row (tr) in the table, and adds the row to the rows collection.
              * @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection.
              */
            insertRow(index?: number): HTMLElement;
        }
        
        declare var HTMLTableElement: {
            prototype: HTMLTableElement;
            new(): HTMLTableElement;
        }
        
        interface HTMLTableHeaderCellElement extends HTMLTableCellElement {
            /**
              * Sets or retrieves the group of cells in a table to which the object's information applies.
              */
            scope: string;
        }
        
        declare var HTMLTableHeaderCellElement: {
            prototype: HTMLTableHeaderCellElement;
            new(): HTMLTableHeaderCellElement;
        }
        
        interface HTMLTableRowElement extends HTMLElement, HTMLTableAlignment {
            /**
              * Sets or retrieves how the object is aligned with adjacent text.
              */
            align: string;
            bgColor: any;
            /**
              * Retrieves a collection of all cells in the table row.
              */
            cells: HTMLCollection;
            /**
              * Sets or retrieves the height of the object.
              */
            height: any;
            /**
              * Retrieves the position of the object in the rows collection for the table.
              */
            rowIndex: number;
            /**
              * Retrieves the position of the object in the collection.
              */
            sectionRowIndex: number;
            /**
              * Removes the specified cell from the table row, as well as from the cells collection.
              * @param index Number that specifies the zero-based position of the cell to remove from the table row. If no value is provided, the last cell in the cells collection is deleted.
              */
            deleteCell(index?: number): void;
            /**
              * Creates a new cell in the table row, and adds the cell to the cells collection.
              * @param index Number that specifies where to insert the cell in the tr. The default value is -1, which appends the new cell to the end of the cells collection.
              */
            insertCell(index?: number): HTMLElement;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLTableRowElement: {
            prototype: HTMLTableRowElement;
            new(): HTMLTableRowElement;
        }
        
        interface HTMLTableSectionElement extends HTMLElement, HTMLTableAlignment {
            /**
              * Sets or retrieves a value that indicates the table alignment.
              */
            align: string;
            /**
              * Sets or retrieves the number of horizontal rows contained in the object.
              */
            rows: HTMLCollection;
            /**
              * Removes the specified row (tr) from the element and from the rows collection.
              * @param index Number that specifies the zero-based position in the rows collection of the row to remove.
              */
            deleteRow(index?: number): void;
            /**
              * Creates a new row (tr) in the table, and adds the row to the rows collection.
              * @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection.
              */
            insertRow(index?: number): HTMLElement;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLTableSectionElement: {
            prototype: HTMLTableSectionElement;
            new(): HTMLTableSectionElement;
        }
        
        interface HTMLTextAreaElement extends HTMLElement {
            /**
              * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.
              */
            autofocus: boolean;
            /**
              * Sets or retrieves the width of the object.
              */
            cols: number;
            /**
              * Sets or retrieves the initial contents of the object.
              */
            defaultValue: string;
            disabled: boolean;
            /**
              * Retrieves a reference to the form that the object is embedded in.
              */
            form: HTMLFormElement;
            /**
              * Sets or retrieves the maximum number of characters that the user can enter in a text control.
              */
            maxLength: number;
            /**
              * Sets or retrieves the name of the object.
              */
            name: string;
            /**
              * Gets or sets a text string that is displayed in an input field as a hint or prompt to users as the format or type of information they need to enter.The text appears in an input field until the user puts focus on the field.
              */
            placeholder: string;
            /**
              * Sets or retrieves the value indicated whether the content of the object is read-only.
              */
            readOnly: boolean;
            /**
              * When present, marks an element that can't be submitted without a value.
              */
            required: boolean;
            /**
              * Sets or retrieves the number of horizontal rows contained in the object.
              */
            rows: number;
            /**
              * Gets or sets the end position or offset of a text selection.
              */
            selectionEnd: number;
            /**
              * Gets or sets the starting position or offset of a text selection.
              */
            selectionStart: number;
            /**
              * Sets or retrieves the value indicating whether the control is selected.
              */
            status: any;
            /**
              * Retrieves the type of control.
              */
            type: string;
            /**
              * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
              */
            validationMessage: string;
            /**
              * Returns a  ValidityState object that represents the validity states of an element.
              */
            validity: ValidityState;
            /**
              * Retrieves or sets the text in the entry field of the textArea element.
              */
            value: string;
            /**
              * Returns whether an element will successfully validate based on forms validation rules and constraints.
              */
            willValidate: boolean;
            /**
              * Sets or retrieves how to handle wordwrapping in the object.
              */
            wrap: string;
            /**
              * Returns whether a form will validate when it is submitted, without having to submit it.
              */
            checkValidity(): boolean;
            /**
              * Creates a TextRange object for the element.
              */
            createTextRange(): TextRange;
            /**
              * Highlights the input area of a form element.
              */
            select(): void;
            /**
              * Sets a custom error message that is displayed when a form is submitted.
              * @param error Sets a custom error message that is displayed when a form is submitted.
              */
            setCustomValidity(error: string): void;
            /**
              * Sets the start and end positions of a selection in a text field.
              * @param start The offset into the text field for the start of the selection.
              * @param end The offset into the text field for the end of the selection.
              */
            setSelectionRange(start: number, end: number): void;
        }
        
        declare var HTMLTextAreaElement: {
            prototype: HTMLTextAreaElement;
            new(): HTMLTextAreaElement;
        }
        
        interface HTMLTitleElement extends HTMLElement {
            /**
              * Retrieves or sets the text of the object as a string. 
              */
            text: string;
        }
        
        declare var HTMLTitleElement: {
            prototype: HTMLTitleElement;
            new(): HTMLTitleElement;
        }
        
        interface HTMLTrackElement extends HTMLElement {
            default: boolean;
            kind: string;
            label: string;
            readyState: number;
            src: string;
            srclang: string;
            track: TextTrack;
            ERROR: number;
            LOADED: number;
            LOADING: number;
            NONE: number;
        }
        
        declare var HTMLTrackElement: {
            prototype: HTMLTrackElement;
            new(): HTMLTrackElement;
            ERROR: number;
            LOADED: number;
            LOADING: number;
            NONE: number;
        }
        
        interface HTMLUListElement extends HTMLElement {
            compact: boolean;
            type: string;
        }
        
        declare var HTMLUListElement: {
            prototype: HTMLUListElement;
            new(): HTMLUListElement;
        }
        
        interface HTMLUnknownElement extends HTMLElement {
        }
        
        declare var HTMLUnknownElement: {
            prototype: HTMLUnknownElement;
            new(): HTMLUnknownElement;
        }
        
        interface HTMLVideoElement extends HTMLMediaElement {
            /**
              * Gets or sets the height of the video element.
              */
            height: number;
            msHorizontalMirror: boolean;
            msIsLayoutOptimalForPlayback: boolean;
            msIsStereo3D: boolean;
            msStereo3DPackingMode: string;
            msStereo3DRenderMode: string;
            msZoom: boolean;
            onMSVideoFormatChanged: (ev: Event) => any;
            onMSVideoFrameStepCompleted: (ev: Event) => any;
            onMSVideoOptimalLayoutChanged: (ev: Event) => any;
            /**
              * Gets or sets a URL of an image to display, for example, like a movie poster. This can be a still frame from the video, or another image if no video data is available.
              */
            poster: string;
            /**
              * Gets the intrinsic height of a video in CSS pixels, or zero if the dimensions are not known.
              */
            videoHeight: number;
            /**
              * Gets the intrinsic width of a video in CSS pixels, or zero if the dimensions are not known.
              */
            videoWidth: number;
            webkitDisplayingFullscreen: boolean;
            webkitSupportsFullscreen: boolean;
            /**
              * Gets or sets the width of the video element.
              */
            width: number;
            getVideoPlaybackQuality(): VideoPlaybackQuality;
            msFrameStep(forward: boolean): void;
            msInsertVideoEffect(activatableClassId: string, effectRequired: boolean, config?: any): void;
            msSetVideoRectangle(left: number, top: number, right: number, bottom: number): void;
            webkitEnterFullScreen(): void;
            webkitEnterFullscreen(): void;
            webkitExitFullScreen(): void;
            webkitExitFullscreen(): void;
            addEventListener(type: "MSContentZoom", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGotPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSLostPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSManipulationStateChanged", listener: (ev: MSManipulationEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSVideoFormatChanged", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "MSVideoFrameStepCompleted", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "MSVideoOptimalLayoutChanged", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "msneedkey", listener: (ev: MSMediaKeyNeededEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "touchcancel", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchend", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchmove", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchstart", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var HTMLVideoElement: {
            prototype: HTMLVideoElement;
            new(): HTMLVideoElement;
        }
        
        interface HashChangeEvent extends Event {
            newURL: string;
            oldURL: string;
        }
        
        declare var HashChangeEvent: {
            prototype: HashChangeEvent;
            new(type: string, eventInitDict?: HashChangeEventInit): HashChangeEvent;
        }
        
        interface History {
            length: number;
            state: any;
            back(distance?: any): void;
            forward(distance?: any): void;
            go(delta?: any): void;
            pushState(statedata: any, title?: string, url?: string): void;
            replaceState(statedata: any, title?: string, url?: string): void;
        }
        
        declare var History: {
            prototype: History;
            new(): History;
        }
        
        interface IDBCursor {
            direction: string;
            key: any;
            primaryKey: any;
            source: any;
            advance(count: number): void;
            continue(key?: any): void;
            delete(): IDBRequest;
            update(value: any): IDBRequest;
            NEXT: string;
            NEXT_NO_DUPLICATE: string;
            PREV: string;
            PREV_NO_DUPLICATE: string;
        }
        
        declare var IDBCursor: {
            prototype: IDBCursor;
            new(): IDBCursor;
            NEXT: string;
            NEXT_NO_DUPLICATE: string;
            PREV: string;
            PREV_NO_DUPLICATE: string;
        }
        
        interface IDBCursorWithValue extends IDBCursor {
            value: any;
        }
        
        declare var IDBCursorWithValue: {
            prototype: IDBCursorWithValue;
            new(): IDBCursorWithValue;
        }
        
        interface IDBDatabase extends EventTarget {
            name: string;
            objectStoreNames: DOMStringList;
            onabort: (ev: Event) => any;
            onerror: (ev: Event) => any;
            version: string;
            close(): void;
            createObjectStore(name: string, optionalParameters?: any): IDBObjectStore;
            deleteObjectStore(name: string): void;
            transaction(storeNames: any, mode?: string): IDBTransaction;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var IDBDatabase: {
            prototype: IDBDatabase;
            new(): IDBDatabase;
        }
        
        interface IDBFactory {
            cmp(first: any, second: any): number;
            deleteDatabase(name: string): IDBOpenDBRequest;
            open(name: string, version?: number): IDBOpenDBRequest;
        }
        
        declare var IDBFactory: {
            prototype: IDBFactory;
            new(): IDBFactory;
        }
        
        interface IDBIndex {
            keyPath: string;
            name: string;
            objectStore: IDBObjectStore;
            unique: boolean;
            count(key?: any): IDBRequest;
            get(key: any): IDBRequest;
            getKey(key: any): IDBRequest;
            openCursor(range?: IDBKeyRange, direction?: string): IDBRequest;
            openKeyCursor(range?: IDBKeyRange, direction?: string): IDBRequest;
        }
        
        declare var IDBIndex: {
            prototype: IDBIndex;
            new(): IDBIndex;
        }
        
        interface IDBKeyRange {
            lower: any;
            lowerOpen: boolean;
            upper: any;
            upperOpen: boolean;
        }
        
        declare var IDBKeyRange: {
            prototype: IDBKeyRange;
            new(): IDBKeyRange;
            bound(lower: any, upper: any, lowerOpen?: boolean, upperOpen?: boolean): IDBKeyRange;
            lowerBound(bound: any, open?: boolean): IDBKeyRange;
            only(value: any): IDBKeyRange;
            upperBound(bound: any, open?: boolean): IDBKeyRange;
        }
        
        interface IDBObjectStore {
            indexNames: DOMStringList;
            keyPath: string;
            name: string;
            transaction: IDBTransaction;
            add(value: any, key?: any): IDBRequest;
            clear(): IDBRequest;
            count(key?: any): IDBRequest;
            createIndex(name: string, keyPath: string, optionalParameters?: any): IDBIndex;
            delete(key: any): IDBRequest;
            deleteIndex(indexName: string): void;
            get(key: any): IDBRequest;
            index(name: string): IDBIndex;
            openCursor(range?: any, direction?: string): IDBRequest;
            put(value: any, key?: any): IDBRequest;
        }
        
        declare var IDBObjectStore: {
            prototype: IDBObjectStore;
            new(): IDBObjectStore;
        }
        
        interface IDBOpenDBRequest extends IDBRequest {
            onblocked: (ev: Event) => any;
            onupgradeneeded: (ev: IDBVersionChangeEvent) => any;
            addEventListener(type: "blocked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "success", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "upgradeneeded", listener: (ev: IDBVersionChangeEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var IDBOpenDBRequest: {
            prototype: IDBOpenDBRequest;
            new(): IDBOpenDBRequest;
        }
        
        interface IDBRequest extends EventTarget {
            error: DOMError;
            onerror: (ev: Event) => any;
            onsuccess: (ev: Event) => any;
            readyState: string;
            result: any;
            source: any;
            transaction: IDBTransaction;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "success", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var IDBRequest: {
            prototype: IDBRequest;
            new(): IDBRequest;
        }
        
        interface IDBTransaction extends EventTarget {
            db: IDBDatabase;
            error: DOMError;
            mode: string;
            onabort: (ev: Event) => any;
            oncomplete: (ev: Event) => any;
            onerror: (ev: Event) => any;
            abort(): void;
            objectStore(name: string): IDBObjectStore;
            READ_ONLY: string;
            READ_WRITE: string;
            VERSION_CHANGE: string;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "complete", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var IDBTransaction: {
            prototype: IDBTransaction;
            new(): IDBTransaction;
            READ_ONLY: string;
            READ_WRITE: string;
            VERSION_CHANGE: string;
        }
        
        interface IDBVersionChangeEvent extends Event {
            newVersion: number;
            oldVersion: number;
        }
        
        declare var IDBVersionChangeEvent: {
            prototype: IDBVersionChangeEvent;
            new(): IDBVersionChangeEvent;
        }
        
        interface ImageData {
            data: number[];
            height: number;
            width: number;
        }
        
        declare var ImageData: {
            prototype: ImageData;
            new(): ImageData;
        }
        
        interface KeyboardEvent extends UIEvent {
            altKey: boolean;
            char: string;
            charCode: number;
            ctrlKey: boolean;
            key: string;
            keyCode: number;
            locale: string;
            location: number;
            metaKey: boolean;
            repeat: boolean;
            shiftKey: boolean;
            which: number;
            getModifierState(keyArg: string): boolean;
            initKeyboardEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, keyArg: string, locationArg: number, modifiersListArg: string, repeat: boolean, locale: string): void;
            DOM_KEY_LOCATION_JOYSTICK: number;
            DOM_KEY_LOCATION_LEFT: number;
            DOM_KEY_LOCATION_MOBILE: number;
            DOM_KEY_LOCATION_NUMPAD: number;
            DOM_KEY_LOCATION_RIGHT: number;
            DOM_KEY_LOCATION_STANDARD: number;
        }
        
        declare var KeyboardEvent: {
            prototype: KeyboardEvent;
            new(typeArg: string, eventInitDict?: KeyboardEventInit): KeyboardEvent;
            DOM_KEY_LOCATION_JOYSTICK: number;
            DOM_KEY_LOCATION_LEFT: number;
            DOM_KEY_LOCATION_MOBILE: number;
            DOM_KEY_LOCATION_NUMPAD: number;
            DOM_KEY_LOCATION_RIGHT: number;
            DOM_KEY_LOCATION_STANDARD: number;
        }
        
        interface Location {
            hash: string;
            host: string;
            hostname: string;
            href: string;
            origin: string;
            pathname: string;
            port: string;
            protocol: string;
            search: string;
            assign(url: string): void;
            reload(forcedReload?: boolean): void;
            replace(url: string): void;
            toString(): string;
        }
        
        declare var Location: {
            prototype: Location;
            new(): Location;
        }
        
        interface LongRunningScriptDetectedEvent extends Event {
            executionTime: number;
            stopPageScriptExecution: boolean;
        }
        
        declare var LongRunningScriptDetectedEvent: {
            prototype: LongRunningScriptDetectedEvent;
            new(): LongRunningScriptDetectedEvent;
        }
        
        interface MSApp {
            clearTemporaryWebDataAsync(): MSAppAsyncOperation;
            createBlobFromRandomAccessStream(type: string, seeker: any): Blob;
            createDataPackage(object: any): any;
            createDataPackageFromSelection(): any;
            createFileFromStorageFile(storageFile: any): File;
            createStreamFromInputStream(type: string, inputStream: any): MSStream;
            execAsyncAtPriority(asynchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): void;
            execAtPriority(synchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): any;
            getCurrentPriority(): string;
            getHtmlPrintDocumentSourceAsync(htmlDoc: any): any;
            getViewId(view: any): any;
            isTaskScheduledAtPriorityOrHigher(priority: string): boolean;
            pageHandlesAllApplicationActivations(enabled: boolean): void;
            suppressSubdownloadCredentialPrompts(suppress: boolean): void;
            terminateApp(exceptionObject: any): void;
            CURRENT: string;
            HIGH: string;
            IDLE: string;
            NORMAL: string;
        }
        declare var MSApp: MSApp;
        
        interface MSAppAsyncOperation extends EventTarget {
            error: DOMError;
            oncomplete: (ev: Event) => any;
            onerror: (ev: Event) => any;
            readyState: number;
            result: any;
            start(): void;
            COMPLETED: number;
            ERROR: number;
            STARTED: number;
            addEventListener(type: "complete", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var MSAppAsyncOperation: {
            prototype: MSAppAsyncOperation;
            new(): MSAppAsyncOperation;
            COMPLETED: number;
            ERROR: number;
            STARTED: number;
        }
        
        interface MSBlobBuilder {
            append(data: any, endings?: string): void;
            getBlob(contentType?: string): Blob;
        }
        
        declare var MSBlobBuilder: {
            prototype: MSBlobBuilder;
            new(): MSBlobBuilder;
        }
        
        interface MSCSSMatrix {
            a: number;
            b: number;
            c: number;
            d: number;
            e: number;
            f: number;
            m11: number;
            m12: number;
            m13: number;
            m14: number;
            m21: number;
            m22: number;
            m23: number;
            m24: number;
            m31: number;
            m32: number;
            m33: number;
            m34: number;
            m41: number;
            m42: number;
            m43: number;
            m44: number;
            inverse(): MSCSSMatrix;
            multiply(secondMatrix: MSCSSMatrix): MSCSSMatrix;
            rotate(angleX: number, angleY?: number, angleZ?: number): MSCSSMatrix;
            rotateAxisAngle(x: number, y: number, z: number, angle: number): MSCSSMatrix;
            scale(scaleX: number, scaleY?: number, scaleZ?: number): MSCSSMatrix;
            setMatrixValue(value: string): void;
            skewX(angle: number): MSCSSMatrix;
            skewY(angle: number): MSCSSMatrix;
            toString(): string;
            translate(x: number, y: number, z?: number): MSCSSMatrix;
        }
        
        declare var MSCSSMatrix: {
            prototype: MSCSSMatrix;
            new(text?: string): MSCSSMatrix;
        }
        
        interface MSGesture {
            target: Element;
            addPointer(pointerId: number): void;
            stop(): void;
        }
        
        declare var MSGesture: {
            prototype: MSGesture;
            new(): MSGesture;
        }
        
        interface MSGestureEvent extends UIEvent {
            clientX: number;
            clientY: number;
            expansion: number;
            gestureObject: any;
            hwTimestamp: number;
            offsetX: number;
            offsetY: number;
            rotation: number;
            scale: number;
            screenX: number;
            screenY: number;
            translationX: number;
            translationY: number;
            velocityAngular: number;
            velocityExpansion: number;
            velocityX: number;
            velocityY: number;
            initGestureEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, offsetXArg: number, offsetYArg: number, translationXArg: number, translationYArg: number, scaleArg: number, expansionArg: number, rotationArg: number, velocityXArg: number, velocityYArg: number, velocityExpansionArg: number, velocityAngularArg: number, hwTimestampArg: number): void;
            MSGESTURE_FLAG_BEGIN: number;
            MSGESTURE_FLAG_CANCEL: number;
            MSGESTURE_FLAG_END: number;
            MSGESTURE_FLAG_INERTIA: number;
            MSGESTURE_FLAG_NONE: number;
        }
        
        declare var MSGestureEvent: {
            prototype: MSGestureEvent;
            new(): MSGestureEvent;
            MSGESTURE_FLAG_BEGIN: number;
            MSGESTURE_FLAG_CANCEL: number;
            MSGESTURE_FLAG_END: number;
            MSGESTURE_FLAG_INERTIA: number;
            MSGESTURE_FLAG_NONE: number;
        }
        
        interface MSGraphicsTrust {
            constrictionActive: boolean;
            status: string;
        }
        
        declare var MSGraphicsTrust: {
            prototype: MSGraphicsTrust;
            new(): MSGraphicsTrust;
        }
        
        interface MSHTMLWebViewElement extends HTMLElement {
            canGoBack: boolean;
            canGoForward: boolean;
            containsFullScreenElement: boolean;
            documentTitle: string;
            height: number;
            settings: MSWebViewSettings;
            src: string;
            width: number;
            addWebAllowedObject(name: string, applicationObject: any): void;
            buildLocalStreamUri(contentIdentifier: string, relativePath: string): string;
            capturePreviewToBlobAsync(): MSWebViewAsyncOperation;
            captureSelectedContentToDataPackageAsync(): MSWebViewAsyncOperation;
            getDeferredPermissionRequestById(id: number): DeferredPermissionRequest;
            getDeferredPermissionRequests(): DeferredPermissionRequest[];
            goBack(): void;
            goForward(): void;
            invokeScriptAsync(scriptName: string, ...args: any[]): MSWebViewAsyncOperation;
            navigate(uri: string): void;
            navigateToLocalStreamUri(source: string, streamResolver: any): void;
            navigateToString(contents: string): void;
            navigateWithHttpRequestMessage(requestMessage: any): void;
            refresh(): void;
            stop(): void;
        }
        
        declare var MSHTMLWebViewElement: {
            prototype: MSHTMLWebViewElement;
            new(): MSHTMLWebViewElement;
        }
        
        interface MSHeaderFooter {
            URL: string;
            dateLong: string;
            dateShort: string;
            font: string;
            htmlFoot: string;
            htmlHead: string;
            page: number;
            pageTotal: number;
            textFoot: string;
            textHead: string;
            timeLong: string;
            timeShort: string;
            title: string;
        }
        
        declare var MSHeaderFooter: {
            prototype: MSHeaderFooter;
            new(): MSHeaderFooter;
        }
        
        interface MSInputMethodContext extends EventTarget {
            compositionEndOffset: number;
            compositionStartOffset: number;
            oncandidatewindowhide: (ev: Event) => any;
            oncandidatewindowshow: (ev: Event) => any;
            oncandidatewindowupdate: (ev: Event) => any;
            target: HTMLElement;
            getCandidateWindowClientRect(): ClientRect;
            getCompositionAlternatives(): string[];
            hasComposition(): boolean;
            isCandidateWindowVisible(): boolean;
            addEventListener(type: "MSCandidateWindowHide", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "MSCandidateWindowShow", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "MSCandidateWindowUpdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var MSInputMethodContext: {
            prototype: MSInputMethodContext;
            new(): MSInputMethodContext;
        }
        
        interface MSManipulationEvent extends UIEvent {
            currentState: number;
            inertiaDestinationX: number;
            inertiaDestinationY: number;
            lastState: number;
            initMSManipulationEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, lastState: number, currentState: number): void;
            MS_MANIPULATION_STATE_ACTIVE: number;
            MS_MANIPULATION_STATE_CANCELLED: number;
            MS_MANIPULATION_STATE_COMMITTED: number;
            MS_MANIPULATION_STATE_DRAGGING: number;
            MS_MANIPULATION_STATE_INERTIA: number;
            MS_MANIPULATION_STATE_PRESELECT: number;
            MS_MANIPULATION_STATE_SELECTING: number;
            MS_MANIPULATION_STATE_STOPPED: number;
        }
        
        declare var MSManipulationEvent: {
            prototype: MSManipulationEvent;
            new(): MSManipulationEvent;
            MS_MANIPULATION_STATE_ACTIVE: number;
            MS_MANIPULATION_STATE_CANCELLED: number;
            MS_MANIPULATION_STATE_COMMITTED: number;
            MS_MANIPULATION_STATE_DRAGGING: number;
            MS_MANIPULATION_STATE_INERTIA: number;
            MS_MANIPULATION_STATE_PRESELECT: number;
            MS_MANIPULATION_STATE_SELECTING: number;
            MS_MANIPULATION_STATE_STOPPED: number;
        }
        
        interface MSMediaKeyError {
            code: number;
            systemCode: number;
            MS_MEDIA_KEYERR_CLIENT: number;
            MS_MEDIA_KEYERR_DOMAIN: number;
            MS_MEDIA_KEYERR_HARDWARECHANGE: number;
            MS_MEDIA_KEYERR_OUTPUT: number;
            MS_MEDIA_KEYERR_SERVICE: number;
            MS_MEDIA_KEYERR_UNKNOWN: number;
        }
        
        declare var MSMediaKeyError: {
            prototype: MSMediaKeyError;
            new(): MSMediaKeyError;
            MS_MEDIA_KEYERR_CLIENT: number;
            MS_MEDIA_KEYERR_DOMAIN: number;
            MS_MEDIA_KEYERR_HARDWARECHANGE: number;
            MS_MEDIA_KEYERR_OUTPUT: number;
            MS_MEDIA_KEYERR_SERVICE: number;
            MS_MEDIA_KEYERR_UNKNOWN: number;
        }
        
        interface MSMediaKeyMessageEvent extends Event {
            destinationURL: string;
            message: Uint8Array;
        }
        
        declare var MSMediaKeyMessageEvent: {
            prototype: MSMediaKeyMessageEvent;
            new(): MSMediaKeyMessageEvent;
        }
        
        interface MSMediaKeyNeededEvent extends Event {
            initData: Uint8Array;
        }
        
        declare var MSMediaKeyNeededEvent: {
            prototype: MSMediaKeyNeededEvent;
            new(): MSMediaKeyNeededEvent;
        }
        
        interface MSMediaKeySession extends EventTarget {
            error: MSMediaKeyError;
            keySystem: string;
            sessionId: string;
            close(): void;
            update(key: Uint8Array): void;
        }
        
        declare var MSMediaKeySession: {
            prototype: MSMediaKeySession;
            new(): MSMediaKeySession;
        }
        
        interface MSMediaKeys {
            keySystem: string;
            createSession(type: string, initData: Uint8Array, cdmData?: Uint8Array): MSMediaKeySession;
        }
        
        declare var MSMediaKeys: {
            prototype: MSMediaKeys;
            new(keySystem: string): MSMediaKeys;
            isTypeSupported(keySystem: string, type?: string): boolean;
        }
        
        interface MSMimeTypesCollection {
            length: number;
        }
        
        declare var MSMimeTypesCollection: {
            prototype: MSMimeTypesCollection;
            new(): MSMimeTypesCollection;
        }
        
        interface MSPluginsCollection {
            length: number;
            refresh(reload?: boolean): void;
        }
        
        declare var MSPluginsCollection: {
            prototype: MSPluginsCollection;
            new(): MSPluginsCollection;
        }
        
        interface MSPointerEvent extends MouseEvent {
            currentPoint: any;
            height: number;
            hwTimestamp: number;
            intermediatePoints: any;
            isPrimary: boolean;
            pointerId: number;
            pointerType: any;
            pressure: number;
            rotation: number;
            tiltX: number;
            tiltY: number;
            width: number;
            getCurrentPoint(element: Element): void;
            getIntermediatePoints(element: Element): void;
            initPointerEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget, offsetXArg: number, offsetYArg: number, widthArg: number, heightArg: number, pressure: number, rotation: number, tiltX: number, tiltY: number, pointerIdArg: number, pointerType: any, hwTimestampArg: number, isPrimary: boolean): void;
        }
        
        declare var MSPointerEvent: {
            prototype: MSPointerEvent;
            new(typeArg: string, eventInitDict?: PointerEventInit): MSPointerEvent;
        }
        
        interface MSPrintManagerTemplatePrinter extends MSTemplatePrinter, EventTarget {
            percentScale: number;
            showHeaderFooter: boolean;
            shrinkToFit: boolean;
            drawPreviewPage(element: HTMLElement, pageNumber: number): void;
            endPrint(): void;
            getPrintTaskOptionValue(key: string): any;
            invalidatePreview(): void;
            setPageCount(pageCount: number): void;
            startPrint(): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var MSPrintManagerTemplatePrinter: {
            prototype: MSPrintManagerTemplatePrinter;
            new(): MSPrintManagerTemplatePrinter;
        }
        
        interface MSRangeCollection {
            length: number;
            item(index: number): Range;
            [index: number]: Range;
        }
        
        declare var MSRangeCollection: {
            prototype: MSRangeCollection;
            new(): MSRangeCollection;
        }
        
        interface MSSiteModeEvent extends Event {
            actionURL: string;
            buttonID: number;
        }
        
        declare var MSSiteModeEvent: {
            prototype: MSSiteModeEvent;
            new(): MSSiteModeEvent;
        }
        
        interface MSStream {
            type: string;
            msClose(): void;
            msDetachStream(): any;
        }
        
        declare var MSStream: {
            prototype: MSStream;
            new(): MSStream;
        }
        
        interface MSStreamReader extends EventTarget, MSBaseReader {
            error: DOMError;
            readAsArrayBuffer(stream: MSStream, size?: number): void;
            readAsBinaryString(stream: MSStream, size?: number): void;
            readAsBlob(stream: MSStream, size?: number): void;
            readAsDataURL(stream: MSStream, size?: number): void;
            readAsText(stream: MSStream, encoding?: string, size?: number): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var MSStreamReader: {
            prototype: MSStreamReader;
            new(): MSStreamReader;
        }
        
        interface MSTemplatePrinter {
            collate: boolean;
            copies: number;
            currentPage: boolean;
            currentPageAvail: boolean;
            duplex: boolean;
            footer: string;
            frameActive: boolean;
            frameActiveEnabled: boolean;
            frameAsShown: boolean;
            framesetDocument: boolean;
            header: string;
            headerFooterFont: string;
            marginBottom: number;
            marginLeft: number;
            marginRight: number;
            marginTop: number;
            orientation: string;
            pageFrom: number;
            pageHeight: number;
            pageTo: number;
            pageWidth: number;
            selectedPages: boolean;
            selection: boolean;
            selectionEnabled: boolean;
            unprintableBottom: number;
            unprintableLeft: number;
            unprintableRight: number;
            unprintableTop: number;
            usePrinterCopyCollate: boolean;
            createHeaderFooter(): MSHeaderFooter;
            deviceSupports(property: string): any;
            ensurePrintDialogDefaults(): boolean;
            getPageMarginBottom(pageRule: CSSPageRule, pageWidth: number, pageHeight: number): any;
            getPageMarginBottomImportant(pageRule: CSSPageRule): boolean;
            getPageMarginLeft(pageRule: CSSPageRule, pageWidth: number, pageHeight: number): any;
            getPageMarginLeftImportant(pageRule: CSSPageRule): boolean;
            getPageMarginRight(pageRule: CSSPageRule, pageWidth: number, pageHeight: number): any;
            getPageMarginRightImportant(pageRule: CSSPageRule): boolean;
            getPageMarginTop(pageRule: CSSPageRule, pageWidth: number, pageHeight: number): any;
            getPageMarginTopImportant(pageRule: CSSPageRule): boolean;
            printBlankPage(): void;
            printNonNative(document: any): boolean;
            printNonNativeFrames(document: any, activeFrame: boolean): void;
            printPage(element: HTMLElement): void;
            showPageSetupDialog(): boolean;
            showPrintDialog(): boolean;
            startDoc(title: string): boolean;
            stopDoc(): void;
            updatePageStatus(status: number): void;
        }
        
        declare var MSTemplatePrinter: {
            prototype: MSTemplatePrinter;
            new(): MSTemplatePrinter;
        }
        
        interface MSWebViewAsyncOperation extends EventTarget {
            error: DOMError;
            oncomplete: (ev: Event) => any;
            onerror: (ev: Event) => any;
            readyState: number;
            result: any;
            target: MSHTMLWebViewElement;
            type: number;
            start(): void;
            COMPLETED: number;
            ERROR: number;
            STARTED: number;
            TYPE_CAPTURE_PREVIEW_TO_RANDOM_ACCESS_STREAM: number;
            TYPE_CREATE_DATA_PACKAGE_FROM_SELECTION: number;
            TYPE_INVOKE_SCRIPT: number;
            addEventListener(type: "complete", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var MSWebViewAsyncOperation: {
            prototype: MSWebViewAsyncOperation;
            new(): MSWebViewAsyncOperation;
            COMPLETED: number;
            ERROR: number;
            STARTED: number;
            TYPE_CAPTURE_PREVIEW_TO_RANDOM_ACCESS_STREAM: number;
            TYPE_CREATE_DATA_PACKAGE_FROM_SELECTION: number;
            TYPE_INVOKE_SCRIPT: number;
        }
        
        interface MSWebViewSettings {
            isIndexedDBEnabled: boolean;
            isJavaScriptEnabled: boolean;
        }
        
        declare var MSWebViewSettings: {
            prototype: MSWebViewSettings;
            new(): MSWebViewSettings;
        }
        
        interface MediaElementAudioSourceNode extends AudioNode {
        }
        
        declare var MediaElementAudioSourceNode: {
            prototype: MediaElementAudioSourceNode;
            new(): MediaElementAudioSourceNode;
        }
        
        interface MediaError {
            code: number;
            msExtendedCode: number;
            MEDIA_ERR_ABORTED: number;
            MEDIA_ERR_DECODE: number;
            MEDIA_ERR_NETWORK: number;
            MEDIA_ERR_SRC_NOT_SUPPORTED: number;
            MS_MEDIA_ERR_ENCRYPTED: number;
        }
        
        declare var MediaError: {
            prototype: MediaError;
            new(): MediaError;
            MEDIA_ERR_ABORTED: number;
            MEDIA_ERR_DECODE: number;
            MEDIA_ERR_NETWORK: number;
            MEDIA_ERR_SRC_NOT_SUPPORTED: number;
            MS_MEDIA_ERR_ENCRYPTED: number;
        }
        
        interface MediaList {
            length: number;
            mediaText: string;
            appendMedium(newMedium: string): void;
            deleteMedium(oldMedium: string): void;
            item(index: number): string;
            toString(): string;
            [index: number]: string;
        }
        
        declare var MediaList: {
            prototype: MediaList;
            new(): MediaList;
        }
        
        interface MediaQueryList {
            matches: boolean;
            media: string;
            addListener(listener: MediaQueryListListener): void;
            removeListener(listener: MediaQueryListListener): void;
        }
        
        declare var MediaQueryList: {
            prototype: MediaQueryList;
            new(): MediaQueryList;
        }
        
        interface MediaSource extends EventTarget {
            activeSourceBuffers: SourceBufferList;
            duration: number;
            readyState: string;
            sourceBuffers: SourceBufferList;
            addSourceBuffer(type: string): SourceBuffer;
            endOfStream(error?: string): void;
            removeSourceBuffer(sourceBuffer: SourceBuffer): void;
        }
        
        declare var MediaSource: {
            prototype: MediaSource;
            new(): MediaSource;
            isTypeSupported(type: string): boolean;
        }
        
        interface MessageChannel {
            port1: MessagePort;
            port2: MessagePort;
        }
        
        declare var MessageChannel: {
            prototype: MessageChannel;
            new(): MessageChannel;
        }
        
        interface MessageEvent extends Event {
            data: any;
            origin: string;
            ports: any;
            source: Window;
            initMessageEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, dataArg: any, originArg: string, lastEventIdArg: string, sourceArg: Window): void;
        }
        
        declare var MessageEvent: {
            prototype: MessageEvent;
            new(): MessageEvent;
        }
        
        interface MessagePort extends EventTarget {
            onmessage: (ev: MessageEvent) => any;
            close(): void;
            postMessage(message?: any, ports?: any): void;
            start(): void;
            addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var MessagePort: {
            prototype: MessagePort;
            new(): MessagePort;
        }
        
        interface MimeType {
            description: string;
            enabledPlugin: Plugin;
            suffixes: string;
            type: string;
        }
        
        declare var MimeType: {
            prototype: MimeType;
            new(): MimeType;
        }
        
        interface MimeTypeArray {
            length: number;
            item(index: number): Plugin;
            namedItem(type: string): Plugin;
            [index: number]: Plugin;
        }
        
        declare var MimeTypeArray: {
            prototype: MimeTypeArray;
            new(): MimeTypeArray;
        }
        
        interface MouseEvent extends UIEvent {
            altKey: boolean;
            button: number;
            buttons: number;
            clientX: number;
            clientY: number;
            ctrlKey: boolean;
            fromElement: Element;
            layerX: number;
            layerY: number;
            metaKey: boolean;
            movementX: number;
            movementY: number;
            offsetX: number;
            offsetY: number;
            pageX: number;
            pageY: number;
            relatedTarget: EventTarget;
            screenX: number;
            screenY: number;
            shiftKey: boolean;
            toElement: Element;
            which: number;
            x: number;
            y: number;
            getModifierState(keyArg: string): boolean;
            initMouseEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget): void;
        }
        
        declare var MouseEvent: {
            prototype: MouseEvent;
            new(typeArg: string, eventInitDict?: MouseEventInit): MouseEvent;
        }
        
        interface MouseWheelEvent extends MouseEvent {
            wheelDelta: number;
            wheelDeltaX: number;
            wheelDeltaY: number;
            initMouseWheelEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, buttonArg: number, relatedTargetArg: EventTarget, modifiersListArg: string, wheelDeltaArg: number): void;
        }
        
        declare var MouseWheelEvent: {
            prototype: MouseWheelEvent;
            new(): MouseWheelEvent;
        }
        
        interface MutationEvent extends Event {
            attrChange: number;
            attrName: string;
            newValue: string;
            prevValue: string;
            relatedNode: Node;
            initMutationEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, relatedNodeArg: Node, prevValueArg: string, newValueArg: string, attrNameArg: string, attrChangeArg: number): void;
            ADDITION: number;
            MODIFICATION: number;
            REMOVAL: number;
        }
        
        declare var MutationEvent: {
            prototype: MutationEvent;
            new(): MutationEvent;
            ADDITION: number;
            MODIFICATION: number;
            REMOVAL: number;
        }
        
        interface MutationObserver {
            disconnect(): void;
            observe(target: Node, options: MutationObserverInit): void;
            takeRecords(): MutationRecord[];
        }
        
        declare var MutationObserver: {
            prototype: MutationObserver;
            new(callback: MutationCallback): MutationObserver;
        }
        
        interface MutationRecord {
            addedNodes: NodeList;
            attributeName: string;
            attributeNamespace: string;
            nextSibling: Node;
            oldValue: string;
            previousSibling: Node;
            removedNodes: NodeList;
            target: Node;
            type: string;
        }
        
        declare var MutationRecord: {
            prototype: MutationRecord;
            new(): MutationRecord;
        }
        
        interface NamedNodeMap {
            length: number;
            getNamedItem(name: string): Attr;
            getNamedItemNS(namespaceURI: string, localName: string): Attr;
            item(index: number): Attr;
            removeNamedItem(name: string): Attr;
            removeNamedItemNS(namespaceURI: string, localName: string): Attr;
            setNamedItem(arg: Attr): Attr;
            setNamedItemNS(arg: Attr): Attr;
            [index: number]: Attr;
        }
        
        declare var NamedNodeMap: {
            prototype: NamedNodeMap;
            new(): NamedNodeMap;
        }
        
        interface NavigationCompletedEvent extends NavigationEvent {
            isSuccess: boolean;
            webErrorStatus: number;
        }
        
        declare var NavigationCompletedEvent: {
            prototype: NavigationCompletedEvent;
            new(): NavigationCompletedEvent;
        }
        
        interface NavigationEvent extends Event {
            uri: string;
        }
        
        declare var NavigationEvent: {
            prototype: NavigationEvent;
            new(): NavigationEvent;
        }
        
        interface NavigationEventWithReferrer extends NavigationEvent {
            referer: string;
        }
        
        declare var NavigationEventWithReferrer: {
            prototype: NavigationEventWithReferrer;
            new(): NavigationEventWithReferrer;
        }
        
        interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorContentUtils, NavigatorStorageUtils, NavigatorGeolocation, MSNavigatorDoNotTrack, MSFileSaver {
            appCodeName: string;
            appMinorVersion: string;
            browserLanguage: string;
            connectionSpeed: number;
            cookieEnabled: boolean;
            cpuClass: string;
            language: string;
            maxTouchPoints: number;
            mimeTypes: MSMimeTypesCollection;
            msManipulationViewsEnabled: boolean;
            msMaxTouchPoints: number;
            msPointerEnabled: boolean;
            plugins: MSPluginsCollection;
            pointerEnabled: boolean;
            systemLanguage: string;
            userLanguage: string;
            webdriver: boolean;
            getGamepads(): Gamepad[];
            javaEnabled(): boolean;
            msLaunchUri(uri: string, successCallback?: MSLaunchUriCallback, noHandlerCallback?: MSLaunchUriCallback): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var Navigator: {
            prototype: Navigator;
            new(): Navigator;
        }
        
        interface Node extends EventTarget {
            attributes: NamedNodeMap;
            baseURI: string;
            childNodes: NodeList;
            firstChild: Node;
            lastChild: Node;
            localName: string;
            namespaceURI: string;
            nextSibling: Node;
            nodeName: string;
            nodeType: number;
            nodeValue: string;
            ownerDocument: Document;
            parentElement: HTMLElement;
            parentNode: Node;
            prefix: string;
            previousSibling: Node;
            textContent: string;
            appendChild(newChild: Node): Node;
            cloneNode(deep?: boolean): Node;
            compareDocumentPosition(other: Node): number;
            hasAttributes(): boolean;
            hasChildNodes(): boolean;
            insertBefore(newChild: Node, refChild?: Node): Node;
            isDefaultNamespace(namespaceURI: string): boolean;
            isEqualNode(arg: Node): boolean;
            isSameNode(other: Node): boolean;
            lookupNamespaceURI(prefix: string): string;
            lookupPrefix(namespaceURI: string): string;
            normalize(): void;
            removeChild(oldChild: Node): Node;
            replaceChild(newChild: Node, oldChild: Node): Node;
            ATTRIBUTE_NODE: number;
            CDATA_SECTION_NODE: number;
            COMMENT_NODE: number;
            DOCUMENT_FRAGMENT_NODE: number;
            DOCUMENT_NODE: number;
            DOCUMENT_POSITION_CONTAINED_BY: number;
            DOCUMENT_POSITION_CONTAINS: number;
            DOCUMENT_POSITION_DISCONNECTED: number;
            DOCUMENT_POSITION_FOLLOWING: number;
            DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number;
            DOCUMENT_POSITION_PRECEDING: number;
            DOCUMENT_TYPE_NODE: number;
            ELEMENT_NODE: number;
            ENTITY_NODE: number;
            ENTITY_REFERENCE_NODE: number;
            NOTATION_NODE: number;
            PROCESSING_INSTRUCTION_NODE: number;
            TEXT_NODE: number;
        }
        
        declare var Node: {
            prototype: Node;
            new(): Node;
            ATTRIBUTE_NODE: number;
            CDATA_SECTION_NODE: number;
            COMMENT_NODE: number;
            DOCUMENT_FRAGMENT_NODE: number;
            DOCUMENT_NODE: number;
            DOCUMENT_POSITION_CONTAINED_BY: number;
            DOCUMENT_POSITION_CONTAINS: number;
            DOCUMENT_POSITION_DISCONNECTED: number;
            DOCUMENT_POSITION_FOLLOWING: number;
            DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number;
            DOCUMENT_POSITION_PRECEDING: number;
            DOCUMENT_TYPE_NODE: number;
            ELEMENT_NODE: number;
            ENTITY_NODE: number;
            ENTITY_REFERENCE_NODE: number;
            NOTATION_NODE: number;
            PROCESSING_INSTRUCTION_NODE: number;
            TEXT_NODE: number;
        }
        
        interface NodeFilter {
            FILTER_ACCEPT: number;
            FILTER_REJECT: number;
            FILTER_SKIP: number;
            SHOW_ALL: number;
            SHOW_ATTRIBUTE: number;
            SHOW_CDATA_SECTION: number;
            SHOW_COMMENT: number;
            SHOW_DOCUMENT: number;
            SHOW_DOCUMENT_FRAGMENT: number;
            SHOW_DOCUMENT_TYPE: number;
            SHOW_ELEMENT: number;
            SHOW_ENTITY: number;
            SHOW_ENTITY_REFERENCE: number;
            SHOW_NOTATION: number;
            SHOW_PROCESSING_INSTRUCTION: number;
            SHOW_TEXT: number;
        }
        declare var NodeFilter: NodeFilter;
        
        interface NodeIterator {
            expandEntityReferences: boolean;
            filter: NodeFilter;
            root: Node;
            whatToShow: number;
            detach(): void;
            nextNode(): Node;
            previousNode(): Node;
        }
        
        declare var NodeIterator: {
            prototype: NodeIterator;
            new(): NodeIterator;
        }
        
        interface NodeList {
            length: number;
            item(index: number): Node;
            [index: number]: Node;
        }
        
        declare var NodeList: {
            prototype: NodeList;
            new(): NodeList;
        }
        
        interface OES_element_index_uint {
        }
        
        declare var OES_element_index_uint: {
            prototype: OES_element_index_uint;
            new(): OES_element_index_uint;
        }
        
        interface OES_standard_derivatives {
            FRAGMENT_SHADER_DERIVATIVE_HINT_OES: number;
        }
        
        declare var OES_standard_derivatives: {
            prototype: OES_standard_derivatives;
            new(): OES_standard_derivatives;
            FRAGMENT_SHADER_DERIVATIVE_HINT_OES: number;
        }
        
        interface OES_texture_float {
        }
        
        declare var OES_texture_float: {
            prototype: OES_texture_float;
            new(): OES_texture_float;
        }
        
        interface OES_texture_float_linear {
        }
        
        declare var OES_texture_float_linear: {
            prototype: OES_texture_float_linear;
            new(): OES_texture_float_linear;
        }
        
        interface OfflineAudioCompletionEvent extends Event {
            renderedBuffer: AudioBuffer;
        }
        
        declare var OfflineAudioCompletionEvent: {
            prototype: OfflineAudioCompletionEvent;
            new(): OfflineAudioCompletionEvent;
        }
        
        interface OfflineAudioContext extends AudioContext {
            oncomplete: (ev: Event) => any;
            startRendering(): void;
            addEventListener(type: "complete", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var OfflineAudioContext: {
            prototype: OfflineAudioContext;
            new(numberOfChannels: number, length: number, sampleRate: number): OfflineAudioContext;
        }
        
        interface OscillatorNode extends AudioNode {
            detune: AudioParam;
            frequency: AudioParam;
            onended: (ev: Event) => any;
            type: string;
            setPeriodicWave(periodicWave: PeriodicWave): void;
            start(when?: number): void;
            stop(when?: number): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var OscillatorNode: {
            prototype: OscillatorNode;
            new(): OscillatorNode;
        }
        
        interface PageTransitionEvent extends Event {
            persisted: boolean;
        }
        
        declare var PageTransitionEvent: {
            prototype: PageTransitionEvent;
            new(): PageTransitionEvent;
        }
        
        interface PannerNode extends AudioNode {
            coneInnerAngle: number;
            coneOuterAngle: number;
            coneOuterGain: number;
            distanceModel: string;
            maxDistance: number;
            panningModel: string;
            refDistance: number;
            rolloffFactor: number;
            setOrientation(x: number, y: number, z: number): void;
            setPosition(x: number, y: number, z: number): void;
            setVelocity(x: number, y: number, z: number): void;
        }
        
        declare var PannerNode: {
            prototype: PannerNode;
            new(): PannerNode;
        }
        
        interface PerfWidgetExternal {
            activeNetworkRequestCount: number;
            averageFrameTime: number;
            averagePaintTime: number;
            extraInformationEnabled: boolean;
            independentRenderingEnabled: boolean;
            irDisablingContentString: string;
            irStatusAvailable: boolean;
            maxCpuSpeed: number;
            paintRequestsPerSecond: number;
            performanceCounter: number;
            performanceCounterFrequency: number;
            addEventListener(eventType: string, callback: Function): void;
            getMemoryUsage(): number;
            getProcessCpuUsage(): number;
            getRecentCpuUsage(last: number): any;
            getRecentFrames(last: number): any;
            getRecentMemoryUsage(last: number): any;
            getRecentPaintRequests(last: number): any;
            removeEventListener(eventType: string, callback: Function): void;
            repositionWindow(x: number, y: number): void;
            resizeWindow(width: number, height: number): void;
        }
        
        declare var PerfWidgetExternal: {
            prototype: PerfWidgetExternal;
            new(): PerfWidgetExternal;
        }
        
        interface Performance {
            navigation: PerformanceNavigation;
            timing: PerformanceTiming;
            clearMarks(markName?: string): void;
            clearMeasures(measureName?: string): void;
            clearResourceTimings(): void;
            getEntries(): any;
            getEntriesByName(name: string, entryType?: string): any;
            getEntriesByType(entryType: string): any;
            getMarks(markName?: string): any;
            getMeasures(measureName?: string): any;
            mark(markName: string): void;
            measure(measureName: string, startMarkName?: string, endMarkName?: string): void;
            now(): number;
            setResourceTimingBufferSize(maxSize: number): void;
            toJSON(): any;
        }
        
        declare var Performance: {
            prototype: Performance;
            new(): Performance;
        }
        
        interface PerformanceEntry {
            duration: number;
            entryType: string;
            name: string;
            startTime: number;
        }
        
        declare var PerformanceEntry: {
            prototype: PerformanceEntry;
            new(): PerformanceEntry;
        }
        
        interface PerformanceMark extends PerformanceEntry {
        }
        
        declare var PerformanceMark: {
            prototype: PerformanceMark;
            new(): PerformanceMark;
        }
        
        interface PerformanceMeasure extends PerformanceEntry {
        }
        
        declare var PerformanceMeasure: {
            prototype: PerformanceMeasure;
            new(): PerformanceMeasure;
        }
        
        interface PerformanceNavigation {
            redirectCount: number;
            type: number;
            toJSON(): any;
            TYPE_BACK_FORWARD: number;
            TYPE_NAVIGATE: number;
            TYPE_RELOAD: number;
            TYPE_RESERVED: number;
        }
        
        declare var PerformanceNavigation: {
            prototype: PerformanceNavigation;
            new(): PerformanceNavigation;
            TYPE_BACK_FORWARD: number;
            TYPE_NAVIGATE: number;
            TYPE_RELOAD: number;
            TYPE_RESERVED: number;
        }
        
        interface PerformanceNavigationTiming extends PerformanceEntry {
            connectEnd: number;
            connectStart: number;
            domComplete: number;
            domContentLoadedEventEnd: number;
            domContentLoadedEventStart: number;
            domInteractive: number;
            domLoading: number;
            domainLookupEnd: number;
            domainLookupStart: number;
            fetchStart: number;
            loadEventEnd: number;
            loadEventStart: number;
            navigationStart: number;
            redirectCount: number;
            redirectEnd: number;
            redirectStart: number;
            requestStart: number;
            responseEnd: number;
            responseStart: number;
            type: string;
            unloadEventEnd: number;
            unloadEventStart: number;
        }
        
        declare var PerformanceNavigationTiming: {
            prototype: PerformanceNavigationTiming;
            new(): PerformanceNavigationTiming;
        }
        
        interface PerformanceResourceTiming extends PerformanceEntry {
            connectEnd: number;
            connectStart: number;
            domainLookupEnd: number;
            domainLookupStart: number;
            fetchStart: number;
            initiatorType: string;
            redirectEnd: number;
            redirectStart: number;
            requestStart: number;
            responseEnd: number;
            responseStart: number;
        }
        
        declare var PerformanceResourceTiming: {
            prototype: PerformanceResourceTiming;
            new(): PerformanceResourceTiming;
        }
        
        interface PerformanceTiming {
            connectEnd: number;
            connectStart: number;
            domComplete: number;
            domContentLoadedEventEnd: number;
            domContentLoadedEventStart: number;
            domInteractive: number;
            domLoading: number;
            domainLookupEnd: number;
            domainLookupStart: number;
            fetchStart: number;
            loadEventEnd: number;
            loadEventStart: number;
            msFirstPaint: number;
            navigationStart: number;
            redirectEnd: number;
            redirectStart: number;
            requestStart: number;
            responseEnd: number;
            responseStart: number;
            unloadEventEnd: number;
            unloadEventStart: number;
            toJSON(): any;
        }
        
        declare var PerformanceTiming: {
            prototype: PerformanceTiming;
            new(): PerformanceTiming;
        }
        
        interface PeriodicWave {
        }
        
        declare var PeriodicWave: {
            prototype: PeriodicWave;
            new(): PeriodicWave;
        }
        
        interface PermissionRequest extends DeferredPermissionRequest {
            state: string;
            defer(): void;
        }
        
        declare var PermissionRequest: {
            prototype: PermissionRequest;
            new(): PermissionRequest;
        }
        
        interface PermissionRequestedEvent extends Event {
            permissionRequest: PermissionRequest;
        }
        
        declare var PermissionRequestedEvent: {
            prototype: PermissionRequestedEvent;
            new(): PermissionRequestedEvent;
        }
        
        interface Plugin {
            description: string;
            filename: string;
            length: number;
            name: string;
            version: string;
            item(index: number): MimeType;
            namedItem(type: string): MimeType;
            [index: number]: MimeType;
        }
        
        declare var Plugin: {
            prototype: Plugin;
            new(): Plugin;
        }
        
        interface PluginArray {
            length: number;
            item(index: number): Plugin;
            namedItem(name: string): Plugin;
            refresh(reload?: boolean): void;
            [index: number]: Plugin;
        }
        
        declare var PluginArray: {
            prototype: PluginArray;
            new(): PluginArray;
        }
        
        interface PointerEvent extends MouseEvent {
            currentPoint: any;
            height: number;
            hwTimestamp: number;
            intermediatePoints: any;
            isPrimary: boolean;
            pointerId: number;
            pointerType: any;
            pressure: number;
            rotation: number;
            tiltX: number;
            tiltY: number;
            width: number;
            getCurrentPoint(element: Element): void;
            getIntermediatePoints(element: Element): void;
            initPointerEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget, offsetXArg: number, offsetYArg: number, widthArg: number, heightArg: number, pressure: number, rotation: number, tiltX: number, tiltY: number, pointerIdArg: number, pointerType: any, hwTimestampArg: number, isPrimary: boolean): void;
        }
        
        declare var PointerEvent: {
            prototype: PointerEvent;
            new(typeArg: string, eventInitDict?: PointerEventInit): PointerEvent;
        }
        
        interface PopStateEvent extends Event {
            state: any;
            initPopStateEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, stateArg: any): void;
        }
        
        declare var PopStateEvent: {
            prototype: PopStateEvent;
            new(): PopStateEvent;
        }
        
        interface Position {
            coords: Coordinates;
            timestamp: Date;
        }
        
        declare var Position: {
            prototype: Position;
            new(): Position;
        }
        
        interface PositionError {
            code: number;
            message: string;
            toString(): string;
            PERMISSION_DENIED: number;
            POSITION_UNAVAILABLE: number;
            TIMEOUT: number;
        }
        
        declare var PositionError: {
            prototype: PositionError;
            new(): PositionError;
            PERMISSION_DENIED: number;
            POSITION_UNAVAILABLE: number;
            TIMEOUT: number;
        }
        
        interface ProcessingInstruction extends CharacterData {
            target: string;
        }
        
        declare var ProcessingInstruction: {
            prototype: ProcessingInstruction;
            new(): ProcessingInstruction;
        }
        
        interface ProgressEvent extends Event {
            lengthComputable: boolean;
            loaded: number;
            total: number;
            initProgressEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, lengthComputableArg: boolean, loadedArg: number, totalArg: number): void;
        }
        
        declare var ProgressEvent: {
            prototype: ProgressEvent;
            new(): ProgressEvent;
        }
        
        interface Range {
            collapsed: boolean;
            commonAncestorContainer: Node;
            endContainer: Node;
            endOffset: number;
            startContainer: Node;
            startOffset: number;
            cloneContents(): DocumentFragment;
            cloneRange(): Range;
            collapse(toStart: boolean): void;
            compareBoundaryPoints(how: number, sourceRange: Range): number;
            createContextualFragment(fragment: string): DocumentFragment;
            deleteContents(): void;
            detach(): void;
            expand(Unit: string): boolean;
            extractContents(): DocumentFragment;
            getBoundingClientRect(): ClientRect;
            getClientRects(): ClientRectList;
            insertNode(newNode: Node): void;
            selectNode(refNode: Node): void;
            selectNodeContents(refNode: Node): void;
            setEnd(refNode: Node, offset: number): void;
            setEndAfter(refNode: Node): void;
            setEndBefore(refNode: Node): void;
            setStart(refNode: Node, offset: number): void;
            setStartAfter(refNode: Node): void;
            setStartBefore(refNode: Node): void;
            surroundContents(newParent: Node): void;
            toString(): string;
            END_TO_END: number;
            END_TO_START: number;
            START_TO_END: number;
            START_TO_START: number;
        }
        
        declare var Range: {
            prototype: Range;
            new(): Range;
            END_TO_END: number;
            END_TO_START: number;
            START_TO_END: number;
            START_TO_START: number;
        }
        
        interface SVGAElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGURIReference {
            target: SVGAnimatedString;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGAElement: {
            prototype: SVGAElement;
            new(): SVGAElement;
        }
        
        interface SVGAngle {
            unitType: number;
            value: number;
            valueAsString: string;
            valueInSpecifiedUnits: number;
            convertToSpecifiedUnits(unitType: number): void;
            newValueSpecifiedUnits(unitType: number, valueInSpecifiedUnits: number): void;
            SVG_ANGLETYPE_DEG: number;
            SVG_ANGLETYPE_GRAD: number;
            SVG_ANGLETYPE_RAD: number;
            SVG_ANGLETYPE_UNKNOWN: number;
            SVG_ANGLETYPE_UNSPECIFIED: number;
        }
        
        declare var SVGAngle: {
            prototype: SVGAngle;
            new(): SVGAngle;
            SVG_ANGLETYPE_DEG: number;
            SVG_ANGLETYPE_GRAD: number;
            SVG_ANGLETYPE_RAD: number;
            SVG_ANGLETYPE_UNKNOWN: number;
            SVG_ANGLETYPE_UNSPECIFIED: number;
        }
        
        interface SVGAnimatedAngle {
            animVal: SVGAngle;
            baseVal: SVGAngle;
        }
        
        declare var SVGAnimatedAngle: {
            prototype: SVGAnimatedAngle;
            new(): SVGAnimatedAngle;
        }
        
        interface SVGAnimatedBoolean {
            animVal: boolean;
            baseVal: boolean;
        }
        
        declare var SVGAnimatedBoolean: {
            prototype: SVGAnimatedBoolean;
            new(): SVGAnimatedBoolean;
        }
        
        interface SVGAnimatedEnumeration {
            animVal: number;
            baseVal: number;
        }
        
        declare var SVGAnimatedEnumeration: {
            prototype: SVGAnimatedEnumeration;
            new(): SVGAnimatedEnumeration;
        }
        
        interface SVGAnimatedInteger {
            animVal: number;
            baseVal: number;
        }
        
        declare var SVGAnimatedInteger: {
            prototype: SVGAnimatedInteger;
            new(): SVGAnimatedInteger;
        }
        
        interface SVGAnimatedLength {
            animVal: SVGLength;
            baseVal: SVGLength;
        }
        
        declare var SVGAnimatedLength: {
            prototype: SVGAnimatedLength;
            new(): SVGAnimatedLength;
        }
        
        interface SVGAnimatedLengthList {
            animVal: SVGLengthList;
            baseVal: SVGLengthList;
        }
        
        declare var SVGAnimatedLengthList: {
            prototype: SVGAnimatedLengthList;
            new(): SVGAnimatedLengthList;
        }
        
        interface SVGAnimatedNumber {
            animVal: number;
            baseVal: number;
        }
        
        declare var SVGAnimatedNumber: {
            prototype: SVGAnimatedNumber;
            new(): SVGAnimatedNumber;
        }
        
        interface SVGAnimatedNumberList {
            animVal: SVGNumberList;
            baseVal: SVGNumberList;
        }
        
        declare var SVGAnimatedNumberList: {
            prototype: SVGAnimatedNumberList;
            new(): SVGAnimatedNumberList;
        }
        
        interface SVGAnimatedPreserveAspectRatio {
            animVal: SVGPreserveAspectRatio;
            baseVal: SVGPreserveAspectRatio;
        }
        
        declare var SVGAnimatedPreserveAspectRatio: {
            prototype: SVGAnimatedPreserveAspectRatio;
            new(): SVGAnimatedPreserveAspectRatio;
        }
        
        interface SVGAnimatedRect {
            animVal: SVGRect;
            baseVal: SVGRect;
        }
        
        declare var SVGAnimatedRect: {
            prototype: SVGAnimatedRect;
            new(): SVGAnimatedRect;
        }
        
        interface SVGAnimatedString {
            animVal: string;
            baseVal: string;
        }
        
        declare var SVGAnimatedString: {
            prototype: SVGAnimatedString;
            new(): SVGAnimatedString;
        }
        
        interface SVGAnimatedTransformList {
            animVal: SVGTransformList;
            baseVal: SVGTransformList;
        }
        
        declare var SVGAnimatedTransformList: {
            prototype: SVGAnimatedTransformList;
            new(): SVGAnimatedTransformList;
        }
        
        interface SVGCircleElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired {
            cx: SVGAnimatedLength;
            cy: SVGAnimatedLength;
            r: SVGAnimatedLength;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGCircleElement: {
            prototype: SVGCircleElement;
            new(): SVGCircleElement;
        }
        
        interface SVGClipPathElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGUnitTypes {
            clipPathUnits: SVGAnimatedEnumeration;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGClipPathElement: {
            prototype: SVGClipPathElement;
            new(): SVGClipPathElement;
        }
        
        interface SVGComponentTransferFunctionElement extends SVGElement {
            amplitude: SVGAnimatedNumber;
            exponent: SVGAnimatedNumber;
            intercept: SVGAnimatedNumber;
            offset: SVGAnimatedNumber;
            slope: SVGAnimatedNumber;
            tableValues: SVGAnimatedNumberList;
            type: SVGAnimatedEnumeration;
            SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE: number;
            SVG_FECOMPONENTTRANSFER_TYPE_GAMMA: number;
            SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY: number;
            SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: number;
            SVG_FECOMPONENTTRANSFER_TYPE_TABLE: number;
            SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN: number;
        }
        
        declare var SVGComponentTransferFunctionElement: {
            prototype: SVGComponentTransferFunctionElement;
            new(): SVGComponentTransferFunctionElement;
            SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE: number;
            SVG_FECOMPONENTTRANSFER_TYPE_GAMMA: number;
            SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY: number;
            SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: number;
            SVG_FECOMPONENTTRANSFER_TYPE_TABLE: number;
            SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN: number;
        }
        
        interface SVGDefsElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGDefsElement: {
            prototype: SVGDefsElement;
            new(): SVGDefsElement;
        }
        
        interface SVGDescElement extends SVGElement, SVGStylable, SVGLangSpace {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGDescElement: {
            prototype: SVGDescElement;
            new(): SVGDescElement;
        }
        
        interface SVGElement extends Element {
            id: string;
            onclick: (ev: MouseEvent) => any;
            ondblclick: (ev: MouseEvent) => any;
            onfocusin: (ev: FocusEvent) => any;
            onfocusout: (ev: FocusEvent) => any;
            onload: (ev: Event) => any;
            onmousedown: (ev: MouseEvent) => any;
            onmousemove: (ev: MouseEvent) => any;
            onmouseout: (ev: MouseEvent) => any;
            onmouseover: (ev: MouseEvent) => any;
            onmouseup: (ev: MouseEvent) => any;
            ownerSVGElement: SVGSVGElement;
            viewportElement: SVGElement;
            xmlbase: string;
            addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGotPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSLostPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchcancel", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchend", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchmove", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchstart", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGElement: {
            prototype: SVGElement;
            new(): SVGElement;
        }
        
        interface SVGElementInstance extends EventTarget {
            childNodes: SVGElementInstanceList;
            correspondingElement: SVGElement;
            correspondingUseElement: SVGUseElement;
            firstChild: SVGElementInstance;
            lastChild: SVGElementInstance;
            nextSibling: SVGElementInstance;
            parentNode: SVGElementInstance;
            previousSibling: SVGElementInstance;
        }
        
        declare var SVGElementInstance: {
            prototype: SVGElementInstance;
            new(): SVGElementInstance;
        }
        
        interface SVGElementInstanceList {
            length: number;
            item(index: number): SVGElementInstance;
        }
        
        declare var SVGElementInstanceList: {
            prototype: SVGElementInstanceList;
            new(): SVGElementInstanceList;
        }
        
        interface SVGEllipseElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired {
            cx: SVGAnimatedLength;
            cy: SVGAnimatedLength;
            rx: SVGAnimatedLength;
            ry: SVGAnimatedLength;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGEllipseElement: {
            prototype: SVGEllipseElement;
            new(): SVGEllipseElement;
        }
        
        interface SVGFEBlendElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in1: SVGAnimatedString;
            in2: SVGAnimatedString;
            mode: SVGAnimatedEnumeration;
            SVG_FEBLEND_MODE_COLOR: number;
            SVG_FEBLEND_MODE_COLOR_BURN: number;
            SVG_FEBLEND_MODE_COLOR_DODGE: number;
            SVG_FEBLEND_MODE_DARKEN: number;
            SVG_FEBLEND_MODE_DIFFERENCE: number;
            SVG_FEBLEND_MODE_EXCLUSION: number;
            SVG_FEBLEND_MODE_HARD_LIGHT: number;
            SVG_FEBLEND_MODE_HUE: number;
            SVG_FEBLEND_MODE_LIGHTEN: number;
            SVG_FEBLEND_MODE_LUMINOSITY: number;
            SVG_FEBLEND_MODE_MULTIPLY: number;
            SVG_FEBLEND_MODE_NORMAL: number;
            SVG_FEBLEND_MODE_OVERLAY: number;
            SVG_FEBLEND_MODE_SATURATION: number;
            SVG_FEBLEND_MODE_SCREEN: number;
            SVG_FEBLEND_MODE_SOFT_LIGHT: number;
            SVG_FEBLEND_MODE_UNKNOWN: number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFEBlendElement: {
            prototype: SVGFEBlendElement;
            new(): SVGFEBlendElement;
            SVG_FEBLEND_MODE_COLOR: number;
            SVG_FEBLEND_MODE_COLOR_BURN: number;
            SVG_FEBLEND_MODE_COLOR_DODGE: number;
            SVG_FEBLEND_MODE_DARKEN: number;
            SVG_FEBLEND_MODE_DIFFERENCE: number;
            SVG_FEBLEND_MODE_EXCLUSION: number;
            SVG_FEBLEND_MODE_HARD_LIGHT: number;
            SVG_FEBLEND_MODE_HUE: number;
            SVG_FEBLEND_MODE_LIGHTEN: number;
            SVG_FEBLEND_MODE_LUMINOSITY: number;
            SVG_FEBLEND_MODE_MULTIPLY: number;
            SVG_FEBLEND_MODE_NORMAL: number;
            SVG_FEBLEND_MODE_OVERLAY: number;
            SVG_FEBLEND_MODE_SATURATION: number;
            SVG_FEBLEND_MODE_SCREEN: number;
            SVG_FEBLEND_MODE_SOFT_LIGHT: number;
            SVG_FEBLEND_MODE_UNKNOWN: number;
        }
        
        interface SVGFEColorMatrixElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in1: SVGAnimatedString;
            type: SVGAnimatedEnumeration;
            values: SVGAnimatedNumberList;
            SVG_FECOLORMATRIX_TYPE_HUEROTATE: number;
            SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA: number;
            SVG_FECOLORMATRIX_TYPE_MATRIX: number;
            SVG_FECOLORMATRIX_TYPE_SATURATE: number;
            SVG_FECOLORMATRIX_TYPE_UNKNOWN: number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFEColorMatrixElement: {
            prototype: SVGFEColorMatrixElement;
            new(): SVGFEColorMatrixElement;
            SVG_FECOLORMATRIX_TYPE_HUEROTATE: number;
            SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA: number;
            SVG_FECOLORMATRIX_TYPE_MATRIX: number;
            SVG_FECOLORMATRIX_TYPE_SATURATE: number;
            SVG_FECOLORMATRIX_TYPE_UNKNOWN: number;
        }
        
        interface SVGFEComponentTransferElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in1: SVGAnimatedString;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFEComponentTransferElement: {
            prototype: SVGFEComponentTransferElement;
            new(): SVGFEComponentTransferElement;
        }
        
        interface SVGFECompositeElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in1: SVGAnimatedString;
            in2: SVGAnimatedString;
            k1: SVGAnimatedNumber;
            k2: SVGAnimatedNumber;
            k3: SVGAnimatedNumber;
            k4: SVGAnimatedNumber;
            operator: SVGAnimatedEnumeration;
            SVG_FECOMPOSITE_OPERATOR_ARITHMETIC: number;
            SVG_FECOMPOSITE_OPERATOR_ATOP: number;
            SVG_FECOMPOSITE_OPERATOR_IN: number;
            SVG_FECOMPOSITE_OPERATOR_OUT: number;
            SVG_FECOMPOSITE_OPERATOR_OVER: number;
            SVG_FECOMPOSITE_OPERATOR_UNKNOWN: number;
            SVG_FECOMPOSITE_OPERATOR_XOR: number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFECompositeElement: {
            prototype: SVGFECompositeElement;
            new(): SVGFECompositeElement;
            SVG_FECOMPOSITE_OPERATOR_ARITHMETIC: number;
            SVG_FECOMPOSITE_OPERATOR_ATOP: number;
            SVG_FECOMPOSITE_OPERATOR_IN: number;
            SVG_FECOMPOSITE_OPERATOR_OUT: number;
            SVG_FECOMPOSITE_OPERATOR_OVER: number;
            SVG_FECOMPOSITE_OPERATOR_UNKNOWN: number;
            SVG_FECOMPOSITE_OPERATOR_XOR: number;
        }
        
        interface SVGFEConvolveMatrixElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            bias: SVGAnimatedNumber;
            divisor: SVGAnimatedNumber;
            edgeMode: SVGAnimatedEnumeration;
            in1: SVGAnimatedString;
            kernelMatrix: SVGAnimatedNumberList;
            kernelUnitLengthX: SVGAnimatedNumber;
            kernelUnitLengthY: SVGAnimatedNumber;
            orderX: SVGAnimatedInteger;
            orderY: SVGAnimatedInteger;
            preserveAlpha: SVGAnimatedBoolean;
            targetX: SVGAnimatedInteger;
            targetY: SVGAnimatedInteger;
            SVG_EDGEMODE_DUPLICATE: number;
            SVG_EDGEMODE_NONE: number;
            SVG_EDGEMODE_UNKNOWN: number;
            SVG_EDGEMODE_WRAP: number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFEConvolveMatrixElement: {
            prototype: SVGFEConvolveMatrixElement;
            new(): SVGFEConvolveMatrixElement;
            SVG_EDGEMODE_DUPLICATE: number;
            SVG_EDGEMODE_NONE: number;
            SVG_EDGEMODE_UNKNOWN: number;
            SVG_EDGEMODE_WRAP: number;
        }
        
        interface SVGFEDiffuseLightingElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            diffuseConstant: SVGAnimatedNumber;
            in1: SVGAnimatedString;
            kernelUnitLengthX: SVGAnimatedNumber;
            kernelUnitLengthY: SVGAnimatedNumber;
            surfaceScale: SVGAnimatedNumber;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFEDiffuseLightingElement: {
            prototype: SVGFEDiffuseLightingElement;
            new(): SVGFEDiffuseLightingElement;
        }
        
        interface SVGFEDisplacementMapElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in1: SVGAnimatedString;
            in2: SVGAnimatedString;
            scale: SVGAnimatedNumber;
            xChannelSelector: SVGAnimatedEnumeration;
            yChannelSelector: SVGAnimatedEnumeration;
            SVG_CHANNEL_A: number;
            SVG_CHANNEL_B: number;
            SVG_CHANNEL_G: number;
            SVG_CHANNEL_R: number;
            SVG_CHANNEL_UNKNOWN: number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFEDisplacementMapElement: {
            prototype: SVGFEDisplacementMapElement;
            new(): SVGFEDisplacementMapElement;
            SVG_CHANNEL_A: number;
            SVG_CHANNEL_B: number;
            SVG_CHANNEL_G: number;
            SVG_CHANNEL_R: number;
            SVG_CHANNEL_UNKNOWN: number;
        }
        
        interface SVGFEDistantLightElement extends SVGElement {
            azimuth: SVGAnimatedNumber;
            elevation: SVGAnimatedNumber;
        }
        
        declare var SVGFEDistantLightElement: {
            prototype: SVGFEDistantLightElement;
            new(): SVGFEDistantLightElement;
        }
        
        interface SVGFEFloodElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFEFloodElement: {
            prototype: SVGFEFloodElement;
            new(): SVGFEFloodElement;
        }
        
        interface SVGFEFuncAElement extends SVGComponentTransferFunctionElement {
        }
        
        declare var SVGFEFuncAElement: {
            prototype: SVGFEFuncAElement;
            new(): SVGFEFuncAElement;
        }
        
        interface SVGFEFuncBElement extends SVGComponentTransferFunctionElement {
        }
        
        declare var SVGFEFuncBElement: {
            prototype: SVGFEFuncBElement;
            new(): SVGFEFuncBElement;
        }
        
        interface SVGFEFuncGElement extends SVGComponentTransferFunctionElement {
        }
        
        declare var SVGFEFuncGElement: {
            prototype: SVGFEFuncGElement;
            new(): SVGFEFuncGElement;
        }
        
        interface SVGFEFuncRElement extends SVGComponentTransferFunctionElement {
        }
        
        declare var SVGFEFuncRElement: {
            prototype: SVGFEFuncRElement;
            new(): SVGFEFuncRElement;
        }
        
        interface SVGFEGaussianBlurElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in1: SVGAnimatedString;
            stdDeviationX: SVGAnimatedNumber;
            stdDeviationY: SVGAnimatedNumber;
            setStdDeviation(stdDeviationX: number, stdDeviationY: number): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFEGaussianBlurElement: {
            prototype: SVGFEGaussianBlurElement;
            new(): SVGFEGaussianBlurElement;
        }
        
        interface SVGFEImageElement extends SVGElement, SVGFilterPrimitiveStandardAttributes, SVGLangSpace, SVGURIReference, SVGExternalResourcesRequired {
            preserveAspectRatio: SVGAnimatedPreserveAspectRatio;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFEImageElement: {
            prototype: SVGFEImageElement;
            new(): SVGFEImageElement;
        }
        
        interface SVGFEMergeElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFEMergeElement: {
            prototype: SVGFEMergeElement;
            new(): SVGFEMergeElement;
        }
        
        interface SVGFEMergeNodeElement extends SVGElement {
            in1: SVGAnimatedString;
        }
        
        declare var SVGFEMergeNodeElement: {
            prototype: SVGFEMergeNodeElement;
            new(): SVGFEMergeNodeElement;
        }
        
        interface SVGFEMorphologyElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in1: SVGAnimatedString;
            operator: SVGAnimatedEnumeration;
            radiusX: SVGAnimatedNumber;
            radiusY: SVGAnimatedNumber;
            SVG_MORPHOLOGY_OPERATOR_DILATE: number;
            SVG_MORPHOLOGY_OPERATOR_ERODE: number;
            SVG_MORPHOLOGY_OPERATOR_UNKNOWN: number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFEMorphologyElement: {
            prototype: SVGFEMorphologyElement;
            new(): SVGFEMorphologyElement;
            SVG_MORPHOLOGY_OPERATOR_DILATE: number;
            SVG_MORPHOLOGY_OPERATOR_ERODE: number;
            SVG_MORPHOLOGY_OPERATOR_UNKNOWN: number;
        }
        
        interface SVGFEOffsetElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            dx: SVGAnimatedNumber;
            dy: SVGAnimatedNumber;
            in1: SVGAnimatedString;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFEOffsetElement: {
            prototype: SVGFEOffsetElement;
            new(): SVGFEOffsetElement;
        }
        
        interface SVGFEPointLightElement extends SVGElement {
            x: SVGAnimatedNumber;
            y: SVGAnimatedNumber;
            z: SVGAnimatedNumber;
        }
        
        declare var SVGFEPointLightElement: {
            prototype: SVGFEPointLightElement;
            new(): SVGFEPointLightElement;
        }
        
        interface SVGFESpecularLightingElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in1: SVGAnimatedString;
            kernelUnitLengthX: SVGAnimatedNumber;
            kernelUnitLengthY: SVGAnimatedNumber;
            specularConstant: SVGAnimatedNumber;
            specularExponent: SVGAnimatedNumber;
            surfaceScale: SVGAnimatedNumber;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFESpecularLightingElement: {
            prototype: SVGFESpecularLightingElement;
            new(): SVGFESpecularLightingElement;
        }
        
        interface SVGFESpotLightElement extends SVGElement {
            limitingConeAngle: SVGAnimatedNumber;
            pointsAtX: SVGAnimatedNumber;
            pointsAtY: SVGAnimatedNumber;
            pointsAtZ: SVGAnimatedNumber;
            specularExponent: SVGAnimatedNumber;
            x: SVGAnimatedNumber;
            y: SVGAnimatedNumber;
            z: SVGAnimatedNumber;
        }
        
        declare var SVGFESpotLightElement: {
            prototype: SVGFESpotLightElement;
            new(): SVGFESpotLightElement;
        }
        
        interface SVGFETileElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            in1: SVGAnimatedString;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFETileElement: {
            prototype: SVGFETileElement;
            new(): SVGFETileElement;
        }
        
        interface SVGFETurbulenceElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {
            baseFrequencyX: SVGAnimatedNumber;
            baseFrequencyY: SVGAnimatedNumber;
            numOctaves: SVGAnimatedInteger;
            seed: SVGAnimatedNumber;
            stitchTiles: SVGAnimatedEnumeration;
            type: SVGAnimatedEnumeration;
            SVG_STITCHTYPE_NOSTITCH: number;
            SVG_STITCHTYPE_STITCH: number;
            SVG_STITCHTYPE_UNKNOWN: number;
            SVG_TURBULENCE_TYPE_FRACTALNOISE: number;
            SVG_TURBULENCE_TYPE_TURBULENCE: number;
            SVG_TURBULENCE_TYPE_UNKNOWN: number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFETurbulenceElement: {
            prototype: SVGFETurbulenceElement;
            new(): SVGFETurbulenceElement;
            SVG_STITCHTYPE_NOSTITCH: number;
            SVG_STITCHTYPE_STITCH: number;
            SVG_STITCHTYPE_UNKNOWN: number;
            SVG_TURBULENCE_TYPE_FRACTALNOISE: number;
            SVG_TURBULENCE_TYPE_TURBULENCE: number;
            SVG_TURBULENCE_TYPE_UNKNOWN: number;
        }
        
        interface SVGFilterElement extends SVGElement, SVGUnitTypes, SVGStylable, SVGLangSpace, SVGURIReference, SVGExternalResourcesRequired {
            filterResX: SVGAnimatedInteger;
            filterResY: SVGAnimatedInteger;
            filterUnits: SVGAnimatedEnumeration;
            height: SVGAnimatedLength;
            primitiveUnits: SVGAnimatedEnumeration;
            width: SVGAnimatedLength;
            x: SVGAnimatedLength;
            y: SVGAnimatedLength;
            setFilterRes(filterResX: number, filterResY: number): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGFilterElement: {
            prototype: SVGFilterElement;
            new(): SVGFilterElement;
        }
        
        interface SVGForeignObjectElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired {
            height: SVGAnimatedLength;
            width: SVGAnimatedLength;
            x: SVGAnimatedLength;
            y: SVGAnimatedLength;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGForeignObjectElement: {
            prototype: SVGForeignObjectElement;
            new(): SVGForeignObjectElement;
        }
        
        interface SVGGElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGGElement: {
            prototype: SVGGElement;
            new(): SVGGElement;
        }
        
        interface SVGGradientElement extends SVGElement, SVGStylable, SVGExternalResourcesRequired, SVGURIReference, SVGUnitTypes {
            gradientTransform: SVGAnimatedTransformList;
            gradientUnits: SVGAnimatedEnumeration;
            spreadMethod: SVGAnimatedEnumeration;
            SVG_SPREADMETHOD_PAD: number;
            SVG_SPREADMETHOD_REFLECT: number;
            SVG_SPREADMETHOD_REPEAT: number;
            SVG_SPREADMETHOD_UNKNOWN: number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGGradientElement: {
            prototype: SVGGradientElement;
            new(): SVGGradientElement;
            SVG_SPREADMETHOD_PAD: number;
            SVG_SPREADMETHOD_REFLECT: number;
            SVG_SPREADMETHOD_REPEAT: number;
            SVG_SPREADMETHOD_UNKNOWN: number;
        }
        
        interface SVGImageElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGURIReference {
            height: SVGAnimatedLength;
            preserveAspectRatio: SVGAnimatedPreserveAspectRatio;
            width: SVGAnimatedLength;
            x: SVGAnimatedLength;
            y: SVGAnimatedLength;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGImageElement: {
            prototype: SVGImageElement;
            new(): SVGImageElement;
        }
        
        interface SVGLength {
            unitType: number;
            value: number;
            valueAsString: string;
            valueInSpecifiedUnits: number;
            convertToSpecifiedUnits(unitType: number): void;
            newValueSpecifiedUnits(unitType: number, valueInSpecifiedUnits: number): void;
            SVG_LENGTHTYPE_CM: number;
            SVG_LENGTHTYPE_EMS: number;
            SVG_LENGTHTYPE_EXS: number;
            SVG_LENGTHTYPE_IN: number;
            SVG_LENGTHTYPE_MM: number;
            SVG_LENGTHTYPE_NUMBER: number;
            SVG_LENGTHTYPE_PC: number;
            SVG_LENGTHTYPE_PERCENTAGE: number;
            SVG_LENGTHTYPE_PT: number;
            SVG_LENGTHTYPE_PX: number;
            SVG_LENGTHTYPE_UNKNOWN: number;
        }
        
        declare var SVGLength: {
            prototype: SVGLength;
            new(): SVGLength;
            SVG_LENGTHTYPE_CM: number;
            SVG_LENGTHTYPE_EMS: number;
            SVG_LENGTHTYPE_EXS: number;
            SVG_LENGTHTYPE_IN: number;
            SVG_LENGTHTYPE_MM: number;
            SVG_LENGTHTYPE_NUMBER: number;
            SVG_LENGTHTYPE_PC: number;
            SVG_LENGTHTYPE_PERCENTAGE: number;
            SVG_LENGTHTYPE_PT: number;
            SVG_LENGTHTYPE_PX: number;
            SVG_LENGTHTYPE_UNKNOWN: number;
        }
        
        interface SVGLengthList {
            numberOfItems: number;
            appendItem(newItem: SVGLength): SVGLength;
            clear(): void;
            getItem(index: number): SVGLength;
            initialize(newItem: SVGLength): SVGLength;
            insertItemBefore(newItem: SVGLength, index: number): SVGLength;
            removeItem(index: number): SVGLength;
            replaceItem(newItem: SVGLength, index: number): SVGLength;
        }
        
        declare var SVGLengthList: {
            prototype: SVGLengthList;
            new(): SVGLengthList;
        }
        
        interface SVGLineElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired {
            x1: SVGAnimatedLength;
            x2: SVGAnimatedLength;
            y1: SVGAnimatedLength;
            y2: SVGAnimatedLength;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGLineElement: {
            prototype: SVGLineElement;
            new(): SVGLineElement;
        }
        
        interface SVGLinearGradientElement extends SVGGradientElement {
            x1: SVGAnimatedLength;
            x2: SVGAnimatedLength;
            y1: SVGAnimatedLength;
            y2: SVGAnimatedLength;
        }
        
        declare var SVGLinearGradientElement: {
            prototype: SVGLinearGradientElement;
            new(): SVGLinearGradientElement;
        }
        
        interface SVGMarkerElement extends SVGElement, SVGStylable, SVGLangSpace, SVGExternalResourcesRequired, SVGFitToViewBox {
            markerHeight: SVGAnimatedLength;
            markerUnits: SVGAnimatedEnumeration;
            markerWidth: SVGAnimatedLength;
            orientAngle: SVGAnimatedAngle;
            orientType: SVGAnimatedEnumeration;
            refX: SVGAnimatedLength;
            refY: SVGAnimatedLength;
            setOrientToAngle(angle: SVGAngle): void;
            setOrientToAuto(): void;
            SVG_MARKERUNITS_STROKEWIDTH: number;
            SVG_MARKERUNITS_UNKNOWN: number;
            SVG_MARKERUNITS_USERSPACEONUSE: number;
            SVG_MARKER_ORIENT_ANGLE: number;
            SVG_MARKER_ORIENT_AUTO: number;
            SVG_MARKER_ORIENT_UNKNOWN: number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGMarkerElement: {
            prototype: SVGMarkerElement;
            new(): SVGMarkerElement;
            SVG_MARKERUNITS_STROKEWIDTH: number;
            SVG_MARKERUNITS_UNKNOWN: number;
            SVG_MARKERUNITS_USERSPACEONUSE: number;
            SVG_MARKER_ORIENT_ANGLE: number;
            SVG_MARKER_ORIENT_AUTO: number;
            SVG_MARKER_ORIENT_UNKNOWN: number;
        }
        
        interface SVGMaskElement extends SVGElement, SVGStylable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGUnitTypes {
            height: SVGAnimatedLength;
            maskContentUnits: SVGAnimatedEnumeration;
            maskUnits: SVGAnimatedEnumeration;
            width: SVGAnimatedLength;
            x: SVGAnimatedLength;
            y: SVGAnimatedLength;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGMaskElement: {
            prototype: SVGMaskElement;
            new(): SVGMaskElement;
        }
        
        interface SVGMatrix {
            a: number;
            b: number;
            c: number;
            d: number;
            e: number;
            f: number;
            flipX(): SVGMatrix;
            flipY(): SVGMatrix;
            inverse(): SVGMatrix;
            multiply(secondMatrix: SVGMatrix): SVGMatrix;
            rotate(angle: number): SVGMatrix;
            rotateFromVector(x: number, y: number): SVGMatrix;
            scale(scaleFactor: number): SVGMatrix;
            scaleNonUniform(scaleFactorX: number, scaleFactorY: number): SVGMatrix;
            skewX(angle: number): SVGMatrix;
            skewY(angle: number): SVGMatrix;
            translate(x: number, y: number): SVGMatrix;
        }
        
        declare var SVGMatrix: {
            prototype: SVGMatrix;
            new(): SVGMatrix;
        }
        
        interface SVGMetadataElement extends SVGElement {
        }
        
        declare var SVGMetadataElement: {
            prototype: SVGMetadataElement;
            new(): SVGMetadataElement;
        }
        
        interface SVGNumber {
            value: number;
        }
        
        declare var SVGNumber: {
            prototype: SVGNumber;
            new(): SVGNumber;
        }
        
        interface SVGNumberList {
            numberOfItems: number;
            appendItem(newItem: SVGNumber): SVGNumber;
            clear(): void;
            getItem(index: number): SVGNumber;
            initialize(newItem: SVGNumber): SVGNumber;
            insertItemBefore(newItem: SVGNumber, index: number): SVGNumber;
            removeItem(index: number): SVGNumber;
            replaceItem(newItem: SVGNumber, index: number): SVGNumber;
        }
        
        declare var SVGNumberList: {
            prototype: SVGNumberList;
            new(): SVGNumberList;
        }
        
        interface SVGPathElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGAnimatedPathData {
            createSVGPathSegArcAbs(x: number, y: number, r1: number, r2: number, angle: number, largeArcFlag: boolean, sweepFlag: boolean): SVGPathSegArcAbs;
            createSVGPathSegArcRel(x: number, y: number, r1: number, r2: number, angle: number, largeArcFlag: boolean, sweepFlag: boolean): SVGPathSegArcRel;
            createSVGPathSegClosePath(): SVGPathSegClosePath;
            createSVGPathSegCurvetoCubicAbs(x: number, y: number, x1: number, y1: number, x2: number, y2: number): SVGPathSegCurvetoCubicAbs;
            createSVGPathSegCurvetoCubicRel(x: number, y: number, x1: number, y1: number, x2: number, y2: number): SVGPathSegCurvetoCubicRel;
            createSVGPathSegCurvetoCubicSmoothAbs(x: number, y: number, x2: number, y2: number): SVGPathSegCurvetoCubicSmoothAbs;
            createSVGPathSegCurvetoCubicSmoothRel(x: number, y: number, x2: number, y2: number): SVGPathSegCurvetoCubicSmoothRel;
            createSVGPathSegCurvetoQuadraticAbs(x: number, y: number, x1: number, y1: number): SVGPathSegCurvetoQuadraticAbs;
            createSVGPathSegCurvetoQuadraticRel(x: number, y: number, x1: number, y1: number): SVGPathSegCurvetoQuadraticRel;
            createSVGPathSegCurvetoQuadraticSmoothAbs(x: number, y: number): SVGPathSegCurvetoQuadraticSmoothAbs;
            createSVGPathSegCurvetoQuadraticSmoothRel(x: number, y: number): SVGPathSegCurvetoQuadraticSmoothRel;
            createSVGPathSegLinetoAbs(x: number, y: number): SVGPathSegLinetoAbs;
            createSVGPathSegLinetoHorizontalAbs(x: number): SVGPathSegLinetoHorizontalAbs;
            createSVGPathSegLinetoHorizontalRel(x: number): SVGPathSegLinetoHorizontalRel;
            createSVGPathSegLinetoRel(x: number, y: number): SVGPathSegLinetoRel;
            createSVGPathSegLinetoVerticalAbs(y: number): SVGPathSegLinetoVerticalAbs;
            createSVGPathSegLinetoVerticalRel(y: number): SVGPathSegLinetoVerticalRel;
            createSVGPathSegMovetoAbs(x: number, y: number): SVGPathSegMovetoAbs;
            createSVGPathSegMovetoRel(x: number, y: number): SVGPathSegMovetoRel;
            getPathSegAtLength(distance: number): number;
            getPointAtLength(distance: number): SVGPoint;
            getTotalLength(): number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGPathElement: {
            prototype: SVGPathElement;
            new(): SVGPathElement;
        }
        
        interface SVGPathSeg {
            pathSegType: number;
            pathSegTypeAsLetter: string;
            PATHSEG_ARC_ABS: number;
            PATHSEG_ARC_REL: number;
            PATHSEG_CLOSEPATH: number;
            PATHSEG_CURVETO_CUBIC_ABS: number;
            PATHSEG_CURVETO_CUBIC_REL: number;
            PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: number;
            PATHSEG_CURVETO_CUBIC_SMOOTH_REL: number;
            PATHSEG_CURVETO_QUADRATIC_ABS: number;
            PATHSEG_CURVETO_QUADRATIC_REL: number;
            PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: number;
            PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: number;
            PATHSEG_LINETO_ABS: number;
            PATHSEG_LINETO_HORIZONTAL_ABS: number;
            PATHSEG_LINETO_HORIZONTAL_REL: number;
            PATHSEG_LINETO_REL: number;
            PATHSEG_LINETO_VERTICAL_ABS: number;
            PATHSEG_LINETO_VERTICAL_REL: number;
            PATHSEG_MOVETO_ABS: number;
            PATHSEG_MOVETO_REL: number;
            PATHSEG_UNKNOWN: number;
        }
        
        declare var SVGPathSeg: {
            prototype: SVGPathSeg;
            new(): SVGPathSeg;
            PATHSEG_ARC_ABS: number;
            PATHSEG_ARC_REL: number;
            PATHSEG_CLOSEPATH: number;
            PATHSEG_CURVETO_CUBIC_ABS: number;
            PATHSEG_CURVETO_CUBIC_REL: number;
            PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: number;
            PATHSEG_CURVETO_CUBIC_SMOOTH_REL: number;
            PATHSEG_CURVETO_QUADRATIC_ABS: number;
            PATHSEG_CURVETO_QUADRATIC_REL: number;
            PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: number;
            PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: number;
            PATHSEG_LINETO_ABS: number;
            PATHSEG_LINETO_HORIZONTAL_ABS: number;
            PATHSEG_LINETO_HORIZONTAL_REL: number;
            PATHSEG_LINETO_REL: number;
            PATHSEG_LINETO_VERTICAL_ABS: number;
            PATHSEG_LINETO_VERTICAL_REL: number;
            PATHSEG_MOVETO_ABS: number;
            PATHSEG_MOVETO_REL: number;
            PATHSEG_UNKNOWN: number;
        }
        
        interface SVGPathSegArcAbs extends SVGPathSeg {
            angle: number;
            largeArcFlag: boolean;
            r1: number;
            r2: number;
            sweepFlag: boolean;
            x: number;
            y: number;
        }
        
        declare var SVGPathSegArcAbs: {
            prototype: SVGPathSegArcAbs;
            new(): SVGPathSegArcAbs;
        }
        
        interface SVGPathSegArcRel extends SVGPathSeg {
            angle: number;
            largeArcFlag: boolean;
            r1: number;
            r2: number;
            sweepFlag: boolean;
            x: number;
            y: number;
        }
        
        declare var SVGPathSegArcRel: {
            prototype: SVGPathSegArcRel;
            new(): SVGPathSegArcRel;
        }
        
        interface SVGPathSegClosePath extends SVGPathSeg {
        }
        
        declare var SVGPathSegClosePath: {
            prototype: SVGPathSegClosePath;
            new(): SVGPathSegClosePath;
        }
        
        interface SVGPathSegCurvetoCubicAbs extends SVGPathSeg {
            x: number;
            x1: number;
            x2: number;
            y: number;
            y1: number;
            y2: number;
        }
        
        declare var SVGPathSegCurvetoCubicAbs: {
            prototype: SVGPathSegCurvetoCubicAbs;
            new(): SVGPathSegCurvetoCubicAbs;
        }
        
        interface SVGPathSegCurvetoCubicRel extends SVGPathSeg {
            x: number;
            x1: number;
            x2: number;
            y: number;
            y1: number;
            y2: number;
        }
        
        declare var SVGPathSegCurvetoCubicRel: {
            prototype: SVGPathSegCurvetoCubicRel;
            new(): SVGPathSegCurvetoCubicRel;
        }
        
        interface SVGPathSegCurvetoCubicSmoothAbs extends SVGPathSeg {
            x: number;
            x2: number;
            y: number;
            y2: number;
        }
        
        declare var SVGPathSegCurvetoCubicSmoothAbs: {
            prototype: SVGPathSegCurvetoCubicSmoothAbs;
            new(): SVGPathSegCurvetoCubicSmoothAbs;
        }
        
        interface SVGPathSegCurvetoCubicSmoothRel extends SVGPathSeg {
            x: number;
            x2: number;
            y: number;
            y2: number;
        }
        
        declare var SVGPathSegCurvetoCubicSmoothRel: {
            prototype: SVGPathSegCurvetoCubicSmoothRel;
            new(): SVGPathSegCurvetoCubicSmoothRel;
        }
        
        interface SVGPathSegCurvetoQuadraticAbs extends SVGPathSeg {
            x: number;
            x1: number;
            y: number;
            y1: number;
        }
        
        declare var SVGPathSegCurvetoQuadraticAbs: {
            prototype: SVGPathSegCurvetoQuadraticAbs;
            new(): SVGPathSegCurvetoQuadraticAbs;
        }
        
        interface SVGPathSegCurvetoQuadraticRel extends SVGPathSeg {
            x: number;
            x1: number;
            y: number;
            y1: number;
        }
        
        declare var SVGPathSegCurvetoQuadraticRel: {
            prototype: SVGPathSegCurvetoQuadraticRel;
            new(): SVGPathSegCurvetoQuadraticRel;
        }
        
        interface SVGPathSegCurvetoQuadraticSmoothAbs extends SVGPathSeg {
            x: number;
            y: number;
        }
        
        declare var SVGPathSegCurvetoQuadraticSmoothAbs: {
            prototype: SVGPathSegCurvetoQuadraticSmoothAbs;
            new(): SVGPathSegCurvetoQuadraticSmoothAbs;
        }
        
        interface SVGPathSegCurvetoQuadraticSmoothRel extends SVGPathSeg {
            x: number;
            y: number;
        }
        
        declare var SVGPathSegCurvetoQuadraticSmoothRel: {
            prototype: SVGPathSegCurvetoQuadraticSmoothRel;
            new(): SVGPathSegCurvetoQuadraticSmoothRel;
        }
        
        interface SVGPathSegLinetoAbs extends SVGPathSeg {
            x: number;
            y: number;
        }
        
        declare var SVGPathSegLinetoAbs: {
            prototype: SVGPathSegLinetoAbs;
            new(): SVGPathSegLinetoAbs;
        }
        
        interface SVGPathSegLinetoHorizontalAbs extends SVGPathSeg {
            x: number;
        }
        
        declare var SVGPathSegLinetoHorizontalAbs: {
            prototype: SVGPathSegLinetoHorizontalAbs;
            new(): SVGPathSegLinetoHorizontalAbs;
        }
        
        interface SVGPathSegLinetoHorizontalRel extends SVGPathSeg {
            x: number;
        }
        
        declare var SVGPathSegLinetoHorizontalRel: {
            prototype: SVGPathSegLinetoHorizontalRel;
            new(): SVGPathSegLinetoHorizontalRel;
        }
        
        interface SVGPathSegLinetoRel extends SVGPathSeg {
            x: number;
            y: number;
        }
        
        declare var SVGPathSegLinetoRel: {
            prototype: SVGPathSegLinetoRel;
            new(): SVGPathSegLinetoRel;
        }
        
        interface SVGPathSegLinetoVerticalAbs extends SVGPathSeg {
            y: number;
        }
        
        declare var SVGPathSegLinetoVerticalAbs: {
            prototype: SVGPathSegLinetoVerticalAbs;
            new(): SVGPathSegLinetoVerticalAbs;
        }
        
        interface SVGPathSegLinetoVerticalRel extends SVGPathSeg {
            y: number;
        }
        
        declare var SVGPathSegLinetoVerticalRel: {
            prototype: SVGPathSegLinetoVerticalRel;
            new(): SVGPathSegLinetoVerticalRel;
        }
        
        interface SVGPathSegList {
            numberOfItems: number;
            appendItem(newItem: SVGPathSeg): SVGPathSeg;
            clear(): void;
            getItem(index: number): SVGPathSeg;
            initialize(newItem: SVGPathSeg): SVGPathSeg;
            insertItemBefore(newItem: SVGPathSeg, index: number): SVGPathSeg;
            removeItem(index: number): SVGPathSeg;
            replaceItem(newItem: SVGPathSeg, index: number): SVGPathSeg;
        }
        
        declare var SVGPathSegList: {
            prototype: SVGPathSegList;
            new(): SVGPathSegList;
        }
        
        interface SVGPathSegMovetoAbs extends SVGPathSeg {
            x: number;
            y: number;
        }
        
        declare var SVGPathSegMovetoAbs: {
            prototype: SVGPathSegMovetoAbs;
            new(): SVGPathSegMovetoAbs;
        }
        
        interface SVGPathSegMovetoRel extends SVGPathSeg {
            x: number;
            y: number;
        }
        
        declare var SVGPathSegMovetoRel: {
            prototype: SVGPathSegMovetoRel;
            new(): SVGPathSegMovetoRel;
        }
        
        interface SVGPatternElement extends SVGElement, SVGStylable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGFitToViewBox, SVGURIReference, SVGUnitTypes {
            height: SVGAnimatedLength;
            patternContentUnits: SVGAnimatedEnumeration;
            patternTransform: SVGAnimatedTransformList;
            patternUnits: SVGAnimatedEnumeration;
            width: SVGAnimatedLength;
            x: SVGAnimatedLength;
            y: SVGAnimatedLength;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGPatternElement: {
            prototype: SVGPatternElement;
            new(): SVGPatternElement;
        }
        
        interface SVGPoint {
            x: number;
            y: number;
            matrixTransform(matrix: SVGMatrix): SVGPoint;
        }
        
        declare var SVGPoint: {
            prototype: SVGPoint;
            new(): SVGPoint;
        }
        
        interface SVGPointList {
            numberOfItems: number;
            appendItem(newItem: SVGPoint): SVGPoint;
            clear(): void;
            getItem(index: number): SVGPoint;
            initialize(newItem: SVGPoint): SVGPoint;
            insertItemBefore(newItem: SVGPoint, index: number): SVGPoint;
            removeItem(index: number): SVGPoint;
            replaceItem(newItem: SVGPoint, index: number): SVGPoint;
        }
        
        declare var SVGPointList: {
            prototype: SVGPointList;
            new(): SVGPointList;
        }
        
        interface SVGPolygonElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGAnimatedPoints {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGPolygonElement: {
            prototype: SVGPolygonElement;
            new(): SVGPolygonElement;
        }
        
        interface SVGPolylineElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGAnimatedPoints {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGPolylineElement: {
            prototype: SVGPolylineElement;
            new(): SVGPolylineElement;
        }
        
        interface SVGPreserveAspectRatio {
            align: number;
            meetOrSlice: number;
            SVG_MEETORSLICE_MEET: number;
            SVG_MEETORSLICE_SLICE: number;
            SVG_MEETORSLICE_UNKNOWN: number;
            SVG_PRESERVEASPECTRATIO_NONE: number;
            SVG_PRESERVEASPECTRATIO_UNKNOWN: number;
            SVG_PRESERVEASPECTRATIO_XMAXYMAX: number;
            SVG_PRESERVEASPECTRATIO_XMAXYMID: number;
            SVG_PRESERVEASPECTRATIO_XMAXYMIN: number;
            SVG_PRESERVEASPECTRATIO_XMIDYMAX: number;
            SVG_PRESERVEASPECTRATIO_XMIDYMID: number;
            SVG_PRESERVEASPECTRATIO_XMIDYMIN: number;
            SVG_PRESERVEASPECTRATIO_XMINYMAX: number;
            SVG_PRESERVEASPECTRATIO_XMINYMID: number;
            SVG_PRESERVEASPECTRATIO_XMINYMIN: number;
        }
        
        declare var SVGPreserveAspectRatio: {
            prototype: SVGPreserveAspectRatio;
            new(): SVGPreserveAspectRatio;
            SVG_MEETORSLICE_MEET: number;
            SVG_MEETORSLICE_SLICE: number;
            SVG_MEETORSLICE_UNKNOWN: number;
            SVG_PRESERVEASPECTRATIO_NONE: number;
            SVG_PRESERVEASPECTRATIO_UNKNOWN: number;
            SVG_PRESERVEASPECTRATIO_XMAXYMAX: number;
            SVG_PRESERVEASPECTRATIO_XMAXYMID: number;
            SVG_PRESERVEASPECTRATIO_XMAXYMIN: number;
            SVG_PRESERVEASPECTRATIO_XMIDYMAX: number;
            SVG_PRESERVEASPECTRATIO_XMIDYMID: number;
            SVG_PRESERVEASPECTRATIO_XMIDYMIN: number;
            SVG_PRESERVEASPECTRATIO_XMINYMAX: number;
            SVG_PRESERVEASPECTRATIO_XMINYMID: number;
            SVG_PRESERVEASPECTRATIO_XMINYMIN: number;
        }
        
        interface SVGRadialGradientElement extends SVGGradientElement {
            cx: SVGAnimatedLength;
            cy: SVGAnimatedLength;
            fx: SVGAnimatedLength;
            fy: SVGAnimatedLength;
            r: SVGAnimatedLength;
        }
        
        declare var SVGRadialGradientElement: {
            prototype: SVGRadialGradientElement;
            new(): SVGRadialGradientElement;
        }
        
        interface SVGRect {
            height: number;
            width: number;
            x: number;
            y: number;
        }
        
        declare var SVGRect: {
            prototype: SVGRect;
            new(): SVGRect;
        }
        
        interface SVGRectElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired {
            height: SVGAnimatedLength;
            rx: SVGAnimatedLength;
            ry: SVGAnimatedLength;
            width: SVGAnimatedLength;
            x: SVGAnimatedLength;
            y: SVGAnimatedLength;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGRectElement: {
            prototype: SVGRectElement;
            new(): SVGRectElement;
        }
        
        interface SVGSVGElement extends SVGElement, DocumentEvent, SVGLocatable, SVGTests, SVGStylable, SVGLangSpace, SVGExternalResourcesRequired, SVGFitToViewBox, SVGZoomAndPan {
            contentScriptType: string;
            contentStyleType: string;
            currentScale: number;
            currentTranslate: SVGPoint;
            height: SVGAnimatedLength;
            onabort: (ev: Event) => any;
            onerror: (ev: Event) => any;
            onresize: (ev: UIEvent) => any;
            onscroll: (ev: UIEvent) => any;
            onunload: (ev: Event) => any;
            onzoom: (ev: SVGZoomEvent) => any;
            pixelUnitToMillimeterX: number;
            pixelUnitToMillimeterY: number;
            screenPixelToMillimeterX: number;
            screenPixelToMillimeterY: number;
            viewport: SVGRect;
            width: SVGAnimatedLength;
            x: SVGAnimatedLength;
            y: SVGAnimatedLength;
            checkEnclosure(element: SVGElement, rect: SVGRect): boolean;
            checkIntersection(element: SVGElement, rect: SVGRect): boolean;
            createSVGAngle(): SVGAngle;
            createSVGLength(): SVGLength;
            createSVGMatrix(): SVGMatrix;
            createSVGNumber(): SVGNumber;
            createSVGPoint(): SVGPoint;
            createSVGRect(): SVGRect;
            createSVGTransform(): SVGTransform;
            createSVGTransformFromMatrix(matrix: SVGMatrix): SVGTransform;
            deselectAll(): void;
            forceRedraw(): void;
            getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration;
            getCurrentTime(): number;
            getElementById(elementId: string): Element;
            getEnclosureList(rect: SVGRect, referenceElement: SVGElement): NodeList;
            getIntersectionList(rect: SVGRect, referenceElement: SVGElement): NodeList;
            pauseAnimations(): void;
            setCurrentTime(seconds: number): void;
            suspendRedraw(maxWaitMilliseconds: number): number;
            unpauseAnimations(): void;
            unsuspendRedraw(suspendHandleID: number): void;
            unsuspendRedrawAll(): void;
            addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGotPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSLostPointerCapture", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "SVGAbort", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "SVGError", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "SVGUnload", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "SVGZoom", listener: (ev: SVGZoomEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusin", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "focusout", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "lostpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchcancel", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchend", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchmove", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "touchstart", listener: (ev: TouchEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "webkitfullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGSVGElement: {
            prototype: SVGSVGElement;
            new(): SVGSVGElement;
        }
        
        interface SVGScriptElement extends SVGElement, SVGExternalResourcesRequired, SVGURIReference {
            type: string;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGScriptElement: {
            prototype: SVGScriptElement;
            new(): SVGScriptElement;
        }
        
        interface SVGStopElement extends SVGElement, SVGStylable {
            offset: SVGAnimatedNumber;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGStopElement: {
            prototype: SVGStopElement;
            new(): SVGStopElement;
        }
        
        interface SVGStringList {
            numberOfItems: number;
            appendItem(newItem: string): string;
            clear(): void;
            getItem(index: number): string;
            initialize(newItem: string): string;
            insertItemBefore(newItem: string, index: number): string;
            removeItem(index: number): string;
            replaceItem(newItem: string, index: number): string;
        }
        
        declare var SVGStringList: {
            prototype: SVGStringList;
            new(): SVGStringList;
        }
        
        interface SVGStyleElement extends SVGElement, SVGLangSpace {
            media: string;
            title: string;
            type: string;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGStyleElement: {
            prototype: SVGStyleElement;
            new(): SVGStyleElement;
        }
        
        interface SVGSwitchElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGSwitchElement: {
            prototype: SVGSwitchElement;
            new(): SVGSwitchElement;
        }
        
        interface SVGSymbolElement extends SVGElement, SVGStylable, SVGLangSpace, SVGExternalResourcesRequired, SVGFitToViewBox {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGSymbolElement: {
            prototype: SVGSymbolElement;
            new(): SVGSymbolElement;
        }
        
        interface SVGTSpanElement extends SVGTextPositioningElement {
        }
        
        declare var SVGTSpanElement: {
            prototype: SVGTSpanElement;
            new(): SVGTSpanElement;
        }
        
        interface SVGTextContentElement extends SVGElement, SVGStylable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired {
            lengthAdjust: SVGAnimatedEnumeration;
            textLength: SVGAnimatedLength;
            getCharNumAtPosition(point: SVGPoint): number;
            getComputedTextLength(): number;
            getEndPositionOfChar(charnum: number): SVGPoint;
            getExtentOfChar(charnum: number): SVGRect;
            getNumberOfChars(): number;
            getRotationOfChar(charnum: number): number;
            getStartPositionOfChar(charnum: number): SVGPoint;
            getSubStringLength(charnum: number, nchars: number): number;
            selectSubString(charnum: number, nchars: number): void;
            LENGTHADJUST_SPACING: number;
            LENGTHADJUST_SPACINGANDGLYPHS: number;
            LENGTHADJUST_UNKNOWN: number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGTextContentElement: {
            prototype: SVGTextContentElement;
            new(): SVGTextContentElement;
            LENGTHADJUST_SPACING: number;
            LENGTHADJUST_SPACINGANDGLYPHS: number;
            LENGTHADJUST_UNKNOWN: number;
        }
        
        interface SVGTextElement extends SVGTextPositioningElement, SVGTransformable {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGTextElement: {
            prototype: SVGTextElement;
            new(): SVGTextElement;
        }
        
        interface SVGTextPathElement extends SVGTextContentElement, SVGURIReference {
            method: SVGAnimatedEnumeration;
            spacing: SVGAnimatedEnumeration;
            startOffset: SVGAnimatedLength;
            TEXTPATH_METHODTYPE_ALIGN: number;
            TEXTPATH_METHODTYPE_STRETCH: number;
            TEXTPATH_METHODTYPE_UNKNOWN: number;
            TEXTPATH_SPACINGTYPE_AUTO: number;
            TEXTPATH_SPACINGTYPE_EXACT: number;
            TEXTPATH_SPACINGTYPE_UNKNOWN: number;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGTextPathElement: {
            prototype: SVGTextPathElement;
            new(): SVGTextPathElement;
            TEXTPATH_METHODTYPE_ALIGN: number;
            TEXTPATH_METHODTYPE_STRETCH: number;
            TEXTPATH_METHODTYPE_UNKNOWN: number;
            TEXTPATH_SPACINGTYPE_AUTO: number;
            TEXTPATH_SPACINGTYPE_EXACT: number;
            TEXTPATH_SPACINGTYPE_UNKNOWN: number;
        }
        
        interface SVGTextPositioningElement extends SVGTextContentElement {
            dx: SVGAnimatedLengthList;
            dy: SVGAnimatedLengthList;
            rotate: SVGAnimatedNumberList;
            x: SVGAnimatedLengthList;
            y: SVGAnimatedLengthList;
        }
        
        declare var SVGTextPositioningElement: {
            prototype: SVGTextPositioningElement;
            new(): SVGTextPositioningElement;
        }
        
        interface SVGTitleElement extends SVGElement, SVGStylable, SVGLangSpace {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGTitleElement: {
            prototype: SVGTitleElement;
            new(): SVGTitleElement;
        }
        
        interface SVGTransform {
            angle: number;
            matrix: SVGMatrix;
            type: number;
            setMatrix(matrix: SVGMatrix): void;
            setRotate(angle: number, cx: number, cy: number): void;
            setScale(sx: number, sy: number): void;
            setSkewX(angle: number): void;
            setSkewY(angle: number): void;
            setTranslate(tx: number, ty: number): void;
            SVG_TRANSFORM_MATRIX: number;
            SVG_TRANSFORM_ROTATE: number;
            SVG_TRANSFORM_SCALE: number;
            SVG_TRANSFORM_SKEWX: number;
            SVG_TRANSFORM_SKEWY: number;
            SVG_TRANSFORM_TRANSLATE: number;
            SVG_TRANSFORM_UNKNOWN: number;
        }
        
        declare var SVGTransform: {
            prototype: SVGTransform;
            new(): SVGTransform;
            SVG_TRANSFORM_MATRIX: number;
            SVG_TRANSFORM_ROTATE: number;
            SVG_TRANSFORM_SCALE: number;
            SVG_TRANSFORM_SKEWX: number;
            SVG_TRANSFORM_SKEWY: number;
            SVG_TRANSFORM_TRANSLATE: number;
            SVG_TRANSFORM_UNKNOWN: number;
        }
        
        interface SVGTransformList {
            numberOfItems: number;
            appendItem(newItem: SVGTransform): SVGTransform;
            clear(): void;
            consolidate(): SVGTransform;
            createSVGTransformFromMatrix(matrix: SVGMatrix): SVGTransform;
            getItem(index: number): SVGTransform;
            initialize(newItem: SVGTransform): SVGTransform;
            insertItemBefore(newItem: SVGTransform, index: number): SVGTransform;
            removeItem(index: number): SVGTransform;
            replaceItem(newItem: SVGTransform, index: number): SVGTransform;
        }
        
        declare var SVGTransformList: {
            prototype: SVGTransformList;
            new(): SVGTransformList;
        }
        
        interface SVGUnitTypes {
            SVG_UNIT_TYPE_OBJECTBOUNDINGBOX: number;
            SVG_UNIT_TYPE_UNKNOWN: number;
            SVG_UNIT_TYPE_USERSPACEONUSE: number;
        }
        declare var SVGUnitTypes: SVGUnitTypes;
        
        interface SVGUseElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGURIReference {
            animatedInstanceRoot: SVGElementInstance;
            height: SVGAnimatedLength;
            instanceRoot: SVGElementInstance;
            width: SVGAnimatedLength;
            x: SVGAnimatedLength;
            y: SVGAnimatedLength;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGUseElement: {
            prototype: SVGUseElement;
            new(): SVGUseElement;
        }
        
        interface SVGViewElement extends SVGElement, SVGExternalResourcesRequired, SVGFitToViewBox, SVGZoomAndPan {
            viewTarget: SVGStringList;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var SVGViewElement: {
            prototype: SVGViewElement;
            new(): SVGViewElement;
        }
        
        interface SVGZoomAndPan {
            SVG_ZOOMANDPAN_DISABLE: number;
            SVG_ZOOMANDPAN_MAGNIFY: number;
            SVG_ZOOMANDPAN_UNKNOWN: number;
        }
        declare var SVGZoomAndPan: SVGZoomAndPan;
        
        interface SVGZoomEvent extends UIEvent {
            newScale: number;
            newTranslate: SVGPoint;
            previousScale: number;
            previousTranslate: SVGPoint;
            zoomRectScreen: SVGRect;
        }
        
        declare var SVGZoomEvent: {
            prototype: SVGZoomEvent;
            new(): SVGZoomEvent;
        }
        
        interface Screen extends EventTarget {
            availHeight: number;
            availWidth: number;
            bufferDepth: number;
            colorDepth: number;
            deviceXDPI: number;
            deviceYDPI: number;
            fontSmoothingEnabled: boolean;
            height: number;
            logicalXDPI: number;
            logicalYDPI: number;
            msOrientation: string;
            onmsorientationchange: (ev: Event) => any;
            pixelDepth: number;
            systemXDPI: number;
            systemYDPI: number;
            width: number;
            msLockOrientation(orientations: string): boolean;
            msLockOrientation(orientations: string[]): boolean;
            msUnlockOrientation(): void;
            addEventListener(type: "MSOrientationChange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var Screen: {
            prototype: Screen;
            new(): Screen;
        }
        
        interface ScriptNotifyEvent extends Event {
            callingUri: string;
            value: string;
        }
        
        declare var ScriptNotifyEvent: {
            prototype: ScriptNotifyEvent;
            new(): ScriptNotifyEvent;
        }
        
        interface ScriptProcessorNode extends AudioNode {
            bufferSize: number;
            onaudioprocess: (ev: AudioProcessingEvent) => any;
            addEventListener(type: "audioprocess", listener: (ev: AudioProcessingEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var ScriptProcessorNode: {
            prototype: ScriptProcessorNode;
            new(): ScriptProcessorNode;
        }
        
        interface Selection {
            anchorNode: Node;
            anchorOffset: number;
            focusNode: Node;
            focusOffset: number;
            isCollapsed: boolean;
            rangeCount: number;
            type: string;
            addRange(range: Range): void;
            collapse(parentNode: Node, offset: number): void;
            collapseToEnd(): void;
            collapseToStart(): void;
            containsNode(node: Node, partlyContained: boolean): boolean;
            deleteFromDocument(): void;
            empty(): void;
            extend(newNode: Node, offset: number): void;
            getRangeAt(index: number): Range;
            removeAllRanges(): void;
            removeRange(range: Range): void;
            selectAllChildren(parentNode: Node): void;
            setBaseAndExtent(baseNode: Node, baseOffset: number, extentNode: Node, extentOffset: number): void;
            toString(): string;
        }
        
        declare var Selection: {
            prototype: Selection;
            new(): Selection;
        }
        
        interface SourceBuffer extends EventTarget {
            appendWindowEnd: number;
            appendWindowStart: number;
            audioTracks: AudioTrackList;
            buffered: TimeRanges;
            mode: string;
            timestampOffset: number;
            updating: boolean;
            videoTracks: VideoTrackList;
            abort(): void;
            appendBuffer(data: ArrayBuffer): void;
            appendBuffer(data: ArrayBufferView): void;
            appendStream(stream: MSStream, maxSize?: number): void;
            remove(start: number, end: number): void;
        }
        
        declare var SourceBuffer: {
            prototype: SourceBuffer;
            new(): SourceBuffer;
        }
        
        interface SourceBufferList extends EventTarget {
            length: number;
            item(index: number): SourceBuffer;
            [index: number]: SourceBuffer;
        }
        
        declare var SourceBufferList: {
            prototype: SourceBufferList;
            new(): SourceBufferList;
        }
        
        interface StereoPannerNode extends AudioNode {
            pan: AudioParam;
        }
        
        declare var StereoPannerNode: {
            prototype: StereoPannerNode;
            new(): StereoPannerNode;
        }
        
        interface Storage {
            length: number;
            clear(): void;
            getItem(key: string): any;
            key(index: number): string;
            removeItem(key: string): void;
            setItem(key: string, data: string): void;
            [key: string]: any;
            [index: number]: string;
        }
        
        declare var Storage: {
            prototype: Storage;
            new(): Storage;
        }
        
        interface StorageEvent extends Event {
            key: string;
            newValue: any;
            oldValue: any;
            storageArea: Storage;
            url: string;
            initStorageEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, keyArg: string, oldValueArg: any, newValueArg: any, urlArg: string, storageAreaArg: Storage): void;
        }
        
        declare var StorageEvent: {
            prototype: StorageEvent;
            new(): StorageEvent;
        }
        
        interface StyleMedia {
            type: string;
            matchMedium(mediaquery: string): boolean;
        }
        
        declare var StyleMedia: {
            prototype: StyleMedia;
            new(): StyleMedia;
        }
        
        interface StyleSheet {
            disabled: boolean;
            href: string;
            media: MediaList;
            ownerNode: Node;
            parentStyleSheet: StyleSheet;
            title: string;
            type: string;
        }
        
        declare var StyleSheet: {
            prototype: StyleSheet;
            new(): StyleSheet;
        }
        
        interface StyleSheetList {
            length: number;
            item(index?: number): StyleSheet;
            [index: number]: StyleSheet;
        }
        
        declare var StyleSheetList: {
            prototype: StyleSheetList;
            new(): StyleSheetList;
        }
        
        interface StyleSheetPageList {
            length: number;
            item(index: number): CSSPageRule;
            [index: number]: CSSPageRule;
        }
        
        declare var StyleSheetPageList: {
            prototype: StyleSheetPageList;
            new(): StyleSheetPageList;
        }
        
        interface SubtleCrypto {
            decrypt(algorithm: string, key: CryptoKey, data: ArrayBufferView): any;
            decrypt(algorithm: Algorithm, key: CryptoKey, data: ArrayBufferView): any;
            deriveBits(algorithm: string, baseKey: CryptoKey, length: number): any;
            deriveBits(algorithm: Algorithm, baseKey: CryptoKey, length: number): any;
            deriveKey(algorithm: string, baseKey: CryptoKey, derivedKeyType: string, extractable: boolean, keyUsages: string[]): any;
            deriveKey(algorithm: string, baseKey: CryptoKey, derivedKeyType: Algorithm, extractable: boolean, keyUsages: string[]): any;
            deriveKey(algorithm: Algorithm, baseKey: CryptoKey, derivedKeyType: string, extractable: boolean, keyUsages: string[]): any;
            deriveKey(algorithm: Algorithm, baseKey: CryptoKey, derivedKeyType: Algorithm, extractable: boolean, keyUsages: string[]): any;
            digest(algorithm: string, data: ArrayBufferView): any;
            digest(algorithm: Algorithm, data: ArrayBufferView): any;
            encrypt(algorithm: string, key: CryptoKey, data: ArrayBufferView): any;
            encrypt(algorithm: Algorithm, key: CryptoKey, data: ArrayBufferView): any;
            exportKey(format: string, key: CryptoKey): any;
            generateKey(algorithm: string, extractable: boolean, keyUsages: string[]): any;
            generateKey(algorithm: Algorithm, extractable: boolean, keyUsages: string[]): any;
            importKey(format: string, keyData: ArrayBufferView, algorithm: string, extractable: boolean, keyUsages: string[]): any;
            importKey(format: string, keyData: ArrayBufferView, algorithm: Algorithm, extractable: boolean, keyUsages: string[]): any;
            sign(algorithm: string, key: CryptoKey, data: ArrayBufferView): any;
            sign(algorithm: Algorithm, key: CryptoKey, data: ArrayBufferView): any;
            unwrapKey(format: string, wrappedKey: ArrayBufferView, unwrappingKey: CryptoKey, unwrapAlgorithm: string, unwrappedKeyAlgorithm: string, extractable: boolean, keyUsages: string[]): any;
            unwrapKey(format: string, wrappedKey: ArrayBufferView, unwrappingKey: CryptoKey, unwrapAlgorithm: string, unwrappedKeyAlgorithm: Algorithm, extractable: boolean, keyUsages: string[]): any;
            unwrapKey(format: string, wrappedKey: ArrayBufferView, unwrappingKey: CryptoKey, unwrapAlgorithm: Algorithm, unwrappedKeyAlgorithm: string, extractable: boolean, keyUsages: string[]): any;
            unwrapKey(format: string, wrappedKey: ArrayBufferView, unwrappingKey: CryptoKey, unwrapAlgorithm: Algorithm, unwrappedKeyAlgorithm: Algorithm, extractable: boolean, keyUsages: string[]): any;
            verify(algorithm: string, key: CryptoKey, signature: ArrayBufferView, data: ArrayBufferView): any;
            verify(algorithm: Algorithm, key: CryptoKey, signature: ArrayBufferView, data: ArrayBufferView): any;
            wrapKey(format: string, key: CryptoKey, wrappingKey: CryptoKey, wrapAlgorithm: string): any;
            wrapKey(format: string, key: CryptoKey, wrappingKey: CryptoKey, wrapAlgorithm: Algorithm): any;
        }
        
        declare var SubtleCrypto: {
            prototype: SubtleCrypto;
            new(): SubtleCrypto;
        }
        
        interface Text extends CharacterData {
            wholeText: string;
            replaceWholeText(content: string): Text;
            splitText(offset: number): Text;
        }
        
        declare var Text: {
            prototype: Text;
            new(): Text;
        }
        
        interface TextEvent extends UIEvent {
            data: string;
            inputMethod: number;
            locale: string;
            initTextEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, dataArg: string, inputMethod: number, locale: string): void;
            DOM_INPUT_METHOD_DROP: number;
            DOM_INPUT_METHOD_HANDWRITING: number;
            DOM_INPUT_METHOD_IME: number;
            DOM_INPUT_METHOD_KEYBOARD: number;
            DOM_INPUT_METHOD_MULTIMODAL: number;
            DOM_INPUT_METHOD_OPTION: number;
            DOM_INPUT_METHOD_PASTE: number;
            DOM_INPUT_METHOD_SCRIPT: number;
            DOM_INPUT_METHOD_UNKNOWN: number;
            DOM_INPUT_METHOD_VOICE: number;
        }
        
        declare var TextEvent: {
            prototype: TextEvent;
            new(): TextEvent;
            DOM_INPUT_METHOD_DROP: number;
            DOM_INPUT_METHOD_HANDWRITING: number;
            DOM_INPUT_METHOD_IME: number;
            DOM_INPUT_METHOD_KEYBOARD: number;
            DOM_INPUT_METHOD_MULTIMODAL: number;
            DOM_INPUT_METHOD_OPTION: number;
            DOM_INPUT_METHOD_PASTE: number;
            DOM_INPUT_METHOD_SCRIPT: number;
            DOM_INPUT_METHOD_UNKNOWN: number;
            DOM_INPUT_METHOD_VOICE: number;
        }
        
        interface TextMetrics {
            width: number;
        }
        
        declare var TextMetrics: {
            prototype: TextMetrics;
            new(): TextMetrics;
        }
        
        interface TextRange {
            boundingHeight: number;
            boundingLeft: number;
            boundingTop: number;
            boundingWidth: number;
            htmlText: string;
            offsetLeft: number;
            offsetTop: number;
            text: string;
            collapse(start?: boolean): void;
            compareEndPoints(how: string, sourceRange: TextRange): number;
            duplicate(): TextRange;
            execCommand(cmdID: string, showUI?: boolean, value?: any): boolean;
            execCommandShowHelp(cmdID: string): boolean;
            expand(Unit: string): boolean;
            findText(string: string, count?: number, flags?: number): boolean;
            getBookmark(): string;
            getBoundingClientRect(): ClientRect;
            getClientRects(): ClientRectList;
            inRange(range: TextRange): boolean;
            isEqual(range: TextRange): boolean;
            move(unit: string, count?: number): number;
            moveEnd(unit: string, count?: number): number;
            moveStart(unit: string, count?: number): number;
            moveToBookmark(bookmark: string): boolean;
            moveToElementText(element: Element): void;
            moveToPoint(x: number, y: number): void;
            parentElement(): Element;
            pasteHTML(html: string): void;
            queryCommandEnabled(cmdID: string): boolean;
            queryCommandIndeterm(cmdID: string): boolean;
            queryCommandState(cmdID: string): boolean;
            queryCommandSupported(cmdID: string): boolean;
            queryCommandText(cmdID: string): string;
            queryCommandValue(cmdID: string): any;
            scrollIntoView(fStart?: boolean): void;
            select(): void;
            setEndPoint(how: string, SourceRange: TextRange): void;
        }
        
        declare var TextRange: {
            prototype: TextRange;
            new(): TextRange;
        }
        
        interface TextRangeCollection {
            length: number;
            item(index: number): TextRange;
            [index: number]: TextRange;
        }
        
        declare var TextRangeCollection: {
            prototype: TextRangeCollection;
            new(): TextRangeCollection;
        }
        
        interface TextTrack extends EventTarget {
            activeCues: TextTrackCueList;
            cues: TextTrackCueList;
            inBandMetadataTrackDispatchType: string;
            kind: string;
            label: string;
            language: string;
            mode: any;
            oncuechange: (ev: Event) => any;
            onerror: (ev: Event) => any;
            onload: (ev: Event) => any;
            readyState: number;
            addCue(cue: TextTrackCue): void;
            removeCue(cue: TextTrackCue): void;
            DISABLED: number;
            ERROR: number;
            HIDDEN: number;
            LOADED: number;
            LOADING: number;
            NONE: number;
            SHOWING: number;
            addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var TextTrack: {
            prototype: TextTrack;
            new(): TextTrack;
            DISABLED: number;
            ERROR: number;
            HIDDEN: number;
            LOADED: number;
            LOADING: number;
            NONE: number;
            SHOWING: number;
        }
        
        interface TextTrackCue extends EventTarget {
            endTime: number;
            id: string;
            onenter: (ev: Event) => any;
            onexit: (ev: Event) => any;
            pauseOnExit: boolean;
            startTime: number;
            text: string;
            track: TextTrack;
            getCueAsHTML(): DocumentFragment;
            addEventListener(type: "enter", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "exit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var TextTrackCue: {
            prototype: TextTrackCue;
            new(startTime: number, endTime: number, text: string): TextTrackCue;
        }
        
        interface TextTrackCueList {
            length: number;
            getCueById(id: string): TextTrackCue;
            item(index: number): TextTrackCue;
            [index: number]: TextTrackCue;
        }
        
        declare var TextTrackCueList: {
            prototype: TextTrackCueList;
            new(): TextTrackCueList;
        }
        
        interface TextTrackList extends EventTarget {
            length: number;
            onaddtrack: (ev: TrackEvent) => any;
            item(index: number): TextTrack;
            addEventListener(type: "addtrack", listener: (ev: TrackEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
            [index: number]: TextTrack;
        }
        
        declare var TextTrackList: {
            prototype: TextTrackList;
            new(): TextTrackList;
        }
        
        interface TimeRanges {
            length: number;
            end(index: number): number;
            start(index: number): number;
        }
        
        declare var TimeRanges: {
            prototype: TimeRanges;
            new(): TimeRanges;
        }
        
        interface Touch {
            clientX: number;
            clientY: number;
            identifier: number;
            pageX: number;
            pageY: number;
            screenX: number;
            screenY: number;
            target: EventTarget;
        }
        
        declare var Touch: {
            prototype: Touch;
            new(): Touch;
        }
        
        interface TouchEvent extends UIEvent {
            altKey: boolean;
            changedTouches: TouchList;
            ctrlKey: boolean;
            metaKey: boolean;
            shiftKey: boolean;
            targetTouches: TouchList;
            touches: TouchList;
        }
        
        declare var TouchEvent: {
            prototype: TouchEvent;
            new(): TouchEvent;
        }
        
        interface TouchList {
            length: number;
            item(index: number): Touch;
            [index: number]: Touch;
        }
        
        declare var TouchList: {
            prototype: TouchList;
            new(): TouchList;
        }
        
        interface TrackEvent extends Event {
            track: any;
        }
        
        declare var TrackEvent: {
            prototype: TrackEvent;
            new(): TrackEvent;
        }
        
        interface TransitionEvent extends Event {
            elapsedTime: number;
            propertyName: string;
            initTransitionEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, propertyNameArg: string, elapsedTimeArg: number): void;
        }
        
        declare var TransitionEvent: {
            prototype: TransitionEvent;
            new(): TransitionEvent;
        }
        
        interface TreeWalker {
            currentNode: Node;
            expandEntityReferences: boolean;
            filter: NodeFilter;
            root: Node;
            whatToShow: number;
            firstChild(): Node;
            lastChild(): Node;
            nextNode(): Node;
            nextSibling(): Node;
            parentNode(): Node;
            previousNode(): Node;
            previousSibling(): Node;
        }
        
        declare var TreeWalker: {
            prototype: TreeWalker;
            new(): TreeWalker;
        }
        
        interface UIEvent extends Event {
            detail: number;
            view: Window;
            initUIEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number): void;
        }
        
        declare var UIEvent: {
            prototype: UIEvent;
            new(type: string, eventInitDict?: UIEventInit): UIEvent;
        }
        
        interface URL {
            createObjectURL(object: any, options?: ObjectURLOptions): string;
            revokeObjectURL(url: string): void;
        }
        declare var URL: URL;
        
        interface UnviewableContentIdentifiedEvent extends NavigationEventWithReferrer {
            mediaType: string;
        }
        
        declare var UnviewableContentIdentifiedEvent: {
            prototype: UnviewableContentIdentifiedEvent;
            new(): UnviewableContentIdentifiedEvent;
        }
        
        interface ValidityState {
            badInput: boolean;
            customError: boolean;
            patternMismatch: boolean;
            rangeOverflow: boolean;
            rangeUnderflow: boolean;
            stepMismatch: boolean;
            tooLong: boolean;
            typeMismatch: boolean;
            valid: boolean;
            valueMissing: boolean;
        }
        
        declare var ValidityState: {
            prototype: ValidityState;
            new(): ValidityState;
        }
        
        interface VideoPlaybackQuality {
            corruptedVideoFrames: number;
            creationTime: number;
            droppedVideoFrames: number;
            totalFrameDelay: number;
            totalVideoFrames: number;
        }
        
        declare var VideoPlaybackQuality: {
            prototype: VideoPlaybackQuality;
            new(): VideoPlaybackQuality;
        }
        
        interface VideoTrack {
            id: string;
            kind: string;
            label: string;
            language: string;
            selected: boolean;
            sourceBuffer: SourceBuffer;
        }
        
        declare var VideoTrack: {
            prototype: VideoTrack;
            new(): VideoTrack;
        }
        
        interface VideoTrackList extends EventTarget {
            length: number;
            onaddtrack: (ev: TrackEvent) => any;
            onchange: (ev: Event) => any;
            onremovetrack: (ev: TrackEvent) => any;
            selectedIndex: number;
            getTrackById(id: string): VideoTrack;
            item(index: number): VideoTrack;
            addEventListener(type: "addtrack", listener: (ev: TrackEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "removetrack", listener: (ev: TrackEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
            [index: number]: VideoTrack;
        }
        
        declare var VideoTrackList: {
            prototype: VideoTrackList;
            new(): VideoTrackList;
        }
        
        interface WEBGL_compressed_texture_s3tc {
            COMPRESSED_RGBA_S3TC_DXT1_EXT: number;
            COMPRESSED_RGBA_S3TC_DXT3_EXT: number;
            COMPRESSED_RGBA_S3TC_DXT5_EXT: number;
            COMPRESSED_RGB_S3TC_DXT1_EXT: number;
        }
        
        declare var WEBGL_compressed_texture_s3tc: {
            prototype: WEBGL_compressed_texture_s3tc;
            new(): WEBGL_compressed_texture_s3tc;
            COMPRESSED_RGBA_S3TC_DXT1_EXT: number;
            COMPRESSED_RGBA_S3TC_DXT3_EXT: number;
            COMPRESSED_RGBA_S3TC_DXT5_EXT: number;
            COMPRESSED_RGB_S3TC_DXT1_EXT: number;
        }
        
        interface WEBGL_debug_renderer_info {
            UNMASKED_RENDERER_WEBGL: number;
            UNMASKED_VENDOR_WEBGL: number;
        }
        
        declare var WEBGL_debug_renderer_info: {
            prototype: WEBGL_debug_renderer_info;
            new(): WEBGL_debug_renderer_info;
            UNMASKED_RENDERER_WEBGL: number;
            UNMASKED_VENDOR_WEBGL: number;
        }
        
        interface WEBGL_depth_texture {
            UNSIGNED_INT_24_8_WEBGL: number;
        }
        
        declare var WEBGL_depth_texture: {
            prototype: WEBGL_depth_texture;
            new(): WEBGL_depth_texture;
            UNSIGNED_INT_24_8_WEBGL: number;
        }
        
        interface WaveShaperNode extends AudioNode {
            curve: any;
            oversample: string;
        }
        
        declare var WaveShaperNode: {
            prototype: WaveShaperNode;
            new(): WaveShaperNode;
        }
        
        interface WebGLActiveInfo {
            name: string;
            size: number;
            type: number;
        }
        
        declare var WebGLActiveInfo: {
            prototype: WebGLActiveInfo;
            new(): WebGLActiveInfo;
        }
        
        interface WebGLBuffer extends WebGLObject {
        }
        
        declare var WebGLBuffer: {
            prototype: WebGLBuffer;
            new(): WebGLBuffer;
        }
        
        interface WebGLContextEvent extends Event {
            statusMessage: string;
        }
        
        declare var WebGLContextEvent: {
            prototype: WebGLContextEvent;
            new(): WebGLContextEvent;
        }
        
        interface WebGLFramebuffer extends WebGLObject {
        }
        
        declare var WebGLFramebuffer: {
            prototype: WebGLFramebuffer;
            new(): WebGLFramebuffer;
        }
        
        interface WebGLObject {
        }
        
        declare var WebGLObject: {
            prototype: WebGLObject;
            new(): WebGLObject;
        }
        
        interface WebGLProgram extends WebGLObject {
        }
        
        declare var WebGLProgram: {
            prototype: WebGLProgram;
            new(): WebGLProgram;
        }
        
        interface WebGLRenderbuffer extends WebGLObject {
        }
        
        declare var WebGLRenderbuffer: {
            prototype: WebGLRenderbuffer;
            new(): WebGLRenderbuffer;
        }
        
        interface WebGLRenderingContext {
            canvas: HTMLCanvasElement;
            drawingBufferHeight: number;
            drawingBufferWidth: number;
            activeTexture(texture: number): void;
            attachShader(program: WebGLProgram, shader: WebGLShader): void;
            bindAttribLocation(program: WebGLProgram, index: number, name: string): void;
            bindBuffer(target: number, buffer: WebGLBuffer): void;
            bindFramebuffer(target: number, framebuffer: WebGLFramebuffer): void;
            bindRenderbuffer(target: number, renderbuffer: WebGLRenderbuffer): void;
            bindTexture(target: number, texture: WebGLTexture): void;
            blendColor(red: number, green: number, blue: number, alpha: number): void;
            blendEquation(mode: number): void;
            blendEquationSeparate(modeRGB: number, modeAlpha: number): void;
            blendFunc(sfactor: number, dfactor: number): void;
            blendFuncSeparate(srcRGB: number, dstRGB: number, srcAlpha: number, dstAlpha: number): void;
            bufferData(target: number, size: number, usage: number): void;
            bufferData(target: number, size: ArrayBufferView, usage: number): void;
            bufferData(target: number, size: any, usage: number): void;
            bufferSubData(target: number, offset: number, data: ArrayBufferView): void;
            bufferSubData(target: number, offset: number, data: any): void;
            checkFramebufferStatus(target: number): number;
            clear(mask: number): void;
            clearColor(red: number, green: number, blue: number, alpha: number): void;
            clearDepth(depth: number): void;
            clearStencil(s: number): void;
            colorMask(red: boolean, green: boolean, blue: boolean, alpha: boolean): void;
            compileShader(shader: WebGLShader): void;
            compressedTexImage2D(target: number, level: number, internalformat: number, width: number, height: number, border: number, data: ArrayBufferView): void;
            compressedTexSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, data: ArrayBufferView): void;
            copyTexImage2D(target: number, level: number, internalformat: number, x: number, y: number, width: number, height: number, border: number): void;
            copyTexSubImage2D(target: number, level: number, xoffset: number, yoffset: number, x: number, y: number, width: number, height: number): void;
            createBuffer(): WebGLBuffer;
            createFramebuffer(): WebGLFramebuffer;
            createProgram(): WebGLProgram;
            createRenderbuffer(): WebGLRenderbuffer;
            createShader(type: number): WebGLShader;
            createTexture(): WebGLTexture;
            cullFace(mode: number): void;
            deleteBuffer(buffer: WebGLBuffer): void;
            deleteFramebuffer(framebuffer: WebGLFramebuffer): void;
            deleteProgram(program: WebGLProgram): void;
            deleteRenderbuffer(renderbuffer: WebGLRenderbuffer): void;
            deleteShader(shader: WebGLShader): void;
            deleteTexture(texture: WebGLTexture): void;
            depthFunc(func: number): void;
            depthMask(flag: boolean): void;
            depthRange(zNear: number, zFar: number): void;
            detachShader(program: WebGLProgram, shader: WebGLShader): void;
            disable(cap: number): void;
            disableVertexAttribArray(index: number): void;
            drawArrays(mode: number, first: number, count: number): void;
            drawElements(mode: number, count: number, type: number, offset: number): void;
            enable(cap: number): void;
            enableVertexAttribArray(index: number): void;
            finish(): void;
            flush(): void;
            framebufferRenderbuffer(target: number, attachment: number, renderbuffertarget: number, renderbuffer: WebGLRenderbuffer): void;
            framebufferTexture2D(target: number, attachment: number, textarget: number, texture: WebGLTexture, level: number): void;
            frontFace(mode: number): void;
            generateMipmap(target: number): void;
            getActiveAttrib(program: WebGLProgram, index: number): WebGLActiveInfo;
            getActiveUniform(program: WebGLProgram, index: number): WebGLActiveInfo;
            getAttachedShaders(program: WebGLProgram): WebGLShader[];
            getAttribLocation(program: WebGLProgram, name: string): number;
            getBufferParameter(target: number, pname: number): any;
            getContextAttributes(): WebGLContextAttributes;
            getError(): number;
            getExtension(name: string): any;
            getFramebufferAttachmentParameter(target: number, attachment: number, pname: number): any;
            getParameter(pname: number): any;
            getProgramInfoLog(program: WebGLProgram): string;
            getProgramParameter(program: WebGLProgram, pname: number): any;
            getRenderbufferParameter(target: number, pname: number): any;
            getShaderInfoLog(shader: WebGLShader): string;
            getShaderParameter(shader: WebGLShader, pname: number): any;
            getShaderPrecisionFormat(shadertype: number, precisiontype: number): WebGLShaderPrecisionFormat;
            getShaderSource(shader: WebGLShader): string;
            getSupportedExtensions(): string[];
            getTexParameter(target: number, pname: number): any;
            getUniform(program: WebGLProgram, location: WebGLUniformLocation): any;
            getUniformLocation(program: WebGLProgram, name: string): WebGLUniformLocation;
            getVertexAttrib(index: number, pname: number): any;
            getVertexAttribOffset(index: number, pname: number): number;
            hint(target: number, mode: number): void;
            isBuffer(buffer: WebGLBuffer): boolean;
            isContextLost(): boolean;
            isEnabled(cap: number): boolean;
            isFramebuffer(framebuffer: WebGLFramebuffer): boolean;
            isProgram(program: WebGLProgram): boolean;
            isRenderbuffer(renderbuffer: WebGLRenderbuffer): boolean;
            isShader(shader: WebGLShader): boolean;
            isTexture(texture: WebGLTexture): boolean;
            lineWidth(width: number): void;
            linkProgram(program: WebGLProgram): void;
            pixelStorei(pname: number, param: number): void;
            polygonOffset(factor: number, units: number): void;
            readPixels(x: number, y: number, width: number, height: number, format: number, type: number, pixels: ArrayBufferView): void;
            renderbufferStorage(target: number, internalformat: number, width: number, height: number): void;
            sampleCoverage(value: number, invert: boolean): void;
            scissor(x: number, y: number, width: number, height: number): void;
            shaderSource(shader: WebGLShader, source: string): void;
            stencilFunc(func: number, ref: number, mask: number): void;
            stencilFuncSeparate(face: number, func: number, ref: number, mask: number): void;
            stencilMask(mask: number): void;
            stencilMaskSeparate(face: number, mask: number): void;
            stencilOp(fail: number, zfail: number, zpass: number): void;
            stencilOpSeparate(face: number, fail: number, zfail: number, zpass: number): void;
            texImage2D(target: number, level: number, internalformat: number, format: number, type: number, pixels: ImageData): void;
            texParameterf(target: number, pname: number, param: number): void;
            texParameteri(target: number, pname: number, param: number): void;
            texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, format: number, type: number, pixels: ImageData): void;
            uniform1f(location: WebGLUniformLocation, x: number): void;
            uniform1fv(location: WebGLUniformLocation, v: any): void;
            uniform1i(location: WebGLUniformLocation, x: number): void;
            uniform1iv(location: WebGLUniformLocation, v: Int32Array): void;
            uniform2f(location: WebGLUniformLocation, x: number, y: number): void;
            uniform2fv(location: WebGLUniformLocation, v: any): void;
            uniform2i(location: WebGLUniformLocation, x: number, y: number): void;
            uniform2iv(location: WebGLUniformLocation, v: Int32Array): void;
            uniform3f(location: WebGLUniformLocation, x: number, y: number, z: number): void;
            uniform3fv(location: WebGLUniformLocation, v: any): void;
            uniform3i(location: WebGLUniformLocation, x: number, y: number, z: number): void;
            uniform3iv(location: WebGLUniformLocation, v: Int32Array): void;
            uniform4f(location: WebGLUniformLocation, x: number, y: number, z: number, w: number): void;
            uniform4fv(location: WebGLUniformLocation, v: any): void;
            uniform4i(location: WebGLUniformLocation, x: number, y: number, z: number, w: number): void;
            uniform4iv(location: WebGLUniformLocation, v: Int32Array): void;
            uniformMatrix2fv(location: WebGLUniformLocation, transpose: boolean, value: any): void;
            uniformMatrix3fv(location: WebGLUniformLocation, transpose: boolean, value: any): void;
            uniformMatrix4fv(location: WebGLUniformLocation, transpose: boolean, value: any): void;
            useProgram(program: WebGLProgram): void;
            validateProgram(program: WebGLProgram): void;
            vertexAttrib1f(indx: number, x: number): void;
            vertexAttrib1fv(indx: number, values: any): void;
            vertexAttrib2f(indx: number, x: number, y: number): void;
            vertexAttrib2fv(indx: number, values: any): void;
            vertexAttrib3f(indx: number, x: number, y: number, z: number): void;
            vertexAttrib3fv(indx: number, values: any): void;
            vertexAttrib4f(indx: number, x: number, y: number, z: number, w: number): void;
            vertexAttrib4fv(indx: number, values: any): void;
            vertexAttribPointer(indx: number, size: number, type: number, normalized: boolean, stride: number, offset: number): void;
            viewport(x: number, y: number, width: number, height: number): void;
            ACTIVE_ATTRIBUTES: number;
            ACTIVE_TEXTURE: number;
            ACTIVE_UNIFORMS: number;
            ALIASED_LINE_WIDTH_RANGE: number;
            ALIASED_POINT_SIZE_RANGE: number;
            ALPHA: number;
            ALPHA_BITS: number;
            ALWAYS: number;
            ARRAY_BUFFER: number;
            ARRAY_BUFFER_BINDING: number;
            ATTACHED_SHADERS: number;
            BACK: number;
            BLEND: number;
            BLEND_COLOR: number;
            BLEND_DST_ALPHA: number;
            BLEND_DST_RGB: number;
            BLEND_EQUATION: number;
            BLEND_EQUATION_ALPHA: number;
            BLEND_EQUATION_RGB: number;
            BLEND_SRC_ALPHA: number;
            BLEND_SRC_RGB: number;
            BLUE_BITS: number;
            BOOL: number;
            BOOL_VEC2: number;
            BOOL_VEC3: number;
            BOOL_VEC4: number;
            BROWSER_DEFAULT_WEBGL: number;
            BUFFER_SIZE: number;
            BUFFER_USAGE: number;
            BYTE: number;
            CCW: number;
            CLAMP_TO_EDGE: number;
            COLOR_ATTACHMENT0: number;
            COLOR_BUFFER_BIT: number;
            COLOR_CLEAR_VALUE: number;
            COLOR_WRITEMASK: number;
            COMPILE_STATUS: number;
            COMPRESSED_TEXTURE_FORMATS: number;
            CONSTANT_ALPHA: number;
            CONSTANT_COLOR: number;
            CONTEXT_LOST_WEBGL: number;
            CULL_FACE: number;
            CULL_FACE_MODE: number;
            CURRENT_PROGRAM: number;
            CURRENT_VERTEX_ATTRIB: number;
            CW: number;
            DECR: number;
            DECR_WRAP: number;
            DELETE_STATUS: number;
            DEPTH_ATTACHMENT: number;
            DEPTH_BITS: number;
            DEPTH_BUFFER_BIT: number;
            DEPTH_CLEAR_VALUE: number;
            DEPTH_COMPONENT: number;
            DEPTH_COMPONENT16: number;
            DEPTH_FUNC: number;
            DEPTH_RANGE: number;
            DEPTH_STENCIL: number;
            DEPTH_STENCIL_ATTACHMENT: number;
            DEPTH_TEST: number;
            DEPTH_WRITEMASK: number;
            DITHER: number;
            DONT_CARE: number;
            DST_ALPHA: number;
            DST_COLOR: number;
            DYNAMIC_DRAW: number;
            ELEMENT_ARRAY_BUFFER: number;
            ELEMENT_ARRAY_BUFFER_BINDING: number;
            EQUAL: number;
            FASTEST: number;
            FLOAT: number;
            FLOAT_MAT2: number;
            FLOAT_MAT3: number;
            FLOAT_MAT4: number;
            FLOAT_VEC2: number;
            FLOAT_VEC3: number;
            FLOAT_VEC4: number;
            FRAGMENT_SHADER: number;
            FRAMEBUFFER: number;
            FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: number;
            FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: number;
            FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: number;
            FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: number;
            FRAMEBUFFER_BINDING: number;
            FRAMEBUFFER_COMPLETE: number;
            FRAMEBUFFER_INCOMPLETE_ATTACHMENT: number;
            FRAMEBUFFER_INCOMPLETE_DIMENSIONS: number;
            FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: number;
            FRAMEBUFFER_UNSUPPORTED: number;
            FRONT: number;
            FRONT_AND_BACK: number;
            FRONT_FACE: number;
            FUNC_ADD: number;
            FUNC_REVERSE_SUBTRACT: number;
            FUNC_SUBTRACT: number;
            GENERATE_MIPMAP_HINT: number;
            GEQUAL: number;
            GREATER: number;
            GREEN_BITS: number;
            HIGH_FLOAT: number;
            HIGH_INT: number;
            IMPLEMENTATION_COLOR_READ_FORMAT: number;
            IMPLEMENTATION_COLOR_READ_TYPE: number;
            INCR: number;
            INCR_WRAP: number;
            INT: number;
            INT_VEC2: number;
            INT_VEC3: number;
            INT_VEC4: number;
            INVALID_ENUM: number;
            INVALID_FRAMEBUFFER_OPERATION: number;
            INVALID_OPERATION: number;
            INVALID_VALUE: number;
            INVERT: number;
            KEEP: number;
            LEQUAL: number;
            LESS: number;
            LINEAR: number;
            LINEAR_MIPMAP_LINEAR: number;
            LINEAR_MIPMAP_NEAREST: number;
            LINES: number;
            LINE_LOOP: number;
            LINE_STRIP: number;
            LINE_WIDTH: number;
            LINK_STATUS: number;
            LOW_FLOAT: number;
            LOW_INT: number;
            LUMINANCE: number;
            LUMINANCE_ALPHA: number;
            MAX_COMBINED_TEXTURE_IMAGE_UNITS: number;
            MAX_CUBE_MAP_TEXTURE_SIZE: number;
            MAX_FRAGMENT_UNIFORM_VECTORS: number;
            MAX_RENDERBUFFER_SIZE: number;
            MAX_TEXTURE_IMAGE_UNITS: number;
            MAX_TEXTURE_SIZE: number;
            MAX_VARYING_VECTORS: number;
            MAX_VERTEX_ATTRIBS: number;
            MAX_VERTEX_TEXTURE_IMAGE_UNITS: number;
            MAX_VERTEX_UNIFORM_VECTORS: number;
            MAX_VIEWPORT_DIMS: number;
            MEDIUM_FLOAT: number;
            MEDIUM_INT: number;
            MIRRORED_REPEAT: number;
            NEAREST: number;
            NEAREST_MIPMAP_LINEAR: number;
            NEAREST_MIPMAP_NEAREST: number;
            NEVER: number;
            NICEST: number;
            NONE: number;
            NOTEQUAL: number;
            NO_ERROR: number;
            ONE: number;
            ONE_MINUS_CONSTANT_ALPHA: number;
            ONE_MINUS_CONSTANT_COLOR: number;
            ONE_MINUS_DST_ALPHA: number;
            ONE_MINUS_DST_COLOR: number;
            ONE_MINUS_SRC_ALPHA: number;
            ONE_MINUS_SRC_COLOR: number;
            OUT_OF_MEMORY: number;
            PACK_ALIGNMENT: number;
            POINTS: number;
            POLYGON_OFFSET_FACTOR: number;
            POLYGON_OFFSET_FILL: number;
            POLYGON_OFFSET_UNITS: number;
            RED_BITS: number;
            RENDERBUFFER: number;
            RENDERBUFFER_ALPHA_SIZE: number;
            RENDERBUFFER_BINDING: number;
            RENDERBUFFER_BLUE_SIZE: number;
            RENDERBUFFER_DEPTH_SIZE: number;
            RENDERBUFFER_GREEN_SIZE: number;
            RENDERBUFFER_HEIGHT: number;
            RENDERBUFFER_INTERNAL_FORMAT: number;
            RENDERBUFFER_RED_SIZE: number;
            RENDERBUFFER_STENCIL_SIZE: number;
            RENDERBUFFER_WIDTH: number;
            RENDERER: number;
            REPEAT: number;
            REPLACE: number;
            RGB: number;
            RGB565: number;
            RGB5_A1: number;
            RGBA: number;
            RGBA4: number;
            SAMPLER_2D: number;
            SAMPLER_CUBE: number;
            SAMPLES: number;
            SAMPLE_ALPHA_TO_COVERAGE: number;
            SAMPLE_BUFFERS: number;
            SAMPLE_COVERAGE: number;
            SAMPLE_COVERAGE_INVERT: number;
            SAMPLE_COVERAGE_VALUE: number;
            SCISSOR_BOX: number;
            SCISSOR_TEST: number;
            SHADER_TYPE: number;
            SHADING_LANGUAGE_VERSION: number;
            SHORT: number;
            SRC_ALPHA: number;
            SRC_ALPHA_SATURATE: number;
            SRC_COLOR: number;
            STATIC_DRAW: number;
            STENCIL_ATTACHMENT: number;
            STENCIL_BACK_FAIL: number;
            STENCIL_BACK_FUNC: number;
            STENCIL_BACK_PASS_DEPTH_FAIL: number;
            STENCIL_BACK_PASS_DEPTH_PASS: number;
            STENCIL_BACK_REF: number;
            STENCIL_BACK_VALUE_MASK: number;
            STENCIL_BACK_WRITEMASK: number;
            STENCIL_BITS: number;
            STENCIL_BUFFER_BIT: number;
            STENCIL_CLEAR_VALUE: number;
            STENCIL_FAIL: number;
            STENCIL_FUNC: number;
            STENCIL_INDEX: number;
            STENCIL_INDEX8: number;
            STENCIL_PASS_DEPTH_FAIL: number;
            STENCIL_PASS_DEPTH_PASS: number;
            STENCIL_REF: number;
            STENCIL_TEST: number;
            STENCIL_VALUE_MASK: number;
            STENCIL_WRITEMASK: number;
            STREAM_DRAW: number;
            SUBPIXEL_BITS: number;
            TEXTURE: number;
            TEXTURE0: number;
            TEXTURE1: number;
            TEXTURE10: number;
            TEXTURE11: number;
            TEXTURE12: number;
            TEXTURE13: number;
            TEXTURE14: number;
            TEXTURE15: number;
            TEXTURE16: number;
            TEXTURE17: number;
            TEXTURE18: number;
            TEXTURE19: number;
            TEXTURE2: number;
            TEXTURE20: number;
            TEXTURE21: number;
            TEXTURE22: number;
            TEXTURE23: number;
            TEXTURE24: number;
            TEXTURE25: number;
            TEXTURE26: number;
            TEXTURE27: number;
            TEXTURE28: number;
            TEXTURE29: number;
            TEXTURE3: number;
            TEXTURE30: number;
            TEXTURE31: number;
            TEXTURE4: number;
            TEXTURE5: number;
            TEXTURE6: number;
            TEXTURE7: number;
            TEXTURE8: number;
            TEXTURE9: number;
            TEXTURE_2D: number;
            TEXTURE_BINDING_2D: number;
            TEXTURE_BINDING_CUBE_MAP: number;
            TEXTURE_CUBE_MAP: number;
            TEXTURE_CUBE_MAP_NEGATIVE_X: number;
            TEXTURE_CUBE_MAP_NEGATIVE_Y: number;
            TEXTURE_CUBE_MAP_NEGATIVE_Z: number;
            TEXTURE_CUBE_MAP_POSITIVE_X: number;
            TEXTURE_CUBE_MAP_POSITIVE_Y: number;
            TEXTURE_CUBE_MAP_POSITIVE_Z: number;
            TEXTURE_MAG_FILTER: number;
            TEXTURE_MIN_FILTER: number;
            TEXTURE_WRAP_S: number;
            TEXTURE_WRAP_T: number;
            TRIANGLES: number;
            TRIANGLE_FAN: number;
            TRIANGLE_STRIP: number;
            UNPACK_ALIGNMENT: number;
            UNPACK_COLORSPACE_CONVERSION_WEBGL: number;
            UNPACK_FLIP_Y_WEBGL: number;
            UNPACK_PREMULTIPLY_ALPHA_WEBGL: number;
            UNSIGNED_BYTE: number;
            UNSIGNED_INT: number;
            UNSIGNED_SHORT: number;
            UNSIGNED_SHORT_4_4_4_4: number;
            UNSIGNED_SHORT_5_5_5_1: number;
            UNSIGNED_SHORT_5_6_5: number;
            VALIDATE_STATUS: number;
            VENDOR: number;
            VERSION: number;
            VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: number;
            VERTEX_ATTRIB_ARRAY_ENABLED: number;
            VERTEX_ATTRIB_ARRAY_NORMALIZED: number;
            VERTEX_ATTRIB_ARRAY_POINTER: number;
            VERTEX_ATTRIB_ARRAY_SIZE: number;
            VERTEX_ATTRIB_ARRAY_STRIDE: number;
            VERTEX_ATTRIB_ARRAY_TYPE: number;
            VERTEX_SHADER: number;
            VIEWPORT: number;
            ZERO: number;
        }
        
        declare var WebGLRenderingContext: {
            prototype: WebGLRenderingContext;
            new(): WebGLRenderingContext;
            ACTIVE_ATTRIBUTES: number;
            ACTIVE_TEXTURE: number;
            ACTIVE_UNIFORMS: number;
            ALIASED_LINE_WIDTH_RANGE: number;
            ALIASED_POINT_SIZE_RANGE: number;
            ALPHA: number;
            ALPHA_BITS: number;
            ALWAYS: number;
            ARRAY_BUFFER: number;
            ARRAY_BUFFER_BINDING: number;
            ATTACHED_SHADERS: number;
            BACK: number;
            BLEND: number;
            BLEND_COLOR: number;
            BLEND_DST_ALPHA: number;
            BLEND_DST_RGB: number;
            BLEND_EQUATION: number;
            BLEND_EQUATION_ALPHA: number;
            BLEND_EQUATION_RGB: number;
            BLEND_SRC_ALPHA: number;
            BLEND_SRC_RGB: number;
            BLUE_BITS: number;
            BOOL: number;
            BOOL_VEC2: number;
            BOOL_VEC3: number;
            BOOL_VEC4: number;
            BROWSER_DEFAULT_WEBGL: number;
            BUFFER_SIZE: number;
            BUFFER_USAGE: number;
            BYTE: number;
            CCW: number;
            CLAMP_TO_EDGE: number;
            COLOR_ATTACHMENT0: number;
            COLOR_BUFFER_BIT: number;
            COLOR_CLEAR_VALUE: number;
            COLOR_WRITEMASK: number;
            COMPILE_STATUS: number;
            COMPRESSED_TEXTURE_FORMATS: number;
            CONSTANT_ALPHA: number;
            CONSTANT_COLOR: number;
            CONTEXT_LOST_WEBGL: number;
            CULL_FACE: number;
            CULL_FACE_MODE: number;
            CURRENT_PROGRAM: number;
            CURRENT_VERTEX_ATTRIB: number;
            CW: number;
            DECR: number;
            DECR_WRAP: number;
            DELETE_STATUS: number;
            DEPTH_ATTACHMENT: number;
            DEPTH_BITS: number;
            DEPTH_BUFFER_BIT: number;
            DEPTH_CLEAR_VALUE: number;
            DEPTH_COMPONENT: number;
            DEPTH_COMPONENT16: number;
            DEPTH_FUNC: number;
            DEPTH_RANGE: number;
            DEPTH_STENCIL: number;
            DEPTH_STENCIL_ATTACHMENT: number;
            DEPTH_TEST: number;
            DEPTH_WRITEMASK: number;
            DITHER: number;
            DONT_CARE: number;
            DST_ALPHA: number;
            DST_COLOR: number;
            DYNAMIC_DRAW: number;
            ELEMENT_ARRAY_BUFFER: number;
            ELEMENT_ARRAY_BUFFER_BINDING: number;
            EQUAL: number;
            FASTEST: number;
            FLOAT: number;
            FLOAT_MAT2: number;
            FLOAT_MAT3: number;
            FLOAT_MAT4: number;
            FLOAT_VEC2: number;
            FLOAT_VEC3: number;
            FLOAT_VEC4: number;
            FRAGMENT_SHADER: number;
            FRAMEBUFFER: number;
            FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: number;
            FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: number;
            FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: number;
            FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: number;
            FRAMEBUFFER_BINDING: number;
            FRAMEBUFFER_COMPLETE: number;
            FRAMEBUFFER_INCOMPLETE_ATTACHMENT: number;
            FRAMEBUFFER_INCOMPLETE_DIMENSIONS: number;
            FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: number;
            FRAMEBUFFER_UNSUPPORTED: number;
            FRONT: number;
            FRONT_AND_BACK: number;
            FRONT_FACE: number;
            FUNC_ADD: number;
            FUNC_REVERSE_SUBTRACT: number;
            FUNC_SUBTRACT: number;
            GENERATE_MIPMAP_HINT: number;
            GEQUAL: number;
            GREATER: number;
            GREEN_BITS: number;
            HIGH_FLOAT: number;
            HIGH_INT: number;
            IMPLEMENTATION_COLOR_READ_FORMAT: number;
            IMPLEMENTATION_COLOR_READ_TYPE: number;
            INCR: number;
            INCR_WRAP: number;
            INT: number;
            INT_VEC2: number;
            INT_VEC3: number;
            INT_VEC4: number;
            INVALID_ENUM: number;
            INVALID_FRAMEBUFFER_OPERATION: number;
            INVALID_OPERATION: number;
            INVALID_VALUE: number;
            INVERT: number;
            KEEP: number;
            LEQUAL: number;
            LESS: number;
            LINEAR: number;
            LINEAR_MIPMAP_LINEAR: number;
            LINEAR_MIPMAP_NEAREST: number;
            LINES: number;
            LINE_LOOP: number;
            LINE_STRIP: number;
            LINE_WIDTH: number;
            LINK_STATUS: number;
            LOW_FLOAT: number;
            LOW_INT: number;
            LUMINANCE: number;
            LUMINANCE_ALPHA: number;
            MAX_COMBINED_TEXTURE_IMAGE_UNITS: number;
            MAX_CUBE_MAP_TEXTURE_SIZE: number;
            MAX_FRAGMENT_UNIFORM_VECTORS: number;
            MAX_RENDERBUFFER_SIZE: number;
            MAX_TEXTURE_IMAGE_UNITS: number;
            MAX_TEXTURE_SIZE: number;
            MAX_VARYING_VECTORS: number;
            MAX_VERTEX_ATTRIBS: number;
            MAX_VERTEX_TEXTURE_IMAGE_UNITS: number;
            MAX_VERTEX_UNIFORM_VECTORS: number;
            MAX_VIEWPORT_DIMS: number;
            MEDIUM_FLOAT: number;
            MEDIUM_INT: number;
            MIRRORED_REPEAT: number;
            NEAREST: number;
            NEAREST_MIPMAP_LINEAR: number;
            NEAREST_MIPMAP_NEAREST: number;
            NEVER: number;
            NICEST: number;
            NONE: number;
            NOTEQUAL: number;
            NO_ERROR: number;
            ONE: number;
            ONE_MINUS_CONSTANT_ALPHA: number;
            ONE_MINUS_CONSTANT_COLOR: number;
            ONE_MINUS_DST_ALPHA: number;
            ONE_MINUS_DST_COLOR: number;
            ONE_MINUS_SRC_ALPHA: number;
            ONE_MINUS_SRC_COLOR: number;
            OUT_OF_MEMORY: number;
            PACK_ALIGNMENT: number;
            POINTS: number;
            POLYGON_OFFSET_FACTOR: number;
            POLYGON_OFFSET_FILL: number;
            POLYGON_OFFSET_UNITS: number;
            RED_BITS: number;
            RENDERBUFFER: number;
            RENDERBUFFER_ALPHA_SIZE: number;
            RENDERBUFFER_BINDING: number;
            RENDERBUFFER_BLUE_SIZE: number;
            RENDERBUFFER_DEPTH_SIZE: number;
            RENDERBUFFER_GREEN_SIZE: number;
            RENDERBUFFER_HEIGHT: number;
            RENDERBUFFER_INTERNAL_FORMAT: number;
            RENDERBUFFER_RED_SIZE: number;
            RENDERBUFFER_STENCIL_SIZE: number;
            RENDERBUFFER_WIDTH: number;
            RENDERER: number;
            REPEAT: number;
            REPLACE: number;
            RGB: number;
            RGB565: number;
            RGB5_A1: number;
            RGBA: number;
            RGBA4: number;
            SAMPLER_2D: number;
            SAMPLER_CUBE: number;
            SAMPLES: number;
            SAMPLE_ALPHA_TO_COVERAGE: number;
            SAMPLE_BUFFERS: number;
            SAMPLE_COVERAGE: number;
            SAMPLE_COVERAGE_INVERT: number;
            SAMPLE_COVERAGE_VALUE: number;
            SCISSOR_BOX: number;
            SCISSOR_TEST: number;
            SHADER_TYPE: number;
            SHADING_LANGUAGE_VERSION: number;
            SHORT: number;
            SRC_ALPHA: number;
            SRC_ALPHA_SATURATE: number;
            SRC_COLOR: number;
            STATIC_DRAW: number;
            STENCIL_ATTACHMENT: number;
            STENCIL_BACK_FAIL: number;
            STENCIL_BACK_FUNC: number;
            STENCIL_BACK_PASS_DEPTH_FAIL: number;
            STENCIL_BACK_PASS_DEPTH_PASS: number;
            STENCIL_BACK_REF: number;
            STENCIL_BACK_VALUE_MASK: number;
            STENCIL_BACK_WRITEMASK: number;
            STENCIL_BITS: number;
            STENCIL_BUFFER_BIT: number;
            STENCIL_CLEAR_VALUE: number;
            STENCIL_FAIL: number;
            STENCIL_FUNC: number;
            STENCIL_INDEX: number;
            STENCIL_INDEX8: number;
            STENCIL_PASS_DEPTH_FAIL: number;
            STENCIL_PASS_DEPTH_PASS: number;
            STENCIL_REF: number;
            STENCIL_TEST: number;
            STENCIL_VALUE_MASK: number;
            STENCIL_WRITEMASK: number;
            STREAM_DRAW: number;
            SUBPIXEL_BITS: number;
            TEXTURE: number;
            TEXTURE0: number;
            TEXTURE1: number;
            TEXTURE10: number;
            TEXTURE11: number;
            TEXTURE12: number;
            TEXTURE13: number;
            TEXTURE14: number;
            TEXTURE15: number;
            TEXTURE16: number;
            TEXTURE17: number;
            TEXTURE18: number;
            TEXTURE19: number;
            TEXTURE2: number;
            TEXTURE20: number;
            TEXTURE21: number;
            TEXTURE22: number;
            TEXTURE23: number;
            TEXTURE24: number;
            TEXTURE25: number;
            TEXTURE26: number;
            TEXTURE27: number;
            TEXTURE28: number;
            TEXTURE29: number;
            TEXTURE3: number;
            TEXTURE30: number;
            TEXTURE31: number;
            TEXTURE4: number;
            TEXTURE5: number;
            TEXTURE6: number;
            TEXTURE7: number;
            TEXTURE8: number;
            TEXTURE9: number;
            TEXTURE_2D: number;
            TEXTURE_BINDING_2D: number;
            TEXTURE_BINDING_CUBE_MAP: number;
            TEXTURE_CUBE_MAP: number;
            TEXTURE_CUBE_MAP_NEGATIVE_X: number;
            TEXTURE_CUBE_MAP_NEGATIVE_Y: number;
            TEXTURE_CUBE_MAP_NEGATIVE_Z: number;
            TEXTURE_CUBE_MAP_POSITIVE_X: number;
            TEXTURE_CUBE_MAP_POSITIVE_Y: number;
            TEXTURE_CUBE_MAP_POSITIVE_Z: number;
            TEXTURE_MAG_FILTER: number;
            TEXTURE_MIN_FILTER: number;
            TEXTURE_WRAP_S: number;
            TEXTURE_WRAP_T: number;
            TRIANGLES: number;
            TRIANGLE_FAN: number;
            TRIANGLE_STRIP: number;
            UNPACK_ALIGNMENT: number;
            UNPACK_COLORSPACE_CONVERSION_WEBGL: number;
            UNPACK_FLIP_Y_WEBGL: number;
            UNPACK_PREMULTIPLY_ALPHA_WEBGL: number;
            UNSIGNED_BYTE: number;
            UNSIGNED_INT: number;
            UNSIGNED_SHORT: number;
            UNSIGNED_SHORT_4_4_4_4: number;
            UNSIGNED_SHORT_5_5_5_1: number;
            UNSIGNED_SHORT_5_6_5: number;
            VALIDATE_STATUS: number;
            VENDOR: number;
            VERSION: number;
            VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: number;
            VERTEX_ATTRIB_ARRAY_ENABLED: number;
            VERTEX_ATTRIB_ARRAY_NORMALIZED: number;
            VERTEX_ATTRIB_ARRAY_POINTER: number;
            VERTEX_ATTRIB_ARRAY_SIZE: number;
            VERTEX_ATTRIB_ARRAY_STRIDE: number;
            VERTEX_ATTRIB_ARRAY_TYPE: number;
            VERTEX_SHADER: number;
            VIEWPORT: number;
            ZERO: number;
        }
        
        interface WebGLShader extends WebGLObject {
        }
        
        declare var WebGLShader: {
            prototype: WebGLShader;
            new(): WebGLShader;
        }
        
        interface WebGLShaderPrecisionFormat {
            precision: number;
            rangeMax: number;
            rangeMin: number;
        }
        
        declare var WebGLShaderPrecisionFormat: {
            prototype: WebGLShaderPrecisionFormat;
            new(): WebGLShaderPrecisionFormat;
        }
        
        interface WebGLTexture extends WebGLObject {
        }
        
        declare var WebGLTexture: {
            prototype: WebGLTexture;
            new(): WebGLTexture;
        }
        
        interface WebGLUniformLocation {
        }
        
        declare var WebGLUniformLocation: {
            prototype: WebGLUniformLocation;
            new(): WebGLUniformLocation;
        }
        
        interface WebKitCSSMatrix {
            a: number;
            b: number;
            c: number;
            d: number;
            e: number;
            f: number;
            m11: number;
            m12: number;
            m13: number;
            m14: number;
            m21: number;
            m22: number;
            m23: number;
            m24: number;
            m31: number;
            m32: number;
            m33: number;
            m34: number;
            m41: number;
            m42: number;
            m43: number;
            m44: number;
            inverse(): WebKitCSSMatrix;
            multiply(secondMatrix: WebKitCSSMatrix): WebKitCSSMatrix;
            rotate(angleX: number, angleY?: number, angleZ?: number): WebKitCSSMatrix;
            rotateAxisAngle(x: number, y: number, z: number, angle: number): WebKitCSSMatrix;
            scale(scaleX: number, scaleY?: number, scaleZ?: number): WebKitCSSMatrix;
            setMatrixValue(value: string): void;
            skewX(angle: number): WebKitCSSMatrix;
            skewY(angle: number): WebKitCSSMatrix;
            toString(): string;
            translate(x: number, y: number, z?: number): WebKitCSSMatrix;
        }
        
        declare var WebKitCSSMatrix: {
            prototype: WebKitCSSMatrix;
            new(text?: string): WebKitCSSMatrix;
        }
        
        interface WebKitPoint {
            x: number;
            y: number;
        }
        
        declare var WebKitPoint: {
            prototype: WebKitPoint;
            new(x?: number, y?: number): WebKitPoint;
        }
        
        interface WebSocket extends EventTarget {
            binaryType: string;
            bufferedAmount: number;
            extensions: string;
            onclose: (ev: CloseEvent) => any;
            onerror: (ev: Event) => any;
            onmessage: (ev: MessageEvent) => any;
            onopen: (ev: Event) => any;
            protocol: string;
            readyState: number;
            url: string;
            close(code?: number, reason?: string): void;
            send(data: any): void;
            CLOSED: number;
            CLOSING: number;
            CONNECTING: number;
            OPEN: number;
            addEventListener(type: "close", listener: (ev: CloseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "open", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var WebSocket: {
            prototype: WebSocket;
            new(url: string, protocols?: string): WebSocket;
            new(url: string, protocols?: any): WebSocket;
            CLOSED: number;
            CLOSING: number;
            CONNECTING: number;
            OPEN: number;
        }
        
        interface WheelEvent extends MouseEvent {
            deltaMode: number;
            deltaX: number;
            deltaY: number;
            deltaZ: number;
            getCurrentPoint(element: Element): void;
            initWheelEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, buttonArg: number, relatedTargetArg: EventTarget, modifiersListArg: string, deltaXArg: number, deltaYArg: number, deltaZArg: number, deltaMode: number): void;
            DOM_DELTA_LINE: number;
            DOM_DELTA_PAGE: number;
            DOM_DELTA_PIXEL: number;
        }
        
        declare var WheelEvent: {
            prototype: WheelEvent;
            new(typeArg: string, eventInitDict?: WheelEventInit): WheelEvent;
            DOM_DELTA_LINE: number;
            DOM_DELTA_PAGE: number;
            DOM_DELTA_PIXEL: number;
        }
        
        interface Window extends EventTarget, WindowTimers, WindowSessionStorage, WindowLocalStorage, WindowConsole, GlobalEventHandlers, IDBEnvironment, WindowBase64 {
            animationStartTime: number;
            applicationCache: ApplicationCache;
            clientInformation: Navigator;
            closed: boolean;
            crypto: Crypto;
            defaultStatus: string;
            devicePixelRatio: number;
            doNotTrack: string;
            document: Document;
            event: Event;
            external: External;
            frameElement: Element;
            frames: Window;
            history: History;
            innerHeight: number;
            innerWidth: number;
            length: number;
            location: Location;
            locationbar: BarProp;
            menubar: BarProp;
            msAnimationStartTime: number;
            msTemplatePrinter: MSTemplatePrinter;
            name: string;
            navigator: Navigator;
            offscreenBuffering: string | boolean;
            onabort: (ev: Event) => any;
            onafterprint: (ev: Event) => any;
            onbeforeprint: (ev: Event) => any;
            onbeforeunload: (ev: BeforeUnloadEvent) => any;
            onblur: (ev: FocusEvent) => any;
            oncanplay: (ev: Event) => any;
            oncanplaythrough: (ev: Event) => any;
            onchange: (ev: Event) => any;
            onclick: (ev: MouseEvent) => any;
            oncompassneedscalibration: (ev: Event) => any;
            oncontextmenu: (ev: PointerEvent) => any;
            ondblclick: (ev: MouseEvent) => any;
            ondevicemotion: (ev: DeviceMotionEvent) => any;
            ondeviceorientation: (ev: DeviceOrientationEvent) => any;
            ondrag: (ev: DragEvent) => any;
            ondragend: (ev: DragEvent) => any;
            ondragenter: (ev: DragEvent) => any;
            ondragleave: (ev: DragEvent) => any;
            ondragover: (ev: DragEvent) => any;
            ondragstart: (ev: DragEvent) => any;
            ondrop: (ev: DragEvent) => any;
            ondurationchange: (ev: Event) => any;
            onemptied: (ev: Event) => any;
            onended: (ev: Event) => any;
            onerror: ErrorEventHandler;
            onfocus: (ev: FocusEvent) => any;
            onhashchange: (ev: HashChangeEvent) => any;
            oninput: (ev: Event) => any;
            onkeydown: (ev: KeyboardEvent) => any;
            onkeypress: (ev: KeyboardEvent) => any;
            onkeyup: (ev: KeyboardEvent) => any;
            onload: (ev: Event) => any;
            onloadeddata: (ev: Event) => any;
            onloadedmetadata: (ev: Event) => any;
            onloadstart: (ev: Event) => any;
            onmessage: (ev: MessageEvent) => any;
            onmousedown: (ev: MouseEvent) => any;
            onmouseenter: (ev: MouseEvent) => any;
            onmouseleave: (ev: MouseEvent) => any;
            onmousemove: (ev: MouseEvent) => any;
            onmouseout: (ev: MouseEvent) => any;
            onmouseover: (ev: MouseEvent) => any;
            onmouseup: (ev: MouseEvent) => any;
            onmousewheel: (ev: MouseWheelEvent) => any;
            onmsgesturechange: (ev: MSGestureEvent) => any;
            onmsgesturedoubletap: (ev: MSGestureEvent) => any;
            onmsgestureend: (ev: MSGestureEvent) => any;
            onmsgesturehold: (ev: MSGestureEvent) => any;
            onmsgesturestart: (ev: MSGestureEvent) => any;
            onmsgesturetap: (ev: MSGestureEvent) => any;
            onmsinertiastart: (ev: MSGestureEvent) => any;
            onmspointercancel: (ev: MSPointerEvent) => any;
            onmspointerdown: (ev: MSPointerEvent) => any;
            onmspointerenter: (ev: MSPointerEvent) => any;
            onmspointerleave: (ev: MSPointerEvent) => any;
            onmspointermove: (ev: MSPointerEvent) => any;
            onmspointerout: (ev: MSPointerEvent) => any;
            onmspointerover: (ev: MSPointerEvent) => any;
            onmspointerup: (ev: MSPointerEvent) => any;
            onoffline: (ev: Event) => any;
            ononline: (ev: Event) => any;
            onorientationchange: (ev: Event) => any;
            onpagehide: (ev: PageTransitionEvent) => any;
            onpageshow: (ev: PageTransitionEvent) => any;
            onpause: (ev: Event) => any;
            onplay: (ev: Event) => any;
            onplaying: (ev: Event) => any;
            onpopstate: (ev: PopStateEvent) => any;
            onprogress: (ev: ProgressEvent) => any;
            onratechange: (ev: Event) => any;
            onreadystatechange: (ev: ProgressEvent) => any;
            onreset: (ev: Event) => any;
            onresize: (ev: UIEvent) => any;
            onscroll: (ev: UIEvent) => any;
            onseeked: (ev: Event) => any;
            onseeking: (ev: Event) => any;
            onselect: (ev: UIEvent) => any;
            onstalled: (ev: Event) => any;
            onstorage: (ev: StorageEvent) => any;
            onsubmit: (ev: Event) => any;
            onsuspend: (ev: Event) => any;
            ontimeupdate: (ev: Event) => any;
            ontouchcancel: any;
            ontouchend: any;
            ontouchmove: any;
            ontouchstart: any;
            onunload: (ev: Event) => any;
            onvolumechange: (ev: Event) => any;
            onwaiting: (ev: Event) => any;
            opener: Window;
            orientation: string;
            outerHeight: number;
            outerWidth: number;
            pageXOffset: number;
            pageYOffset: number;
            parent: Window;
            performance: Performance;
            personalbar: BarProp;
            screen: Screen;
            screenLeft: number;
            screenTop: number;
            screenX: number;
            screenY: number;
            scrollX: number;
            scrollY: number;
            scrollbars: BarProp;
            self: Window;
            status: string;
            statusbar: BarProp;
            styleMedia: StyleMedia;
            toolbar: BarProp;
            top: Window;
            window: Window;
            alert(message?: any): void;
            blur(): void;
            cancelAnimationFrame(handle: number): void;
            captureEvents(): void;
            close(): void;
            confirm(message?: string): boolean;
            focus(): void;
            getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration;
            getMatchedCSSRules(elt: Element, pseudoElt?: string): CSSRuleList;
            getSelection(): Selection;
            matchMedia(mediaQuery: string): MediaQueryList;
            moveBy(x?: number, y?: number): void;
            moveTo(x?: number, y?: number): void;
            msCancelRequestAnimationFrame(handle: number): void;
            msMatchMedia(mediaQuery: string): MediaQueryList;
            msRequestAnimationFrame(callback: FrameRequestCallback): number;
            msWriteProfilerMark(profilerMarkName: string): void;
            open(url?: string, target?: string, features?: string, replace?: boolean): any;
            postMessage(message: any, targetOrigin: string, ports?: any): void;
            print(): void;
            prompt(message?: string, _default?: string): string;
            releaseEvents(): void;
            requestAnimationFrame(callback: FrameRequestCallback): number;
            resizeBy(x?: number, y?: number): void;
            resizeTo(x?: number, y?: number): void;
            scroll(x?: number, y?: number): void;
            scrollBy(x?: number, y?: number): void;
            scrollTo(x?: number, y?: number): void;
            webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint;
            webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint;
            addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "afterprint", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeprint", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "beforeunload", listener: (ev: BeforeUnloadEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "compassneedscalibration", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "devicemotion", listener: (ev: DeviceMotionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "deviceorientation", listener: (ev: DeviceOrientationEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "hashchange", listener: (ev: HashChangeEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "offline", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "online", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "orientationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pagehide", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pageshow", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "popstate", listener: (ev: PopStateEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "storage", listener: (ev: StorageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "unload", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
            [index: number]: Window;
        }
        
        declare var Window: {
            prototype: Window;
            new(): Window;
        }
        
        interface Worker extends EventTarget, AbstractWorker {
            onmessage: (ev: MessageEvent) => any;
            postMessage(message: any, ports?: any): void;
            terminate(): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var Worker: {
            prototype: Worker;
            new(stringUrl: string): Worker;
        }
        
        interface XMLDocument extends Document {
        }
        
        declare var XMLDocument: {
            prototype: XMLDocument;
            new(): XMLDocument;
        }
        
        interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget {
            msCaching: string;
            onreadystatechange: (ev: ProgressEvent) => any;
            readyState: number;
            response: any;
            responseBody: any;
            responseText: string;
            responseType: string;
            responseXML: any;
            status: number;
            statusText: string;
            timeout: number;
            upload: XMLHttpRequestUpload;
            withCredentials: boolean;
            abort(): void;
            getAllResponseHeaders(): string;
            getResponseHeader(header: string): string;
            msCachingEnabled(): boolean;
            open(method: string, url: string, async?: boolean, user?: string, password?: string): void;
            overrideMimeType(mime: string): void;
            send(data?: Document): void;
            send(data?: string): void;
            setRequestHeader(header: string, value: string): void;
            DONE: number;
            HEADERS_RECEIVED: number;
            LOADING: number;
            OPENED: number;
            UNSENT: number;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadend", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "readystatechange", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "timeout", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var XMLHttpRequest: {
            prototype: XMLHttpRequest;
            new(): XMLHttpRequest;
            DONE: number;
            HEADERS_RECEIVED: number;
            LOADING: number;
            OPENED: number;
            UNSENT: number;
            create(): XMLHttpRequest;
        }
        
        interface XMLHttpRequestUpload extends EventTarget, XMLHttpRequestEventTarget {
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        declare var XMLHttpRequestUpload: {
            prototype: XMLHttpRequestUpload;
            new(): XMLHttpRequestUpload;
        }
        
        interface XMLSerializer {
            serializeToString(target: Node): string;
        }
        
        declare var XMLSerializer: {
            prototype: XMLSerializer;
            new(): XMLSerializer;
        }
        
        interface XPathEvaluator {
            createExpression(expression: string, resolver: XPathNSResolver): XPathExpression;
            createNSResolver(nodeResolver?: Node): XPathNSResolver;
            evaluate(expression: string, contextNode: Node, resolver: XPathNSResolver, type: number, result: XPathResult): XPathResult;
        }
        
        declare var XPathEvaluator: {
            prototype: XPathEvaluator;
            new(): XPathEvaluator;
        }
        
        interface XPathExpression {
            evaluate(contextNode: Node, type: number, result: XPathResult): XPathExpression;
        }
        
        declare var XPathExpression: {
            prototype: XPathExpression;
            new(): XPathExpression;
        }
        
        interface XPathNSResolver {
            lookupNamespaceURI(prefix: string): string;
        }
        
        declare var XPathNSResolver: {
            prototype: XPathNSResolver;
            new(): XPathNSResolver;
        }
        
        interface XPathResult {
            booleanValue: boolean;
            invalidIteratorState: boolean;
            numberValue: number;
            resultType: number;
            singleNodeValue: Node;
            snapshotLength: number;
            stringValue: string;
            iterateNext(): Node;
            snapshotItem(index: number): Node;
            ANY_TYPE: number;
            ANY_UNORDERED_NODE_TYPE: number;
            BOOLEAN_TYPE: number;
            FIRST_ORDERED_NODE_TYPE: number;
            NUMBER_TYPE: number;
            ORDERED_NODE_ITERATOR_TYPE: number;
            ORDERED_NODE_SNAPSHOT_TYPE: number;
            STRING_TYPE: number;
            UNORDERED_NODE_ITERATOR_TYPE: number;
            UNORDERED_NODE_SNAPSHOT_TYPE: number;
        }
        
        declare var XPathResult: {
            prototype: XPathResult;
            new(): XPathResult;
            ANY_TYPE: number;
            ANY_UNORDERED_NODE_TYPE: number;
            BOOLEAN_TYPE: number;
            FIRST_ORDERED_NODE_TYPE: number;
            NUMBER_TYPE: number;
            ORDERED_NODE_ITERATOR_TYPE: number;
            ORDERED_NODE_SNAPSHOT_TYPE: number;
            STRING_TYPE: number;
            UNORDERED_NODE_ITERATOR_TYPE: number;
            UNORDERED_NODE_SNAPSHOT_TYPE: number;
        }
        
        interface XSLTProcessor {
            clearParameters(): void;
            getParameter(namespaceURI: string, localName: string): any;
            importStylesheet(style: Node): void;
            removeParameter(namespaceURI: string, localName: string): void;
            reset(): void;
            setParameter(namespaceURI: string, localName: string, value: any): void;
            transformToDocument(source: Node): Document;
            transformToFragment(source: Node, document: Document): DocumentFragment;
        }
        
        declare var XSLTProcessor: {
            prototype: XSLTProcessor;
            new(): XSLTProcessor;
        }
        
        interface AbstractWorker {
            onerror: (ev: Event) => any;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        interface ChildNode {
            remove(): void;
        }
        
        interface DOML2DeprecatedColorProperty {
            color: string;
        }
        
        interface DOML2DeprecatedSizeProperty {
            size: number;
        }
        
        interface DocumentEvent {
            createEvent(eventInterface:"AnimationEvent"): AnimationEvent;
            createEvent(eventInterface:"AriaRequestEvent"): AriaRequestEvent;
            createEvent(eventInterface:"AudioProcessingEvent"): AudioProcessingEvent;
            createEvent(eventInterface:"BeforeUnloadEvent"): BeforeUnloadEvent;
            createEvent(eventInterface:"CloseEvent"): CloseEvent;
            createEvent(eventInterface:"CommandEvent"): CommandEvent;
            createEvent(eventInterface:"CompositionEvent"): CompositionEvent;
            createEvent(eventInterface:"DeviceMotionEvent"): DeviceMotionEvent;
            createEvent(eventInterface:"DeviceOrientationEvent"): DeviceOrientationEvent;
            createEvent(eventInterface:"DragEvent"): DragEvent;
            createEvent(eventInterface:"ErrorEvent"): ErrorEvent;
            createEvent(eventInterface:"Event"): Event;
            createEvent(eventInterface:"FocusEvent"): FocusEvent;
            createEvent(eventInterface:"GamepadEvent"): GamepadEvent;
            createEvent(eventInterface:"HashChangeEvent"): HashChangeEvent;
            createEvent(eventInterface:"IDBVersionChangeEvent"): IDBVersionChangeEvent;
            createEvent(eventInterface:"KeyboardEvent"): KeyboardEvent;
            createEvent(eventInterface:"LongRunningScriptDetectedEvent"): LongRunningScriptDetectedEvent;
            createEvent(eventInterface:"MSGestureEvent"): MSGestureEvent;
            createEvent(eventInterface:"MSManipulationEvent"): MSManipulationEvent;
            createEvent(eventInterface:"MSMediaKeyMessageEvent"): MSMediaKeyMessageEvent;
            createEvent(eventInterface:"MSMediaKeyNeededEvent"): MSMediaKeyNeededEvent;
            createEvent(eventInterface:"MSPointerEvent"): MSPointerEvent;
            createEvent(eventInterface:"MSSiteModeEvent"): MSSiteModeEvent;
            createEvent(eventInterface:"MessageEvent"): MessageEvent;
            createEvent(eventInterface:"MouseEvent"): MouseEvent;
            createEvent(eventInterface:"MouseWheelEvent"): MouseWheelEvent;
            createEvent(eventInterface:"MutationEvent"): MutationEvent;
            createEvent(eventInterface:"NavigationCompletedEvent"): NavigationCompletedEvent;
            createEvent(eventInterface:"NavigationEvent"): NavigationEvent;
            createEvent(eventInterface:"NavigationEventWithReferrer"): NavigationEventWithReferrer;
            createEvent(eventInterface:"OfflineAudioCompletionEvent"): OfflineAudioCompletionEvent;
            createEvent(eventInterface:"PageTransitionEvent"): PageTransitionEvent;
            createEvent(eventInterface:"PermissionRequestedEvent"): PermissionRequestedEvent;
            createEvent(eventInterface:"PointerEvent"): PointerEvent;
            createEvent(eventInterface:"PopStateEvent"): PopStateEvent;
            createEvent(eventInterface:"ProgressEvent"): ProgressEvent;
            createEvent(eventInterface:"SVGZoomEvent"): SVGZoomEvent;
            createEvent(eventInterface:"ScriptNotifyEvent"): ScriptNotifyEvent;
            createEvent(eventInterface:"StorageEvent"): StorageEvent;
            createEvent(eventInterface:"TextEvent"): TextEvent;
            createEvent(eventInterface:"TouchEvent"): TouchEvent;
            createEvent(eventInterface:"TrackEvent"): TrackEvent;
            createEvent(eventInterface:"TransitionEvent"): TransitionEvent;
            createEvent(eventInterface:"UIEvent"): UIEvent;
            createEvent(eventInterface:"UnviewableContentIdentifiedEvent"): UnviewableContentIdentifiedEvent;
            createEvent(eventInterface:"WebGLContextEvent"): WebGLContextEvent;
            createEvent(eventInterface:"WheelEvent"): WheelEvent;
            createEvent(eventInterface: string): Event;
        }
        
        interface ElementTraversal {
            childElementCount: number;
            firstElementChild: Element;
            lastElementChild: Element;
            nextElementSibling: Element;
            previousElementSibling: Element;
        }
        
        interface GetSVGDocument {
            getSVGDocument(): Document;
        }
        
        interface GlobalEventHandlers {
            onpointercancel: (ev: PointerEvent) => any;
            onpointerdown: (ev: PointerEvent) => any;
            onpointerenter: (ev: PointerEvent) => any;
            onpointerleave: (ev: PointerEvent) => any;
            onpointermove: (ev: PointerEvent) => any;
            onpointerout: (ev: PointerEvent) => any;
            onpointerover: (ev: PointerEvent) => any;
            onpointerup: (ev: PointerEvent) => any;
            onwheel: (ev: WheelEvent) => any;
            addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        interface HTMLTableAlignment {
            /**
              * Sets or retrieves a value that you can use to implement your own ch functionality for the object.
              */
            ch: string;
            /**
              * Sets or retrieves a value that you can use to implement your own chOff functionality for the object.
              */
            chOff: string;
            /**
              * Sets or retrieves how text and other content are vertically aligned within the object that contains them.
              */
            vAlign: string;
        }
        
        interface IDBEnvironment {
            indexedDB: IDBFactory;
            msIndexedDB: IDBFactory;
        }
        
        interface LinkStyle {
            sheet: StyleSheet;
        }
        
        interface MSBaseReader {
            onabort: (ev: Event) => any;
            onerror: (ev: Event) => any;
            onload: (ev: Event) => any;
            onloadend: (ev: ProgressEvent) => any;
            onloadstart: (ev: Event) => any;
            onprogress: (ev: ProgressEvent) => any;
            readyState: number;
            result: any;
            abort(): void;
            DONE: number;
            EMPTY: number;
            LOADING: number;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadend", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        interface MSFileSaver {
            msSaveBlob(blob: any, defaultName?: string): boolean;
            msSaveOrOpenBlob(blob: any, defaultName?: string): boolean;
        }
        
        interface MSNavigatorDoNotTrack {
            confirmSiteSpecificTrackingException(args: ConfirmSiteSpecificExceptionsInformation): boolean;
            confirmWebWideTrackingException(args: ExceptionInformation): boolean;
            removeSiteSpecificTrackingException(args: ExceptionInformation): void;
            removeWebWideTrackingException(args: ExceptionInformation): void;
            storeSiteSpecificTrackingException(args: StoreSiteSpecificExceptionsInformation): void;
            storeWebWideTrackingException(args: StoreExceptionsInformation): void;
        }
        
        interface NavigatorContentUtils {
        }
        
        interface NavigatorGeolocation {
            geolocation: Geolocation;
        }
        
        interface NavigatorID {
            appName: string;
            appVersion: string;
            platform: string;
            product: string;
            productSub: string;
            userAgent: string;
            vendor: string;
            vendorSub: string;
        }
        
        interface NavigatorOnLine {
            onLine: boolean;
        }
        
        interface NavigatorStorageUtils {
        }
        
        interface NodeSelector {
            querySelector(selectors: string): Element;
            querySelectorAll(selectors: string): NodeList;
        }
        
        interface RandomSource {
            getRandomValues(array: ArrayBufferView): ArrayBufferView;
        }
        
        interface SVGAnimatedPathData {
            pathSegList: SVGPathSegList;
        }
        
        interface SVGAnimatedPoints {
            animatedPoints: SVGPointList;
            points: SVGPointList;
        }
        
        interface SVGExternalResourcesRequired {
            externalResourcesRequired: SVGAnimatedBoolean;
        }
        
        interface SVGFilterPrimitiveStandardAttributes extends SVGStylable {
            height: SVGAnimatedLength;
            result: SVGAnimatedString;
            width: SVGAnimatedLength;
            x: SVGAnimatedLength;
            y: SVGAnimatedLength;
        }
        
        interface SVGFitToViewBox {
            preserveAspectRatio: SVGAnimatedPreserveAspectRatio;
            viewBox: SVGAnimatedRect;
        }
        
        interface SVGLangSpace {
            xmllang: string;
            xmlspace: string;
        }
        
        interface SVGLocatable {
            farthestViewportElement: SVGElement;
            nearestViewportElement: SVGElement;
            getBBox(): SVGRect;
            getCTM(): SVGMatrix;
            getScreenCTM(): SVGMatrix;
            getTransformToElement(element: SVGElement): SVGMatrix;
        }
        
        interface SVGStylable {
            className: SVGAnimatedString;
            style: CSSStyleDeclaration;
        }
        
        interface SVGTests {
            requiredExtensions: SVGStringList;
            requiredFeatures: SVGStringList;
            systemLanguage: SVGStringList;
            hasExtension(extension: string): boolean;
        }
        
        interface SVGTransformable extends SVGLocatable {
            transform: SVGAnimatedTransformList;
        }
        
        interface SVGURIReference {
            href: SVGAnimatedString;
        }
        
        interface WindowBase64 {
            atob(encodedString: string): string;
            btoa(rawString: string): string;
        }
        
        interface WindowConsole {
            console: Console;
        }
        
        interface WindowLocalStorage {
            localStorage: Storage;
        }
        
        interface WindowSessionStorage {
            sessionStorage: Storage;
        }
        
        interface WindowTimers extends Object, WindowTimersExtension {
            clearInterval(handle: number): void;
            clearTimeout(handle: number): void;
            setInterval(handler: any, timeout?: any, ...args: any[]): number;
            setTimeout(handler: any, timeout?: any, ...args: any[]): number;
        }
        
        interface WindowTimersExtension {
            clearImmediate(handle: number): void;
            msClearImmediate(handle: number): void;
            msSetImmediate(expression: any, ...args: any[]): number;
            setImmediate(expression: any, ...args: any[]): number;
        }
        
        interface XMLHttpRequestEventTarget {
            onabort: (ev: Event) => any;
            onerror: (ev: Event) => any;
            onload: (ev: Event) => any;
            onloadend: (ev: ProgressEvent) => any;
            onloadstart: (ev: Event) => any;
            onprogress: (ev: ProgressEvent) => any;
            ontimeout: (ev: ProgressEvent) => any;
            addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "loadend", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
            addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: "timeout", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
            addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        }
        
        
        interface NodeListOf<TNode extends Node> extends NodeList {
            length: number;
            item(index: number): TNode;
            [index: number]: TNode;
        }
        
        interface BlobPropertyBag {
            type?: string;
            endings?: string;
        }
        
        interface EventListenerObject {
            handleEvent(evt: Event): void;
        }
        
        declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
        
        interface ErrorEventHandler {
            (event: Event, source?: string, fileno?: number, columnNumber?: number): void;
            (event: string, source?: string, fileno?: number, columnNumber?: number): void;
        }
        interface PositionCallback {
            (position: Position): void;
        }
        interface PositionErrorCallback {
            (error: PositionError): void;
        }
        interface MediaQueryListListener {
            (mql: MediaQueryList): void;
        }
        interface MSLaunchUriCallback {
            (): void;
        }
        interface FrameRequestCallback {
            (time: number): void;
        }
        interface MSUnsafeFunctionCallback {
            (): any;
        }
        interface MSExecAtPriorityFunctionCallback {
            (...args: any[]): any;
        }
        interface MutationCallback {
            (mutations: MutationRecord[], observer: MutationObserver): void;
        }
        interface DecodeSuccessCallback {
            (decodedData: AudioBuffer): void;
        }
        interface DecodeErrorCallback {
            (): void;
        }
        interface FunctionStringCallback {
            (data: string): void;
        }
        declare var Audio: {new(src?: string): HTMLAudioElement; };
        declare var Image: {new(width?: number, height?: number): HTMLImageElement; };
        declare var Option: {new(text?: string, value?: string, defaultSelected?: boolean, selected?: boolean): HTMLOptionElement; };
        declare var animationStartTime: number;
        declare var applicationCache: ApplicationCache;
        declare var clientInformation: Navigator;
        declare var closed: boolean;
        declare var crypto: Crypto;
        declare var defaultStatus: string;
        declare var devicePixelRatio: number;
        declare var doNotTrack: string;
        declare var document: Document;
        declare var event: Event;
        declare var external: External;
        declare var frameElement: Element;
        declare var frames: Window;
        declare var history: History;
        declare var innerHeight: number;
        declare var innerWidth: number;
        declare var length: number;
        declare var location: Location;
        declare var locationbar: BarProp;
        declare var menubar: BarProp;
        declare var msAnimationStartTime: number;
        declare var msTemplatePrinter: MSTemplatePrinter;
        declare var name: string;
        declare var navigator: Navigator;
        declare var offscreenBuffering: string | boolean;
        declare var onabort: (ev: Event) => any;
        declare var onafterprint: (ev: Event) => any;
        declare var onbeforeprint: (ev: Event) => any;
        declare var onbeforeunload: (ev: BeforeUnloadEvent) => any;
        declare var onblur: (ev: FocusEvent) => any;
        declare var oncanplay: (ev: Event) => any;
        declare var oncanplaythrough: (ev: Event) => any;
        declare var onchange: (ev: Event) => any;
        declare var onclick: (ev: MouseEvent) => any;
        declare var oncompassneedscalibration: (ev: Event) => any;
        declare var oncontextmenu: (ev: PointerEvent) => any;
        declare var ondblclick: (ev: MouseEvent) => any;
        declare var ondevicemotion: (ev: DeviceMotionEvent) => any;
        declare var ondeviceorientation: (ev: DeviceOrientationEvent) => any;
        declare var ondrag: (ev: DragEvent) => any;
        declare var ondragend: (ev: DragEvent) => any;
        declare var ondragenter: (ev: DragEvent) => any;
        declare var ondragleave: (ev: DragEvent) => any;
        declare var ondragover: (ev: DragEvent) => any;
        declare var ondragstart: (ev: DragEvent) => any;
        declare var ondrop: (ev: DragEvent) => any;
        declare var ondurationchange: (ev: Event) => any;
        declare var onemptied: (ev: Event) => any;
        declare var onended: (ev: Event) => any;
        declare var onerror: ErrorEventHandler;
        declare var onfocus: (ev: FocusEvent) => any;
        declare var onhashchange: (ev: HashChangeEvent) => any;
        declare var oninput: (ev: Event) => any;
        declare var onkeydown: (ev: KeyboardEvent) => any;
        declare var onkeypress: (ev: KeyboardEvent) => any;
        declare var onkeyup: (ev: KeyboardEvent) => any;
        declare var onload: (ev: Event) => any;
        declare var onloadeddata: (ev: Event) => any;
        declare var onloadedmetadata: (ev: Event) => any;
        declare var onloadstart: (ev: Event) => any;
        declare var onmessage: (ev: MessageEvent) => any;
        declare var onmousedown: (ev: MouseEvent) => any;
        declare var onmouseenter: (ev: MouseEvent) => any;
        declare var onmouseleave: (ev: MouseEvent) => any;
        declare var onmousemove: (ev: MouseEvent) => any;
        declare var onmouseout: (ev: MouseEvent) => any;
        declare var onmouseover: (ev: MouseEvent) => any;
        declare var onmouseup: (ev: MouseEvent) => any;
        declare var onmousewheel: (ev: MouseWheelEvent) => any;
        declare var onmsgesturechange: (ev: MSGestureEvent) => any;
        declare var onmsgesturedoubletap: (ev: MSGestureEvent) => any;
        declare var onmsgestureend: (ev: MSGestureEvent) => any;
        declare var onmsgesturehold: (ev: MSGestureEvent) => any;
        declare var onmsgesturestart: (ev: MSGestureEvent) => any;
        declare var onmsgesturetap: (ev: MSGestureEvent) => any;
        declare var onmsinertiastart: (ev: MSGestureEvent) => any;
        declare var onmspointercancel: (ev: MSPointerEvent) => any;
        declare var onmspointerdown: (ev: MSPointerEvent) => any;
        declare var onmspointerenter: (ev: MSPointerEvent) => any;
        declare var onmspointerleave: (ev: MSPointerEvent) => any;
        declare var onmspointermove: (ev: MSPointerEvent) => any;
        declare var onmspointerout: (ev: MSPointerEvent) => any;
        declare var onmspointerover: (ev: MSPointerEvent) => any;
        declare var onmspointerup: (ev: MSPointerEvent) => any;
        declare var onoffline: (ev: Event) => any;
        declare var ononline: (ev: Event) => any;
        declare var onorientationchange: (ev: Event) => any;
        declare var onpagehide: (ev: PageTransitionEvent) => any;
        declare var onpageshow: (ev: PageTransitionEvent) => any;
        declare var onpause: (ev: Event) => any;
        declare var onplay: (ev: Event) => any;
        declare var onplaying: (ev: Event) => any;
        declare var onpopstate: (ev: PopStateEvent) => any;
        declare var onprogress: (ev: ProgressEvent) => any;
        declare var onratechange: (ev: Event) => any;
        declare var onreadystatechange: (ev: ProgressEvent) => any;
        declare var onreset: (ev: Event) => any;
        declare var onresize: (ev: UIEvent) => any;
        declare var onscroll: (ev: UIEvent) => any;
        declare var onseeked: (ev: Event) => any;
        declare var onseeking: (ev: Event) => any;
        declare var onselect: (ev: UIEvent) => any;
        declare var onstalled: (ev: Event) => any;
        declare var onstorage: (ev: StorageEvent) => any;
        declare var onsubmit: (ev: Event) => any;
        declare var onsuspend: (ev: Event) => any;
        declare var ontimeupdate: (ev: Event) => any;
        declare var ontouchcancel: any;
        declare var ontouchend: any;
        declare var ontouchmove: any;
        declare var ontouchstart: any;
        declare var onunload: (ev: Event) => any;
        declare var onvolumechange: (ev: Event) => any;
        declare var onwaiting: (ev: Event) => any;
        declare var opener: Window;
        declare var orientation: string;
        declare var outerHeight: number;
        declare var outerWidth: number;
        declare var pageXOffset: number;
        declare var pageYOffset: number;
        declare var parent: Window;
        declare var performance: Performance;
        declare var personalbar: BarProp;
        declare var screen: Screen;
        declare var screenLeft: number;
        declare var screenTop: number;
        declare var screenX: number;
        declare var screenY: number;
        declare var scrollX: number;
        declare var scrollY: number;
        declare var scrollbars: BarProp;
        declare var self: Window;
        declare var status: string;
        declare var statusbar: BarProp;
        declare var styleMedia: StyleMedia;
        declare var toolbar: BarProp;
        declare var top: Window;
        declare var window: Window;
        declare function alert(message?: any): void;
        declare function blur(): void;
        declare function cancelAnimationFrame(handle: number): void;
        declare function captureEvents(): void;
        declare function close(): void;
        declare function confirm(message?: string): boolean;
        declare function focus(): void;
        declare function getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration;
        declare function getMatchedCSSRules(elt: Element, pseudoElt?: string): CSSRuleList;
        declare function getSelection(): Selection;
        declare function matchMedia(mediaQuery: string): MediaQueryList;
        declare function moveBy(x?: number, y?: number): void;
        declare function moveTo(x?: number, y?: number): void;
        declare function msCancelRequestAnimationFrame(handle: number): void;
        declare function msMatchMedia(mediaQuery: string): MediaQueryList;
        declare function msRequestAnimationFrame(callback: FrameRequestCallback): number;
        declare function msWriteProfilerMark(profilerMarkName: string): void;
        declare function open(url?: string, target?: string, features?: string, replace?: boolean): any;
        declare function postMessage(message: any, targetOrigin: string, ports?: any): void;
        declare function print(): void;
        declare function prompt(message?: string, _default?: string): string;
        declare function releaseEvents(): void;
        declare function requestAnimationFrame(callback: FrameRequestCallback): number;
        declare function resizeBy(x?: number, y?: number): void;
        declare function resizeTo(x?: number, y?: number): void;
        declare function scroll(x?: number, y?: number): void;
        declare function scrollBy(x?: number, y?: number): void;
        declare function scrollTo(x?: number, y?: number): void;
        declare function webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint;
        declare function webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint;
        declare function toString(): string;
        declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        declare function dispatchEvent(evt: Event): boolean;
        declare function removeEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
        declare function clearInterval(handle: number): void;
        declare function clearTimeout(handle: number): void;
        declare function setInterval(handler: any, timeout?: any, ...args: any[]): number;
        declare function setTimeout(handler: any, timeout?: any, ...args: any[]): number;
        declare function clearImmediate(handle: number): void;
        declare function msClearImmediate(handle: number): void;
        declare function msSetImmediate(expression: any, ...args: any[]): number;
        declare function setImmediate(expression: any, ...args: any[]): number;
        declare var sessionStorage: Storage;
        declare var localStorage: Storage;
        declare var console: Console;
        declare var onpointercancel: (ev: PointerEvent) => any;
        declare var onpointerdown: (ev: PointerEvent) => any;
        declare var onpointerenter: (ev: PointerEvent) => any;
        declare var onpointerleave: (ev: PointerEvent) => any;
        declare var onpointermove: (ev: PointerEvent) => any;
        declare var onpointerout: (ev: PointerEvent) => any;
        declare var onpointerover: (ev: PointerEvent) => any;
        declare var onpointerup: (ev: PointerEvent) => any;
        declare var onwheel: (ev: WheelEvent) => any;
        declare var indexedDB: IDBFactory;
        declare var msIndexedDB: IDBFactory;
        declare function atob(encodedString: string): string;
        declare function btoa(rawString: string): string;
        declare function addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSGestureHold", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSGestureStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSGestureTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSInertiaStart", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSPointerCancel", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSPointerDown", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSPointerEnter", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSPointerLeave", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSPointerMove", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSPointerOut", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSPointerOver", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "MSPointerUp", listener: (ev: MSPointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "abort", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "afterprint", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "beforeprint", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "beforeunload", listener: (ev: BeforeUnloadEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "change", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "compassneedscalibration", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "devicemotion", listener: (ev: DeviceMotionEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "deviceorientation", listener: (ev: DeviceOrientationEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "dragend", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "dragenter", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "dragleave", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "dragover", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "dragstart", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "hashchange", listener: (ev: HashChangeEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "load", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "loadeddata", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "loadedmetadata", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "loadstart", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mousedown", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mouseenter", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mouseleave", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mousemove", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "offline", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "online", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "orientationchange", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pagehide", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pageshow", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointercancel", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointerdown", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointerenter", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointerleave", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointermove", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointerout", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointerover", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "pointerup", listener: (ev: PointerEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "popstate", listener: (ev: PopStateEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "progress", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "ratechange", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "readystatechange", listener: (ev: ProgressEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "reset", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "resize", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "scroll", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "storage", listener: (ev: StorageEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "submit", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "suspend", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "timeupdate", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "unload", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
        declare function addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
        declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
      • extensions.d.ts.text
        /////////////////////////////
        /// IE10 ECMAScript Extensions
        /////////////////////////////
        
        /**
          * Represents a raw buffer of binary data, which is used to store data for the 
          * different typed arrays. ArrayBuffers cannot be read from or written to directly, 
          * but can be passed to a typed array or DataView Object to interpret the raw 
          * buffer as needed. 
          */
        interface ArrayBuffer {
            /**
              * Read-only. The length of the ArrayBuffer (in bytes).
              */
            byteLength: number;
        
            /**
              * Returns a section of an ArrayBuffer.
              */
            slice(begin:number, end?:number): ArrayBuffer;
        }
        
        interface ArrayBufferConstructor {
            prototype: ArrayBuffer;
            new (byteLength: number): ArrayBuffer;
            isView(arg: any): boolean;
        }
        declare var ArrayBuffer: ArrayBufferConstructor;
        
        interface ArrayBufferView {
            /**
              * The ArrayBuffer instance referenced by the array. 
              */
            buffer: ArrayBuffer;
        
            /**
              * The length in bytes of the array.
              */
            byteLength: number;
        
            /**
              * The offset in bytes of the array.
              */
            byteOffset: number;
        }
        
        /**
          * A typed array of 8-bit integer values. The contents are initialized to 0. If the requested 
          * number of bytes could not be allocated an exception is raised.
          */
        interface Int8Array {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The ArrayBuffer instance referenced by the array. 
              */
            buffer: ArrayBuffer;
        
            /**
              * The length in bytes of the array.
              */
            byteLength: number;
        
            /**
              * The offset in bytes of the array.
              */
            byteOffset: number;
        
            /** 
              * Returns the this object after copying a section of the array identified by start and end
              * to the same array starting at position target
              * @param target If target is negative, it is treated as length+target where length is the 
              * length of the array. 
              * @param start If start is negative, it is treated as length+start. If end is negative, it 
              * is treated as length+end.
              * @param end If not specified, length of the this object is used as its default value. 
              */
            copyWithin(target: number, start: number, end?: number): Int8Array;
        
            /**
              * Determines whether all the members of an array satisfy the specified test.
              * @param callbackfn A function that accepts up to three arguments. The every method calls 
              * the callbackfn function for each element in array1 until the callbackfn returns false, 
              * or until the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function.
              * If thisArg is omitted, undefined is used as the this value.
              */
            every(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean;
        
            /**
                * Returns the this object after filling the section identified by start and end with value
                * @param value value to fill array section with
                * @param start index to start filling the array at. If start is negative, it is treated as 
                * length+start where length is the length of the array. 
                * @param end index to stop filling the array at. If end is negative, it is treated as 
                * length+end.
                */
            fill(value: number, start?: number, end?: number): Int8Array;
        
            /**
              * Returns the elements of an array that meet the condition specified in a callback function. 
              * @param callbackfn A function that accepts up to three arguments. The filter method calls 
              * the callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            filter(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): Int8Array;
        
            /** 
              * Returns the value of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
        
            /** 
              * Returns the index of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
        
            /**
              * Performs the specified action for each element in an array.
              * @param callbackfn  A function that accepts up to three arguments. forEach calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg  An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            forEach(callbackfn: (value: number, index: number, array: Int8Array) => void, thisArg?: any): void;
        
            /**
              * Returns the index of the first occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
              *  search starts at index 0.
              */
            indexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * Adds all the elements of an array separated by the specified separator string.
              * @param separator A string used to separate one element of an array from the next in the 
              * resulting String. If omitted, the array elements are separated with a comma.
              */
            join(separator?: string): string;
        
            /**
              * Returns the index of the last occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the 
              * search starts at index 0.
              */
            lastIndexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * The length of the array.
              */
            length: number;
        
            /**
              * Calls a defined callback function on each element of an array, and returns an array that 
              * contains the results.
              * @param callbackfn A function that accepts up to three arguments. The map method calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            map(callbackfn: (value: number, index: number, array: Int8Array) => number, thisArg?: any): Int8Array;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue?: number): number;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument 
              * instead of an array value.
              */
            reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls 
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an 
              * argument instead of an array value.
              */
            reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue?: number): number;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U;
        
            /**
              * Reverses the elements in an Array. 
              */
            reverse(): Int8Array;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Int8Array, offset?: number): void;
        
            /** 
              * Returns a section of an array.
              * @param start The beginning of the specified portion of the array.
              * @param end The end of the specified portion of the array.
              */
            slice(start?: number, end?: number): Int8Array;
        
            /**
              * Determines whether the specified callback function returns true for any element of an array.
              * @param callbackfn A function that accepts up to three arguments. The some method calls the 
              * callbackfn function for each element in array1 until the callbackfn returns true, or until 
              * the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            some(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean;
        
            /**
              * Sorts an array.
              * @param compareFn The name of the function used to determine the order of the elements. If 
              * omitted, the elements are sorted in ascending, ASCII character order.
              */
            sort(compareFn?: (a: number, b: number) => number): Int8Array;
        
            /**
              * Gets a new Int8Array view of the ArrayBuffer store for this array, referencing the elements
              * at begin, inclusive, up to end, exclusive. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Int8Array;
        
            /**
              * Converts a number to a string by using the current locale. 
              */
            toLocaleString(): string;
        
            /**
              * Returns a string representation of an array.
              */
            toString(): string;
        
            [index: number]: number;
        }
        interface Int8ArrayConstructor {
            prototype: Int8Array;
            new (length: number): Int8Array;
            new (array: Int8Array): Int8Array;
            new (array: number[]): Int8Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Int8Array;
        
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * Returns a new array from a set of elements.
              * @param items A set of elements to include in the new array object.
              */
            of(...items: number[]): Int8Array;
        }
        declare var Int8Array: Int8ArrayConstructor;
        
        /**
          * A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the 
          * requested number of bytes could not be allocated an exception is raised.
          */
        interface Uint8Array {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The ArrayBuffer instance referenced by the array. 
              */
            buffer: ArrayBuffer;
        
            /**
              * The length in bytes of the array.
              */
            byteLength: number;
        
            /**
              * The offset in bytes of the array.
              */
            byteOffset: number;
        
            /** 
              * Returns the this object after copying a section of the array identified by start and end
              * to the same array starting at position target
              * @param target If target is negative, it is treated as length+target where length is the 
              * length of the array. 
              * @param start If start is negative, it is treated as length+start. If end is negative, it 
              * is treated as length+end.
              * @param end If not specified, length of the this object is used as its default value. 
              */
            copyWithin(target: number, start: number, end?: number): Uint8Array;
        
            /**
              * Determines whether all the members of an array satisfy the specified test.
              * @param callbackfn A function that accepts up to three arguments. The every method calls 
              * the callbackfn function for each element in array1 until the callbackfn returns false, 
              * or until the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function.
              * If thisArg is omitted, undefined is used as the this value.
              */
            every(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean;
        
            /**
                * Returns the this object after filling the section identified by start and end with value
                * @param value value to fill array section with
                * @param start index to start filling the array at. If start is negative, it is treated as 
                * length+start where length is the length of the array. 
                * @param end index to stop filling the array at. If end is negative, it is treated as 
                * length+end.
                */
            fill(value: number, start?: number, end?: number): Uint8Array;
        
            /**
              * Returns the elements of an array that meet the condition specified in a callback function. 
              * @param callbackfn A function that accepts up to three arguments. The filter method calls 
              * the callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            filter(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): Uint8Array;
        
            /** 
              * Returns the value of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
        
            /** 
              * Returns the index of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
        
            /**
              * Performs the specified action for each element in an array.
              * @param callbackfn  A function that accepts up to three arguments. forEach calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg  An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            forEach(callbackfn: (value: number, index: number, array: Uint8Array) => void, thisArg?: any): void;
        
            /**
              * Returns the index of the first occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
              *  search starts at index 0.
              */
            indexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * Adds all the elements of an array separated by the specified separator string.
              * @param separator A string used to separate one element of an array from the next in the 
              * resulting String. If omitted, the array elements are separated with a comma.
              */
            join(separator?: string): string;
        
            /**
              * Returns the index of the last occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the 
              * search starts at index 0.
              */
            lastIndexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * The length of the array.
              */
            length: number;
        
            /**
              * Calls a defined callback function on each element of an array, and returns an array that 
              * contains the results.
              * @param callbackfn A function that accepts up to three arguments. The map method calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            map(callbackfn: (value: number, index: number, array: Uint8Array) => number, thisArg?: any): Uint8Array;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue?: number): number;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument 
              * instead of an array value.
              */
            reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls 
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an 
              * argument instead of an array value.
              */
            reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue?: number): number;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U;
        
            /**
              * Reverses the elements in an Array. 
              */
            reverse(): Uint8Array;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Uint8Array, offset?: number): void;
        
            /** 
              * Returns a section of an array.
              * @param start The beginning of the specified portion of the array.
              * @param end The end of the specified portion of the array.
              */
            slice(start?: number, end?: number): Uint8Array;
        
            /**
              * Determines whether the specified callback function returns true for any element of an array.
              * @param callbackfn A function that accepts up to three arguments. The some method calls the 
              * callbackfn function for each element in array1 until the callbackfn returns true, or until 
              * the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            some(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean;
        
            /**
              * Sorts an array.
              * @param compareFn The name of the function used to determine the order of the elements. If 
              * omitted, the elements are sorted in ascending, ASCII character order.
              */
            sort(compareFn?: (a: number, b: number) => number): Uint8Array;
        
            /**
              * Gets a new Uint8Array view of the ArrayBuffer store for this array, referencing the elements
              * at begin, inclusive, up to end, exclusive. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Uint8Array;
        
            /**
              * Converts a number to a string by using the current locale. 
              */
            toLocaleString(): string;
        
            /**
              * Returns a string representation of an array.
              */
            toString(): string;
        
            [index: number]: number;
        }
        
        interface Uint8ArrayConstructor {
            prototype: Uint8Array;
            new (length: number): Uint8Array;
            new (array: Uint8Array): Uint8Array;
            new (array: number[]): Uint8Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Uint8Array;
        
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * Returns a new array from a set of elements.
              * @param items A set of elements to include in the new array object.
              */
            of(...items: number[]): Uint8Array;
        }
        declare var Uint8Array: Uint8ArrayConstructor;
        
        /**
          * A typed array of 16-bit signed integer values. The contents are initialized to 0. If the 
          * requested number of bytes could not be allocated an exception is raised.
          */
        interface Int16Array {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The ArrayBuffer instance referenced by the array. 
              */
            buffer: ArrayBuffer;
        
            /**
              * The length in bytes of the array.
              */
            byteLength: number;
        
            /**
              * The offset in bytes of the array.
              */
            byteOffset: number;
        
            /** 
              * Returns the this object after copying a section of the array identified by start and end
              * to the same array starting at position target
              * @param target If target is negative, it is treated as length+target where length is the 
              * length of the array. 
              * @param start If start is negative, it is treated as length+start. If end is negative, it 
              * is treated as length+end.
              * @param end If not specified, length of the this object is used as its default value. 
              */
            copyWithin(target: number, start: number, end?: number): Int16Array;
        
            /**
              * Determines whether all the members of an array satisfy the specified test.
              * @param callbackfn A function that accepts up to three arguments. The every method calls 
              * the callbackfn function for each element in array1 until the callbackfn returns false, 
              * or until the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function.
              * If thisArg is omitted, undefined is used as the this value.
              */
            every(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): boolean;
        
            /**
                * Returns the this object after filling the section identified by start and end with value
                * @param value value to fill array section with
                * @param start index to start filling the array at. If start is negative, it is treated as 
                * length+start where length is the length of the array. 
                * @param end index to stop filling the array at. If end is negative, it is treated as 
                * length+end.
                */
            fill(value: number, start?: number, end?: number): Int16Array;
        
            /**
              * Returns the elements of an array that meet the condition specified in a callback function. 
              * @param callbackfn A function that accepts up to three arguments. The filter method calls 
              * the callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            filter(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): Int16Array;
        
            /** 
              * Returns the value of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
        
            /** 
              * Returns the index of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
        
            /**
              * Performs the specified action for each element in an array.
              * @param callbackfn  A function that accepts up to three arguments. forEach calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg  An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            forEach(callbackfn: (value: number, index: number, array: Int16Array) => void, thisArg?: any): void;
        
            /**
              * Returns the index of the first occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
              *  search starts at index 0.
              */
            indexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * Adds all the elements of an array separated by the specified separator string.
              * @param separator A string used to separate one element of an array from the next in the 
              * resulting String. If omitted, the array elements are separated with a comma.
              */
            join(separator?: string): string;
        
            /**
              * Returns the index of the last occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the 
              * search starts at index 0.
              */
            lastIndexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * The length of the array.
              */
            length: number;
        
            /**
              * Calls a defined callback function on each element of an array, and returns an array that 
              * contains the results.
              * @param callbackfn A function that accepts up to three arguments. The map method calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            map(callbackfn: (value: number, index: number, array: Int16Array) => number, thisArg?: any): Int16Array;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue?: number): number;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument 
              * instead of an array value.
              */
            reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int16Array) => U, initialValue: U): U;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls 
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an 
              * argument instead of an array value.
              */
            reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue?: number): number;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int16Array) => U, initialValue: U): U;
        
            /**
              * Reverses the elements in an Array. 
              */
            reverse(): Int16Array;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Int16Array, offset?: number): void;
        
            /** 
              * Returns a section of an array.
              * @param start The beginning of the specified portion of the array.
              * @param end The end of the specified portion of the array.
              */
            slice(start?: number, end?: number): Int16Array;
        
            /**
              * Determines whether the specified callback function returns true for any element of an array.
              * @param callbackfn A function that accepts up to three arguments. The some method calls the 
              * callbackfn function for each element in array1 until the callbackfn returns true, or until 
              * the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            some(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): boolean;
        
            /**
              * Sorts an array.
              * @param compareFn The name of the function used to determine the order of the elements. If 
              * omitted, the elements are sorted in ascending, ASCII character order.
              */
            sort(compareFn?: (a: number, b: number) => number): Int16Array;
        
            /**
              * Gets a new Int16Array view of the ArrayBuffer store for this array, referencing the elements
              * at begin, inclusive, up to end, exclusive. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Int16Array;
        
            /**
              * Converts a number to a string by using the current locale. 
              */
            toLocaleString(): string;
        
            /**
              * Returns a string representation of an array.
              */
            toString(): string;
        
            [index: number]: number;
        }
        
        interface Int16ArrayConstructor {
            prototype: Int16Array;
            new (length: number): Int16Array;
            new (array: Int16Array): Int16Array;
            new (array: number[]): Int16Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Int16Array;
        
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * Returns a new array from a set of elements.
              * @param items A set of elements to include in the new array object.
              */
            of(...items: number[]): Int16Array;
        }
        declare var Int16Array: Int16ArrayConstructor;
        
        /**
          * A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the 
          * requested number of bytes could not be allocated an exception is raised.
          */
        interface Uint16Array {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The ArrayBuffer instance referenced by the array. 
              */
            buffer: ArrayBuffer;
        
            /**
              * The length in bytes of the array.
              */
            byteLength: number;
        
            /**
              * The offset in bytes of the array.
              */
            byteOffset: number;
        
            /** 
              * Returns the this object after copying a section of the array identified by start and end
              * to the same array starting at position target
              * @param target If target is negative, it is treated as length+target where length is the 
              * length of the array. 
              * @param start If start is negative, it is treated as length+start. If end is negative, it 
              * is treated as length+end.
              * @param end If not specified, length of the this object is used as its default value. 
              */
            copyWithin(target: number, start: number, end?: number): Uint16Array;
        
            /**
              * Determines whether all the members of an array satisfy the specified test.
              * @param callbackfn A function that accepts up to three arguments. The every method calls 
              * the callbackfn function for each element in array1 until the callbackfn returns false, 
              * or until the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function.
              * If thisArg is omitted, undefined is used as the this value.
              */
            every(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): boolean;
        
            /**
                * Returns the this object after filling the section identified by start and end with value
                * @param value value to fill array section with
                * @param start index to start filling the array at. If start is negative, it is treated as 
                * length+start where length is the length of the array. 
                * @param end index to stop filling the array at. If end is negative, it is treated as 
                * length+end.
                */
            fill(value: number, start?: number, end?: number): Uint16Array;
        
            /**
              * Returns the elements of an array that meet the condition specified in a callback function. 
              * @param callbackfn A function that accepts up to three arguments. The filter method calls 
              * the callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            filter(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): Uint16Array;
        
            /** 
              * Returns the value of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
        
            /** 
              * Returns the index of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
        
            /**
              * Performs the specified action for each element in an array.
              * @param callbackfn  A function that accepts up to three arguments. forEach calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg  An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            forEach(callbackfn: (value: number, index: number, array: Uint16Array) => void, thisArg?: any): void;
        
            /**
              * Returns the index of the first occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
              *  search starts at index 0.
              */
            indexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * Adds all the elements of an array separated by the specified separator string.
              * @param separator A string used to separate one element of an array from the next in the 
              * resulting String. If omitted, the array elements are separated with a comma.
              */
            join(separator?: string): string;
        
            /**
              * Returns the index of the last occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the 
              * search starts at index 0.
              */
            lastIndexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * The length of the array.
              */
            length: number;
        
            /**
              * Calls a defined callback function on each element of an array, and returns an array that 
              * contains the results.
              * @param callbackfn A function that accepts up to three arguments. The map method calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            map(callbackfn: (value: number, index: number, array: Uint16Array) => number, thisArg?: any): Uint16Array;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue?: number): number;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument 
              * instead of an array value.
              */
            reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U, initialValue: U): U;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls 
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an 
              * argument instead of an array value.
              */
            reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue?: number): number;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U, initialValue: U): U;
        
            /**
              * Reverses the elements in an Array. 
              */
            reverse(): Uint16Array;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Uint16Array, offset?: number): void;
        
            /** 
              * Returns a section of an array.
              * @param start The beginning of the specified portion of the array.
              * @param end The end of the specified portion of the array.
              */
            slice(start?: number, end?: number): Uint16Array;
        
            /**
              * Determines whether the specified callback function returns true for any element of an array.
              * @param callbackfn A function that accepts up to three arguments. The some method calls the 
              * callbackfn function for each element in array1 until the callbackfn returns true, or until 
              * the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            some(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): boolean;
        
            /**
              * Sorts an array.
              * @param compareFn The name of the function used to determine the order of the elements. If 
              * omitted, the elements are sorted in ascending, ASCII character order.
              */
            sort(compareFn?: (a: number, b: number) => number): Uint16Array;
        
            /**
              * Gets a new Uint16Array view of the ArrayBuffer store for this array, referencing the elements
              * at begin, inclusive, up to end, exclusive. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Uint16Array;
        
            /**
              * Converts a number to a string by using the current locale. 
              */
            toLocaleString(): string;
        
            /**
              * Returns a string representation of an array.
              */
            toString(): string;
        
            [index: number]: number;
        }
        
        interface Uint16ArrayConstructor {
            prototype: Uint16Array;
            new (length: number): Uint16Array;
            new (array: Uint16Array): Uint16Array;
            new (array: number[]): Uint16Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Uint16Array;
        
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * Returns a new array from a set of elements.
              * @param items A set of elements to include in the new array object.
              */
            of(...items: number[]): Uint16Array;
        }
        declare var Uint16Array: Uint16ArrayConstructor;
        /**
          * A typed array of 32-bit signed integer values. The contents are initialized to 0. If the 
          * requested number of bytes could not be allocated an exception is raised.
          */
        interface Int32Array {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The ArrayBuffer instance referenced by the array. 
              */
            buffer: ArrayBuffer;
        
            /**
              * The length in bytes of the array.
              */
            byteLength: number;
        
            /**
              * The offset in bytes of the array.
              */
            byteOffset: number;
        
            /** 
              * Returns the this object after copying a section of the array identified by start and end
              * to the same array starting at position target
              * @param target If target is negative, it is treated as length+target where length is the 
              * length of the array. 
              * @param start If start is negative, it is treated as length+start. If end is negative, it 
              * is treated as length+end.
              * @param end If not specified, length of the this object is used as its default value. 
              */
            copyWithin(target: number, start: number, end?: number): Int32Array;
        
            /**
              * Determines whether all the members of an array satisfy the specified test.
              * @param callbackfn A function that accepts up to three arguments. The every method calls 
              * the callbackfn function for each element in array1 until the callbackfn returns false, 
              * or until the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function.
              * If thisArg is omitted, undefined is used as the this value.
              */
            every(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): boolean;
        
            /**
                * Returns the this object after filling the section identified by start and end with value
                * @param value value to fill array section with
                * @param start index to start filling the array at. If start is negative, it is treated as 
                * length+start where length is the length of the array. 
                * @param end index to stop filling the array at. If end is negative, it is treated as 
                * length+end.
                */
            fill(value: number, start?: number, end?: number): Int32Array;
        
            /**
              * Returns the elements of an array that meet the condition specified in a callback function. 
              * @param callbackfn A function that accepts up to three arguments. The filter method calls 
              * the callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            filter(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): Int32Array;
        
            /** 
              * Returns the value of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
        
            /** 
              * Returns the index of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
        
            /**
              * Performs the specified action for each element in an array.
              * @param callbackfn  A function that accepts up to three arguments. forEach calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg  An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            forEach(callbackfn: (value: number, index: number, array: Int32Array) => void, thisArg?: any): void;
        
            /**
              * Returns the index of the first occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
              *  search starts at index 0.
              */
            indexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * Adds all the elements of an array separated by the specified separator string.
              * @param separator A string used to separate one element of an array from the next in the 
              * resulting String. If omitted, the array elements are separated with a comma.
              */
            join(separator?: string): string;
        
            /**
              * Returns the index of the last occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the 
              * search starts at index 0.
              */
            lastIndexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * The length of the array.
              */
            length: number;
        
            /**
              * Calls a defined callback function on each element of an array, and returns an array that 
              * contains the results.
              * @param callbackfn A function that accepts up to three arguments. The map method calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            map(callbackfn: (value: number, index: number, array: Int32Array) => number, thisArg?: any): Int32Array;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue?: number): number;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument 
              * instead of an array value.
              */
            reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int32Array) => U, initialValue: U): U;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls 
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an 
              * argument instead of an array value.
              */
            reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue?: number): number;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int32Array) => U, initialValue: U): U;
        
            /**
              * Reverses the elements in an Array. 
              */
            reverse(): Int32Array;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Int32Array, offset?: number): void;
        
            /** 
              * Returns a section of an array.
              * @param start The beginning of the specified portion of the array.
              * @param end The end of the specified portion of the array.
              */
            slice(start?: number, end?: number): Int32Array;
        
            /**
              * Determines whether the specified callback function returns true for any element of an array.
              * @param callbackfn A function that accepts up to three arguments. The some method calls the 
              * callbackfn function for each element in array1 until the callbackfn returns true, or until 
              * the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            some(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): boolean;
        
            /**
              * Sorts an array.
              * @param compareFn The name of the function used to determine the order of the elements. If 
              * omitted, the elements are sorted in ascending, ASCII character order.
              */
            sort(compareFn?: (a: number, b: number) => number): Int32Array;
        
            /**
              * Gets a new Int32Array view of the ArrayBuffer store for this array, referencing the elements
              * at begin, inclusive, up to end, exclusive. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Int32Array;
        
            /**
              * Converts a number to a string by using the current locale. 
              */
            toLocaleString(): string;
        
            /**
              * Returns a string representation of an array.
              */
            toString(): string;
        
            [index: number]: number;
        }
        
        interface Int32ArrayConstructor {
            prototype: Int32Array;
            new (length: number): Int32Array;
            new (array: Int32Array): Int32Array;
            new (array: number[]): Int32Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Int32Array;
        
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * Returns a new array from a set of elements.
              * @param items A set of elements to include in the new array object.
              */
            of(...items: number[]): Int32Array;
        }
        declare var Int32Array: Int32ArrayConstructor;
        
        /**
          * A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the 
          * requested number of bytes could not be allocated an exception is raised.
          */
        interface Uint32Array {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The ArrayBuffer instance referenced by the array. 
              */
            buffer: ArrayBuffer;
        
            /**
              * The length in bytes of the array.
              */
            byteLength: number;
        
            /**
              * The offset in bytes of the array.
              */
            byteOffset: number;
        
            /** 
              * Returns the this object after copying a section of the array identified by start and end
              * to the same array starting at position target
              * @param target If target is negative, it is treated as length+target where length is the 
              * length of the array. 
              * @param start If start is negative, it is treated as length+start. If end is negative, it 
              * is treated as length+end.
              * @param end If not specified, length of the this object is used as its default value. 
              */
            copyWithin(target: number, start: number, end?: number): Uint32Array;
        
            /**
              * Determines whether all the members of an array satisfy the specified test.
              * @param callbackfn A function that accepts up to three arguments. The every method calls 
              * the callbackfn function for each element in array1 until the callbackfn returns false, 
              * or until the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function.
              * If thisArg is omitted, undefined is used as the this value.
              */
            every(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): boolean;
        
            /**
                * Returns the this object after filling the section identified by start and end with value
                * @param value value to fill array section with
                * @param start index to start filling the array at. If start is negative, it is treated as 
                * length+start where length is the length of the array. 
                * @param end index to stop filling the array at. If end is negative, it is treated as 
                * length+end.
                */
            fill(value: number, start?: number, end?: number): Uint32Array;
        
            /**
              * Returns the elements of an array that meet the condition specified in a callback function. 
              * @param callbackfn A function that accepts up to three arguments. The filter method calls 
              * the callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            filter(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): Uint32Array;
        
            /** 
              * Returns the value of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
        
            /** 
              * Returns the index of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
        
            /**
              * Performs the specified action for each element in an array.
              * @param callbackfn  A function that accepts up to three arguments. forEach calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg  An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            forEach(callbackfn: (value: number, index: number, array: Uint32Array) => void, thisArg?: any): void;
        
            /**
              * Returns the index of the first occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
              *  search starts at index 0.
              */
            indexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * Adds all the elements of an array separated by the specified separator string.
              * @param separator A string used to separate one element of an array from the next in the 
              * resulting String. If omitted, the array elements are separated with a comma.
              */
            join(separator?: string): string;
        
            /**
              * Returns the index of the last occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the 
              * search starts at index 0.
              */
            lastIndexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * The length of the array.
              */
            length: number;
        
            /**
              * Calls a defined callback function on each element of an array, and returns an array that 
              * contains the results.
              * @param callbackfn A function that accepts up to three arguments. The map method calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            map(callbackfn: (value: number, index: number, array: Uint32Array) => number, thisArg?: any): Uint32Array;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue?: number): number;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument 
              * instead of an array value.
              */
            reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U, initialValue: U): U;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls 
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an 
              * argument instead of an array value.
              */
            reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue?: number): number;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U, initialValue: U): U;
        
            /**
              * Reverses the elements in an Array. 
              */
            reverse(): Uint32Array;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Uint32Array, offset?: number): void;
        
            /** 
              * Returns a section of an array.
              * @param start The beginning of the specified portion of the array.
              * @param end The end of the specified portion of the array.
              */
            slice(start?: number, end?: number): Uint32Array;
        
            /**
              * Determines whether the specified callback function returns true for any element of an array.
              * @param callbackfn A function that accepts up to three arguments. The some method calls the 
              * callbackfn function for each element in array1 until the callbackfn returns true, or until 
              * the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            some(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): boolean;
        
            /**
              * Sorts an array.
              * @param compareFn The name of the function used to determine the order of the elements. If 
              * omitted, the elements are sorted in ascending, ASCII character order.
              */
            sort(compareFn?: (a: number, b: number) => number): Uint32Array;
        
            /**
              * Gets a new Uint32Array view of the ArrayBuffer store for this array, referencing the elements
              * at begin, inclusive, up to end, exclusive. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Uint32Array;
        
            /**
              * Converts a number to a string by using the current locale. 
              */
            toLocaleString(): string;
        
            /**
              * Returns a string representation of an array.
              */
            toString(): string;
        
            [index: number]: number;
        }
        
        interface Uint32ArrayConstructor {
            prototype: Uint32Array;
            new (length: number): Uint32Array;
            new (array: Uint32Array): Uint32Array;
            new (array: number[]): Uint32Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Uint32Array;
        
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * Returns a new array from a set of elements.
              * @param items A set of elements to include in the new array object.
              */
            of(...items: number[]): Uint32Array;
        }
        declare var Uint32Array: Uint32ArrayConstructor;
        
        /**
          * A typed array of 32-bit float values. The contents are initialized to 0. If the requested number
          * of bytes could not be allocated an exception is raised.
          */
        interface Float32Array {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The ArrayBuffer instance referenced by the array. 
              */
            buffer: ArrayBuffer;
        
            /**
              * The length in bytes of the array.
              */
            byteLength: number;
        
            /**
              * The offset in bytes of the array.
              */
            byteOffset: number;
        
            /** 
              * Returns the this object after copying a section of the array identified by start and end
              * to the same array starting at position target
              * @param target If target is negative, it is treated as length+target where length is the 
              * length of the array. 
              * @param start If start is negative, it is treated as length+start. If end is negative, it 
              * is treated as length+end.
              * @param end If not specified, length of the this object is used as its default value. 
              */
            copyWithin(target: number, start: number, end?: number): Float32Array;
        
            /**
              * Determines whether all the members of an array satisfy the specified test.
              * @param callbackfn A function that accepts up to three arguments. The every method calls 
              * the callbackfn function for each element in array1 until the callbackfn returns false, 
              * or until the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function.
              * If thisArg is omitted, undefined is used as the this value.
              */
            every(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): boolean;
        
            /**
                * Returns the this object after filling the section identified by start and end with value
                * @param value value to fill array section with
                * @param start index to start filling the array at. If start is negative, it is treated as 
                * length+start where length is the length of the array. 
                * @param end index to stop filling the array at. If end is negative, it is treated as 
                * length+end.
                */
            fill(value: number, start?: number, end?: number): Float32Array;
        
            /**
              * Returns the elements of an array that meet the condition specified in a callback function. 
              * @param callbackfn A function that accepts up to three arguments. The filter method calls 
              * the callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            filter(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): Float32Array;
        
            /** 
              * Returns the value of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
        
            /** 
              * Returns the index of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
        
            /**
              * Performs the specified action for each element in an array.
              * @param callbackfn  A function that accepts up to three arguments. forEach calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg  An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            forEach(callbackfn: (value: number, index: number, array: Float32Array) => void, thisArg?: any): void;
        
            /**
              * Returns the index of the first occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
              *  search starts at index 0.
              */
            indexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * Adds all the elements of an array separated by the specified separator string.
              * @param separator A string used to separate one element of an array from the next in the 
              * resulting String. If omitted, the array elements are separated with a comma.
              */
            join(separator?: string): string;
        
            /**
              * Returns the index of the last occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the 
              * search starts at index 0.
              */
            lastIndexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * The length of the array.
              */
            length: number;
        
            /**
              * Calls a defined callback function on each element of an array, and returns an array that 
              * contains the results.
              * @param callbackfn A function that accepts up to three arguments. The map method calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            map(callbackfn: (value: number, index: number, array: Float32Array) => number, thisArg?: any): Float32Array;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue?: number): number;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument 
              * instead of an array value.
              */
            reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float32Array) => U, initialValue: U): U;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls 
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an 
              * argument instead of an array value.
              */
            reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue?: number): number;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float32Array) => U, initialValue: U): U;
        
            /**
              * Reverses the elements in an Array. 
              */
            reverse(): Float32Array;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Float32Array, offset?: number): void;
        
            /** 
              * Returns a section of an array.
              * @param start The beginning of the specified portion of the array.
              * @param end The end of the specified portion of the array.
              */
            slice(start?: number, end?: number): Float32Array;
        
            /**
              * Determines whether the specified callback function returns true for any element of an array.
              * @param callbackfn A function that accepts up to three arguments. The some method calls the 
              * callbackfn function for each element in array1 until the callbackfn returns true, or until 
              * the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            some(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): boolean;
        
            /**
              * Sorts an array.
              * @param compareFn The name of the function used to determine the order of the elements. If 
              * omitted, the elements are sorted in ascending, ASCII character order.
              */
            sort(compareFn?: (a: number, b: number) => number): Float32Array;
        
            /**
              * Gets a new Float32Array view of the ArrayBuffer store for this array, referencing the elements
              * at begin, inclusive, up to end, exclusive. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Float32Array;
        
            /**
              * Converts a number to a string by using the current locale. 
              */
            toLocaleString(): string;
        
            /**
              * Returns a string representation of an array.
              */
            toString(): string;
        
            [index: number]: number;
        }
        
        interface Float32ArrayConstructor {
            prototype: Float32Array;
            new (length: number): Float32Array;
            new (array: Float32Array): Float32Array;
            new (array: number[]): Float32Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Float32Array;
        
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * Returns a new array from a set of elements.
              * @param items A set of elements to include in the new array object.
              */
            of(...items: number[]): Float32Array;
        }
        declare var Float32Array: Float32ArrayConstructor;
        
        /**
          * A typed array of 64-bit float values. The contents are initialized to 0. If the requested 
          * number of bytes could not be allocated an exception is raised.
          */
        interface Float64Array {
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * The ArrayBuffer instance referenced by the array. 
              */
            buffer: ArrayBuffer;
        
            /**
              * The length in bytes of the array.
              */
            byteLength: number;
        
            /**
              * The offset in bytes of the array.
              */
            byteOffset: number;
        
            /** 
              * Returns the this object after copying a section of the array identified by start and end
              * to the same array starting at position target
              * @param target If target is negative, it is treated as length+target where length is the 
              * length of the array. 
              * @param start If start is negative, it is treated as length+start. If end is negative, it 
              * is treated as length+end.
              * @param end If not specified, length of the this object is used as its default value. 
              */
            copyWithin(target: number, start: number, end?: number): Float64Array;
        
            /**
              * Determines whether all the members of an array satisfy the specified test.
              * @param callbackfn A function that accepts up to three arguments. The every method calls 
              * the callbackfn function for each element in array1 until the callbackfn returns false, 
              * or until the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function.
              * If thisArg is omitted, undefined is used as the this value.
              */
            every(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): boolean;
        
            /**
                * Returns the this object after filling the section identified by start and end with value
                * @param value value to fill array section with
                * @param start index to start filling the array at. If start is negative, it is treated as 
                * length+start where length is the length of the array. 
                * @param end index to stop filling the array at. If end is negative, it is treated as 
                * length+end.
                */
            fill(value: number, start?: number, end?: number): Float64Array;
        
            /**
              * Returns the elements of an array that meet the condition specified in a callback function. 
              * @param callbackfn A function that accepts up to three arguments. The filter method calls 
              * the callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            filter(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): Float64Array;
        
            /** 
              * Returns the value of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
        
            /** 
              * Returns the index of the first element in the array where predicate is true, and undefined 
              * otherwise.
              * @param predicate find calls predicate once for each element of the array, in ascending 
              * order, until it finds one where predicate returns true. If such an element is found, find 
              * immediately returns that element value. Otherwise, find returns undefined.
              * @param thisArg If provided, it will be used as the this value for each invocation of 
              * predicate. If it is not provided, undefined is used instead.
              */
            findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
        
            /**
              * Performs the specified action for each element in an array.
              * @param callbackfn  A function that accepts up to three arguments. forEach calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg  An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            forEach(callbackfn: (value: number, index: number, array: Float64Array) => void, thisArg?: any): void;
        
            /**
              * Returns the index of the first occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
              *  search starts at index 0.
              */
            indexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * Adds all the elements of an array separated by the specified separator string.
              * @param separator A string used to separate one element of an array from the next in the 
              * resulting String. If omitted, the array elements are separated with a comma.
              */
            join(separator?: string): string;
        
            /**
              * Returns the index of the last occurrence of a value in an array.
              * @param searchElement The value to locate in the array.
              * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the 
              * search starts at index 0.
              */
            lastIndexOf(searchElement: number, fromIndex?: number): number;
        
            /**
              * The length of the array.
              */
            length: number;
        
            /**
              * Calls a defined callback function on each element of an array, and returns an array that 
              * contains the results.
              * @param callbackfn A function that accepts up to three arguments. The map method calls the 
              * callbackfn function one time for each element in the array. 
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            map(callbackfn: (value: number, index: number, array: Float64Array) => number, thisArg?: any): Float64Array;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue?: number): number;
        
            /**
              * Calls the specified callback function for all the elements in an array. The return value of 
              * the callback function is the accumulated result, and is provided as an argument in the next 
              * call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduce method calls the 
              * callbackfn function one time for each element in the array.
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument 
              * instead of an array value.
              */
            reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float64Array) => U, initialValue: U): U;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls 
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an 
              * argument instead of an array value.
              */
            reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue?: number): number;
        
            /** 
              * Calls the specified callback function for all the elements in an array, in descending order. 
              * The return value of the callback function is the accumulated result, and is provided as an 
              * argument in the next call to the callback function.
              * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
              * the callbackfn function one time for each element in the array. 
              * @param initialValue If initialValue is specified, it is used as the initial value to start 
              * the accumulation. The first call to the callbackfn function provides this value as an argument
              * instead of an array value.
              */
            reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float64Array) => U, initialValue: U): U;
        
            /**
              * Reverses the elements in an Array. 
              */
            reverse(): Float64Array;
        
            /**
              * Sets a value or an array of values.
              * @param index The index of the location to set.
              * @param value The value to set.
              */
            set(index: number, value: number): void;
        
            /**
              * Sets a value or an array of values.
              * @param array A typed or untyped array of values to set.
              * @param offset The index in the current array at which the values are to be written.
              */
            set(array: Float64Array, offset?: number): void;
        
            /** 
              * Returns a section of an array.
              * @param start The beginning of the specified portion of the array.
              * @param end The end of the specified portion of the array.
              */
            slice(start?: number, end?: number): Float64Array;
        
            /**
              * Determines whether the specified callback function returns true for any element of an array.
              * @param callbackfn A function that accepts up to three arguments. The some method calls the 
              * callbackfn function for each element in array1 until the callbackfn returns true, or until 
              * the end of the array.
              * @param thisArg An object to which the this keyword can refer in the callbackfn function. 
              * If thisArg is omitted, undefined is used as the this value.
              */
            some(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): boolean;
        
            /**
              * Sorts an array.
              * @param compareFn The name of the function used to determine the order of the elements. If 
              * omitted, the elements are sorted in ascending, ASCII character order.
              */
            sort(compareFn?: (a: number, b: number) => number): Float64Array;
        
            /**
              * Gets a new Float64Array view of the ArrayBuffer store for this array, referencing the elements
              * at begin, inclusive, up to end, exclusive. 
              * @param begin The index of the beginning of the array.
              * @param end The index of the end of the array.
              */
            subarray(begin: number, end?: number): Float64Array;
        
            /**
              * Converts a number to a string by using the current locale. 
              */
            toLocaleString(): string;
        
            /**
              * Returns a string representation of an array.
              */
            toString(): string;
        
            [index: number]: number;
        }
        
        interface Float64ArrayConstructor {
            prototype: Float64Array;
            new (length: number): Float64Array;
            new (array: Float64Array): Float64Array;
            new (array: number[]): Float64Array;
            new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Float64Array;
        
            /**
              * The size in bytes of each element in the array. 
              */
            BYTES_PER_ELEMENT: number;
        
            /**
              * Returns a new array from a set of elements.
              * @param items A set of elements to include in the new array object.
              */
            of(...items: number[]): Float64Array;
        }
        declare var Float64Array: Float64ArrayConstructor;
      • typescriptServices.js
        /*! *****************************************************************************
        Copyright (c) Microsoft Corporation. All rights reserved. 
        Licensed under the Apache License, Version 2.0 (the "License"); you may not use
        this file except in compliance with the License. You may obtain a copy of the
        License at http://www.apache.org/licenses/LICENSE-2.0  
         
        THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
        KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
        WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
        MERCHANTABLITY OR NON-INFRINGEMENT. 
         
        See the Apache Version 2.0 License for specific language governing permissions
        and limitations under the License.
        ***************************************************************************** */
        
        var ts;
        (function (ts) {
            // token > SyntaxKind.Identifer => token is a keyword
            (function (SyntaxKind) {
                SyntaxKind[SyntaxKind["Unknown"] = 0] = "Unknown";
                SyntaxKind[SyntaxKind["EndOfFileToken"] = 1] = "EndOfFileToken";
                SyntaxKind[SyntaxKind["SingleLineCommentTrivia"] = 2] = "SingleLineCommentTrivia";
                SyntaxKind[SyntaxKind["MultiLineCommentTrivia"] = 3] = "MultiLineCommentTrivia";
                SyntaxKind[SyntaxKind["NewLineTrivia"] = 4] = "NewLineTrivia";
                SyntaxKind[SyntaxKind["WhitespaceTrivia"] = 5] = "WhitespaceTrivia";
                // We detect and provide better error recovery when we encounter a git merge marker.  This
                // allows us to edit files with git-conflict markers in them in a much more pleasant manner.
                SyntaxKind[SyntaxKind["ConflictMarkerTrivia"] = 6] = "ConflictMarkerTrivia";
                // Literals
                SyntaxKind[SyntaxKind["NumericLiteral"] = 7] = "NumericLiteral";
                SyntaxKind[SyntaxKind["StringLiteral"] = 8] = "StringLiteral";
                SyntaxKind[SyntaxKind["RegularExpressionLiteral"] = 9] = "RegularExpressionLiteral";
                SyntaxKind[SyntaxKind["NoSubstitutionTemplateLiteral"] = 10] = "NoSubstitutionTemplateLiteral";
                // Pseudo-literals
                SyntaxKind[SyntaxKind["TemplateHead"] = 11] = "TemplateHead";
                SyntaxKind[SyntaxKind["TemplateMiddle"] = 12] = "TemplateMiddle";
                SyntaxKind[SyntaxKind["TemplateTail"] = 13] = "TemplateTail";
                // Punctuation
                SyntaxKind[SyntaxKind["OpenBraceToken"] = 14] = "OpenBraceToken";
                SyntaxKind[SyntaxKind["CloseBraceToken"] = 15] = "CloseBraceToken";
                SyntaxKind[SyntaxKind["OpenParenToken"] = 16] = "OpenParenToken";
                SyntaxKind[SyntaxKind["CloseParenToken"] = 17] = "CloseParenToken";
                SyntaxKind[SyntaxKind["OpenBracketToken"] = 18] = "OpenBracketToken";
                SyntaxKind[SyntaxKind["CloseBracketToken"] = 19] = "CloseBracketToken";
                SyntaxKind[SyntaxKind["DotToken"] = 20] = "DotToken";
                SyntaxKind[SyntaxKind["DotDotDotToken"] = 21] = "DotDotDotToken";
                SyntaxKind[SyntaxKind["SemicolonToken"] = 22] = "SemicolonToken";
                SyntaxKind[SyntaxKind["CommaToken"] = 23] = "CommaToken";
                SyntaxKind[SyntaxKind["LessThanToken"] = 24] = "LessThanToken";
                SyntaxKind[SyntaxKind["GreaterThanToken"] = 25] = "GreaterThanToken";
                SyntaxKind[SyntaxKind["LessThanEqualsToken"] = 26] = "LessThanEqualsToken";
                SyntaxKind[SyntaxKind["GreaterThanEqualsToken"] = 27] = "GreaterThanEqualsToken";
                SyntaxKind[SyntaxKind["EqualsEqualsToken"] = 28] = "EqualsEqualsToken";
                SyntaxKind[SyntaxKind["ExclamationEqualsToken"] = 29] = "ExclamationEqualsToken";
                SyntaxKind[SyntaxKind["EqualsEqualsEqualsToken"] = 30] = "EqualsEqualsEqualsToken";
                SyntaxKind[SyntaxKind["ExclamationEqualsEqualsToken"] = 31] = "ExclamationEqualsEqualsToken";
                SyntaxKind[SyntaxKind["EqualsGreaterThanToken"] = 32] = "EqualsGreaterThanToken";
                SyntaxKind[SyntaxKind["PlusToken"] = 33] = "PlusToken";
                SyntaxKind[SyntaxKind["MinusToken"] = 34] = "MinusToken";
                SyntaxKind[SyntaxKind["AsteriskToken"] = 35] = "AsteriskToken";
                SyntaxKind[SyntaxKind["SlashToken"] = 36] = "SlashToken";
                SyntaxKind[SyntaxKind["PercentToken"] = 37] = "PercentToken";
                SyntaxKind[SyntaxKind["PlusPlusToken"] = 38] = "PlusPlusToken";
                SyntaxKind[SyntaxKind["MinusMinusToken"] = 39] = "MinusMinusToken";
                SyntaxKind[SyntaxKind["LessThanLessThanToken"] = 40] = "LessThanLessThanToken";
                SyntaxKind[SyntaxKind["GreaterThanGreaterThanToken"] = 41] = "GreaterThanGreaterThanToken";
                SyntaxKind[SyntaxKind["GreaterThanGreaterThanGreaterThanToken"] = 42] = "GreaterThanGreaterThanGreaterThanToken";
                SyntaxKind[SyntaxKind["AmpersandToken"] = 43] = "AmpersandToken";
                SyntaxKind[SyntaxKind["BarToken"] = 44] = "BarToken";
                SyntaxKind[SyntaxKind["CaretToken"] = 45] = "CaretToken";
                SyntaxKind[SyntaxKind["ExclamationToken"] = 46] = "ExclamationToken";
                SyntaxKind[SyntaxKind["TildeToken"] = 47] = "TildeToken";
                SyntaxKind[SyntaxKind["AmpersandAmpersandToken"] = 48] = "AmpersandAmpersandToken";
                SyntaxKind[SyntaxKind["BarBarToken"] = 49] = "BarBarToken";
                SyntaxKind[SyntaxKind["QuestionToken"] = 50] = "QuestionToken";
                SyntaxKind[SyntaxKind["ColonToken"] = 51] = "ColonToken";
                SyntaxKind[SyntaxKind["AtToken"] = 52] = "AtToken";
                // Assignments
                SyntaxKind[SyntaxKind["EqualsToken"] = 53] = "EqualsToken";
                SyntaxKind[SyntaxKind["PlusEqualsToken"] = 54] = "PlusEqualsToken";
                SyntaxKind[SyntaxKind["MinusEqualsToken"] = 55] = "MinusEqualsToken";
                SyntaxKind[SyntaxKind["AsteriskEqualsToken"] = 56] = "AsteriskEqualsToken";
                SyntaxKind[SyntaxKind["SlashEqualsToken"] = 57] = "SlashEqualsToken";
                SyntaxKind[SyntaxKind["PercentEqualsToken"] = 58] = "PercentEqualsToken";
                SyntaxKind[SyntaxKind["LessThanLessThanEqualsToken"] = 59] = "LessThanLessThanEqualsToken";
                SyntaxKind[SyntaxKind["GreaterThanGreaterThanEqualsToken"] = 60] = "GreaterThanGreaterThanEqualsToken";
                SyntaxKind[SyntaxKind["GreaterThanGreaterThanGreaterThanEqualsToken"] = 61] = "GreaterThanGreaterThanGreaterThanEqualsToken";
                SyntaxKind[SyntaxKind["AmpersandEqualsToken"] = 62] = "AmpersandEqualsToken";
                SyntaxKind[SyntaxKind["BarEqualsToken"] = 63] = "BarEqualsToken";
                SyntaxKind[SyntaxKind["CaretEqualsToken"] = 64] = "CaretEqualsToken";
                // Identifiers
                SyntaxKind[SyntaxKind["Identifier"] = 65] = "Identifier";
                // Reserved words
                SyntaxKind[SyntaxKind["BreakKeyword"] = 66] = "BreakKeyword";
                SyntaxKind[SyntaxKind["CaseKeyword"] = 67] = "CaseKeyword";
                SyntaxKind[SyntaxKind["CatchKeyword"] = 68] = "CatchKeyword";
                SyntaxKind[SyntaxKind["ClassKeyword"] = 69] = "ClassKeyword";
                SyntaxKind[SyntaxKind["ConstKeyword"] = 70] = "ConstKeyword";
                SyntaxKind[SyntaxKind["ContinueKeyword"] = 71] = "ContinueKeyword";
                SyntaxKind[SyntaxKind["DebuggerKeyword"] = 72] = "DebuggerKeyword";
                SyntaxKind[SyntaxKind["DefaultKeyword"] = 73] = "DefaultKeyword";
                SyntaxKind[SyntaxKind["DeleteKeyword"] = 74] = "DeleteKeyword";
                SyntaxKind[SyntaxKind["DoKeyword"] = 75] = "DoKeyword";
                SyntaxKind[SyntaxKind["ElseKeyword"] = 76] = "ElseKeyword";
                SyntaxKind[SyntaxKind["EnumKeyword"] = 77] = "EnumKeyword";
                SyntaxKind[SyntaxKind["ExportKeyword"] = 78] = "ExportKeyword";
                SyntaxKind[SyntaxKind["ExtendsKeyword"] = 79] = "ExtendsKeyword";
                SyntaxKind[SyntaxKind["FalseKeyword"] = 80] = "FalseKeyword";
                SyntaxKind[SyntaxKind["FinallyKeyword"] = 81] = "FinallyKeyword";
                SyntaxKind[SyntaxKind["ForKeyword"] = 82] = "ForKeyword";
                SyntaxKind[SyntaxKind["FunctionKeyword"] = 83] = "FunctionKeyword";
                SyntaxKind[SyntaxKind["IfKeyword"] = 84] = "IfKeyword";
                SyntaxKind[SyntaxKind["ImportKeyword"] = 85] = "ImportKeyword";
                SyntaxKind[SyntaxKind["InKeyword"] = 86] = "InKeyword";
                SyntaxKind[SyntaxKind["InstanceOfKeyword"] = 87] = "InstanceOfKeyword";
                SyntaxKind[SyntaxKind["NewKeyword"] = 88] = "NewKeyword";
                SyntaxKind[SyntaxKind["NullKeyword"] = 89] = "NullKeyword";
                SyntaxKind[SyntaxKind["ReturnKeyword"] = 90] = "ReturnKeyword";
                SyntaxKind[SyntaxKind["SuperKeyword"] = 91] = "SuperKeyword";
                SyntaxKind[SyntaxKind["SwitchKeyword"] = 92] = "SwitchKeyword";
                SyntaxKind[SyntaxKind["ThisKeyword"] = 93] = "ThisKeyword";
                SyntaxKind[SyntaxKind["ThrowKeyword"] = 94] = "ThrowKeyword";
                SyntaxKind[SyntaxKind["TrueKeyword"] = 95] = "TrueKeyword";
                SyntaxKind[SyntaxKind["TryKeyword"] = 96] = "TryKeyword";
                SyntaxKind[SyntaxKind["TypeOfKeyword"] = 97] = "TypeOfKeyword";
                SyntaxKind[SyntaxKind["VarKeyword"] = 98] = "VarKeyword";
                SyntaxKind[SyntaxKind["VoidKeyword"] = 99] = "VoidKeyword";
                SyntaxKind[SyntaxKind["WhileKeyword"] = 100] = "WhileKeyword";
                SyntaxKind[SyntaxKind["WithKeyword"] = 101] = "WithKeyword";
                // Strict mode reserved words
                SyntaxKind[SyntaxKind["ImplementsKeyword"] = 102] = "ImplementsKeyword";
                SyntaxKind[SyntaxKind["InterfaceKeyword"] = 103] = "InterfaceKeyword";
                SyntaxKind[SyntaxKind["LetKeyword"] = 104] = "LetKeyword";
                SyntaxKind[SyntaxKind["PackageKeyword"] = 105] = "PackageKeyword";
                SyntaxKind[SyntaxKind["PrivateKeyword"] = 106] = "PrivateKeyword";
                SyntaxKind[SyntaxKind["ProtectedKeyword"] = 107] = "ProtectedKeyword";
                SyntaxKind[SyntaxKind["PublicKeyword"] = 108] = "PublicKeyword";
                SyntaxKind[SyntaxKind["StaticKeyword"] = 109] = "StaticKeyword";
                SyntaxKind[SyntaxKind["YieldKeyword"] = 110] = "YieldKeyword";
                // Contextual keywords
                SyntaxKind[SyntaxKind["AsKeyword"] = 111] = "AsKeyword";
                SyntaxKind[SyntaxKind["AnyKeyword"] = 112] = "AnyKeyword";
                SyntaxKind[SyntaxKind["BooleanKeyword"] = 113] = "BooleanKeyword";
                SyntaxKind[SyntaxKind["ConstructorKeyword"] = 114] = "ConstructorKeyword";
                SyntaxKind[SyntaxKind["DeclareKeyword"] = 115] = "DeclareKeyword";
                SyntaxKind[SyntaxKind["GetKeyword"] = 116] = "GetKeyword";
                SyntaxKind[SyntaxKind["ModuleKeyword"] = 117] = "ModuleKeyword";
                SyntaxKind[SyntaxKind["RequireKeyword"] = 118] = "RequireKeyword";
                SyntaxKind[SyntaxKind["NumberKeyword"] = 119] = "NumberKeyword";
                SyntaxKind[SyntaxKind["SetKeyword"] = 120] = "SetKeyword";
                SyntaxKind[SyntaxKind["StringKeyword"] = 121] = "StringKeyword";
                SyntaxKind[SyntaxKind["SymbolKeyword"] = 122] = "SymbolKeyword";
                SyntaxKind[SyntaxKind["TypeKeyword"] = 123] = "TypeKeyword";
                SyntaxKind[SyntaxKind["FromKeyword"] = 124] = "FromKeyword";
                SyntaxKind[SyntaxKind["OfKeyword"] = 125] = "OfKeyword";
                // Parse tree nodes
                // Names
                SyntaxKind[SyntaxKind["QualifiedName"] = 126] = "QualifiedName";
                SyntaxKind[SyntaxKind["ComputedPropertyName"] = 127] = "ComputedPropertyName";
                // Signature elements
                SyntaxKind[SyntaxKind["TypeParameter"] = 128] = "TypeParameter";
                SyntaxKind[SyntaxKind["Parameter"] = 129] = "Parameter";
                SyntaxKind[SyntaxKind["Decorator"] = 130] = "Decorator";
                // TypeMember
                SyntaxKind[SyntaxKind["PropertySignature"] = 131] = "PropertySignature";
                SyntaxKind[SyntaxKind["PropertyDeclaration"] = 132] = "PropertyDeclaration";
                SyntaxKind[SyntaxKind["MethodSignature"] = 133] = "MethodSignature";
                SyntaxKind[SyntaxKind["MethodDeclaration"] = 134] = "MethodDeclaration";
                SyntaxKind[SyntaxKind["Constructor"] = 135] = "Constructor";
                SyntaxKind[SyntaxKind["GetAccessor"] = 136] = "GetAccessor";
                SyntaxKind[SyntaxKind["SetAccessor"] = 137] = "SetAccessor";
                SyntaxKind[SyntaxKind["CallSignature"] = 138] = "CallSignature";
                SyntaxKind[SyntaxKind["ConstructSignature"] = 139] = "ConstructSignature";
                SyntaxKind[SyntaxKind["IndexSignature"] = 140] = "IndexSignature";
                // Type
                SyntaxKind[SyntaxKind["TypeReference"] = 141] = "TypeReference";
                SyntaxKind[SyntaxKind["FunctionType"] = 142] = "FunctionType";
                SyntaxKind[SyntaxKind["ConstructorType"] = 143] = "ConstructorType";
                SyntaxKind[SyntaxKind["TypeQuery"] = 144] = "TypeQuery";
                SyntaxKind[SyntaxKind["TypeLiteral"] = 145] = "TypeLiteral";
                SyntaxKind[SyntaxKind["ArrayType"] = 146] = "ArrayType";
                SyntaxKind[SyntaxKind["TupleType"] = 147] = "TupleType";
                SyntaxKind[SyntaxKind["UnionType"] = 148] = "UnionType";
                SyntaxKind[SyntaxKind["ParenthesizedType"] = 149] = "ParenthesizedType";
                // Binding patterns
                SyntaxKind[SyntaxKind["ObjectBindingPattern"] = 150] = "ObjectBindingPattern";
                SyntaxKind[SyntaxKind["ArrayBindingPattern"] = 151] = "ArrayBindingPattern";
                SyntaxKind[SyntaxKind["BindingElement"] = 152] = "BindingElement";
                // Expression
                SyntaxKind[SyntaxKind["ArrayLiteralExpression"] = 153] = "ArrayLiteralExpression";
                SyntaxKind[SyntaxKind["ObjectLiteralExpression"] = 154] = "ObjectLiteralExpression";
                SyntaxKind[SyntaxKind["PropertyAccessExpression"] = 155] = "PropertyAccessExpression";
                SyntaxKind[SyntaxKind["ElementAccessExpression"] = 156] = "ElementAccessExpression";
                SyntaxKind[SyntaxKind["CallExpression"] = 157] = "CallExpression";
                SyntaxKind[SyntaxKind["NewExpression"] = 158] = "NewExpression";
                SyntaxKind[SyntaxKind["TaggedTemplateExpression"] = 159] = "TaggedTemplateExpression";
                SyntaxKind[SyntaxKind["TypeAssertionExpression"] = 160] = "TypeAssertionExpression";
                SyntaxKind[SyntaxKind["ParenthesizedExpression"] = 161] = "ParenthesizedExpression";
                SyntaxKind[SyntaxKind["FunctionExpression"] = 162] = "FunctionExpression";
                SyntaxKind[SyntaxKind["ArrowFunction"] = 163] = "ArrowFunction";
                SyntaxKind[SyntaxKind["DeleteExpression"] = 164] = "DeleteExpression";
                SyntaxKind[SyntaxKind["TypeOfExpression"] = 165] = "TypeOfExpression";
                SyntaxKind[SyntaxKind["VoidExpression"] = 166] = "VoidExpression";
                SyntaxKind[SyntaxKind["PrefixUnaryExpression"] = 167] = "PrefixUnaryExpression";
                SyntaxKind[SyntaxKind["PostfixUnaryExpression"] = 168] = "PostfixUnaryExpression";
                SyntaxKind[SyntaxKind["BinaryExpression"] = 169] = "BinaryExpression";
                SyntaxKind[SyntaxKind["ConditionalExpression"] = 170] = "ConditionalExpression";
                SyntaxKind[SyntaxKind["TemplateExpression"] = 171] = "TemplateExpression";
                SyntaxKind[SyntaxKind["YieldExpression"] = 172] = "YieldExpression";
                SyntaxKind[SyntaxKind["SpreadElementExpression"] = 173] = "SpreadElementExpression";
                SyntaxKind[SyntaxKind["ClassExpression"] = 174] = "ClassExpression";
                SyntaxKind[SyntaxKind["OmittedExpression"] = 175] = "OmittedExpression";
                // Misc
                SyntaxKind[SyntaxKind["TemplateSpan"] = 176] = "TemplateSpan";
                SyntaxKind[SyntaxKind["HeritageClauseElement"] = 177] = "HeritageClauseElement";
                SyntaxKind[SyntaxKind["SemicolonClassElement"] = 178] = "SemicolonClassElement";
                // Element
                SyntaxKind[SyntaxKind["Block"] = 179] = "Block";
                SyntaxKind[SyntaxKind["VariableStatement"] = 180] = "VariableStatement";
                SyntaxKind[SyntaxKind["EmptyStatement"] = 181] = "EmptyStatement";
                SyntaxKind[SyntaxKind["ExpressionStatement"] = 182] = "ExpressionStatement";
                SyntaxKind[SyntaxKind["IfStatement"] = 183] = "IfStatement";
                SyntaxKind[SyntaxKind["DoStatement"] = 184] = "DoStatement";
                SyntaxKind[SyntaxKind["WhileStatement"] = 185] = "WhileStatement";
                SyntaxKind[SyntaxKind["ForStatement"] = 186] = "ForStatement";
                SyntaxKind[SyntaxKind["ForInStatement"] = 187] = "ForInStatement";
                SyntaxKind[SyntaxKind["ForOfStatement"] = 188] = "ForOfStatement";
                SyntaxKind[SyntaxKind["ContinueStatement"] = 189] = "ContinueStatement";
                SyntaxKind[SyntaxKind["BreakStatement"] = 190] = "BreakStatement";
                SyntaxKind[SyntaxKind["ReturnStatement"] = 191] = "ReturnStatement";
                SyntaxKind[SyntaxKind["WithStatement"] = 192] = "WithStatement";
                SyntaxKind[SyntaxKind["SwitchStatement"] = 193] = "SwitchStatement";
                SyntaxKind[SyntaxKind["LabeledStatement"] = 194] = "LabeledStatement";
                SyntaxKind[SyntaxKind["ThrowStatement"] = 195] = "ThrowStatement";
                SyntaxKind[SyntaxKind["TryStatement"] = 196] = "TryStatement";
                SyntaxKind[SyntaxKind["DebuggerStatement"] = 197] = "DebuggerStatement";
                SyntaxKind[SyntaxKind["VariableDeclaration"] = 198] = "VariableDeclaration";
                SyntaxKind[SyntaxKind["VariableDeclarationList"] = 199] = "VariableDeclarationList";
                SyntaxKind[SyntaxKind["FunctionDeclaration"] = 200] = "FunctionDeclaration";
                SyntaxKind[SyntaxKind["ClassDeclaration"] = 201] = "ClassDeclaration";
                SyntaxKind[SyntaxKind["InterfaceDeclaration"] = 202] = "InterfaceDeclaration";
                SyntaxKind[SyntaxKind["TypeAliasDeclaration"] = 203] = "TypeAliasDeclaration";
                SyntaxKind[SyntaxKind["EnumDeclaration"] = 204] = "EnumDeclaration";
                SyntaxKind[SyntaxKind["ModuleDeclaration"] = 205] = "ModuleDeclaration";
                SyntaxKind[SyntaxKind["ModuleBlock"] = 206] = "ModuleBlock";
                SyntaxKind[SyntaxKind["CaseBlock"] = 207] = "CaseBlock";
                SyntaxKind[SyntaxKind["ImportEqualsDeclaration"] = 208] = "ImportEqualsDeclaration";
                SyntaxKind[SyntaxKind["ImportDeclaration"] = 209] = "ImportDeclaration";
                SyntaxKind[SyntaxKind["ImportClause"] = 210] = "ImportClause";
                SyntaxKind[SyntaxKind["NamespaceImport"] = 211] = "NamespaceImport";
                SyntaxKind[SyntaxKind["NamedImports"] = 212] = "NamedImports";
                SyntaxKind[SyntaxKind["ImportSpecifier"] = 213] = "ImportSpecifier";
                SyntaxKind[SyntaxKind["ExportAssignment"] = 214] = "ExportAssignment";
                SyntaxKind[SyntaxKind["ExportDeclaration"] = 215] = "ExportDeclaration";
                SyntaxKind[SyntaxKind["NamedExports"] = 216] = "NamedExports";
                SyntaxKind[SyntaxKind["ExportSpecifier"] = 217] = "ExportSpecifier";
                SyntaxKind[SyntaxKind["MissingDeclaration"] = 218] = "MissingDeclaration";
                // Module references
                SyntaxKind[SyntaxKind["ExternalModuleReference"] = 219] = "ExternalModuleReference";
                // Clauses
                SyntaxKind[SyntaxKind["CaseClause"] = 220] = "CaseClause";
                SyntaxKind[SyntaxKind["DefaultClause"] = 221] = "DefaultClause";
                SyntaxKind[SyntaxKind["HeritageClause"] = 222] = "HeritageClause";
                SyntaxKind[SyntaxKind["CatchClause"] = 223] = "CatchClause";
                // Property assignments
                SyntaxKind[SyntaxKind["PropertyAssignment"] = 224] = "PropertyAssignment";
                SyntaxKind[SyntaxKind["ShorthandPropertyAssignment"] = 225] = "ShorthandPropertyAssignment";
                // Enum
                SyntaxKind[SyntaxKind["EnumMember"] = 226] = "EnumMember";
                // Top-level nodes
                SyntaxKind[SyntaxKind["SourceFile"] = 227] = "SourceFile";
                // Synthesized list
                SyntaxKind[SyntaxKind["SyntaxList"] = 228] = "SyntaxList";
                // Enum value count
                SyntaxKind[SyntaxKind["Count"] = 229] = "Count";
                // Markers
                SyntaxKind[SyntaxKind["FirstAssignment"] = 53] = "FirstAssignment";
                SyntaxKind[SyntaxKind["LastAssignment"] = 64] = "LastAssignment";
                SyntaxKind[SyntaxKind["FirstReservedWord"] = 66] = "FirstReservedWord";
                SyntaxKind[SyntaxKind["LastReservedWord"] = 101] = "LastReservedWord";
                SyntaxKind[SyntaxKind["FirstKeyword"] = 66] = "FirstKeyword";
                SyntaxKind[SyntaxKind["LastKeyword"] = 125] = "LastKeyword";
                SyntaxKind[SyntaxKind["FirstFutureReservedWord"] = 102] = "FirstFutureReservedWord";
                SyntaxKind[SyntaxKind["LastFutureReservedWord"] = 110] = "LastFutureReservedWord";
                SyntaxKind[SyntaxKind["FirstTypeNode"] = 141] = "FirstTypeNode";
                SyntaxKind[SyntaxKind["LastTypeNode"] = 149] = "LastTypeNode";
                SyntaxKind[SyntaxKind["FirstPunctuation"] = 14] = "FirstPunctuation";
                SyntaxKind[SyntaxKind["LastPunctuation"] = 64] = "LastPunctuation";
                SyntaxKind[SyntaxKind["FirstToken"] = 0] = "FirstToken";
                SyntaxKind[SyntaxKind["LastToken"] = 125] = "LastToken";
                SyntaxKind[SyntaxKind["FirstTriviaToken"] = 2] = "FirstTriviaToken";
                SyntaxKind[SyntaxKind["LastTriviaToken"] = 6] = "LastTriviaToken";
                SyntaxKind[SyntaxKind["FirstLiteralToken"] = 7] = "FirstLiteralToken";
                SyntaxKind[SyntaxKind["LastLiteralToken"] = 10] = "LastLiteralToken";
                SyntaxKind[SyntaxKind["FirstTemplateToken"] = 10] = "FirstTemplateToken";
                SyntaxKind[SyntaxKind["LastTemplateToken"] = 13] = "LastTemplateToken";
                SyntaxKind[SyntaxKind["FirstBinaryOperator"] = 24] = "FirstBinaryOperator";
                SyntaxKind[SyntaxKind["LastBinaryOperator"] = 64] = "LastBinaryOperator";
                SyntaxKind[SyntaxKind["FirstNode"] = 126] = "FirstNode";
            })(ts.SyntaxKind || (ts.SyntaxKind = {}));
            var SyntaxKind = ts.SyntaxKind;
            (function (NodeFlags) {
                NodeFlags[NodeFlags["Export"] = 1] = "Export";
                NodeFlags[NodeFlags["Ambient"] = 2] = "Ambient";
                NodeFlags[NodeFlags["Public"] = 16] = "Public";
                NodeFlags[NodeFlags["Private"] = 32] = "Private";
                NodeFlags[NodeFlags["Protected"] = 64] = "Protected";
                NodeFlags[NodeFlags["Static"] = 128] = "Static";
                NodeFlags[NodeFlags["Default"] = 256] = "Default";
                NodeFlags[NodeFlags["MultiLine"] = 512] = "MultiLine";
                NodeFlags[NodeFlags["Synthetic"] = 1024] = "Synthetic";
                NodeFlags[NodeFlags["DeclarationFile"] = 2048] = "DeclarationFile";
                NodeFlags[NodeFlags["Let"] = 4096] = "Let";
                NodeFlags[NodeFlags["Const"] = 8192] = "Const";
                NodeFlags[NodeFlags["OctalLiteral"] = 16384] = "OctalLiteral";
                NodeFlags[NodeFlags["ExportContext"] = 32768] = "ExportContext";
                NodeFlags[NodeFlags["Modifier"] = 499] = "Modifier";
                NodeFlags[NodeFlags["AccessibilityModifier"] = 112] = "AccessibilityModifier";
                NodeFlags[NodeFlags["BlockScoped"] = 12288] = "BlockScoped";
            })(ts.NodeFlags || (ts.NodeFlags = {}));
            var NodeFlags = ts.NodeFlags;
            /* @internal */
            (function (ParserContextFlags) {
                // Set if this node was parsed in strict mode.  Used for grammar error checks, as well as
                // checking if the node can be reused in incremental settings.
                ParserContextFlags[ParserContextFlags["StrictMode"] = 1] = "StrictMode";
                // If this node was parsed in a context where 'in-expressions' are not allowed.
                ParserContextFlags[ParserContextFlags["DisallowIn"] = 2] = "DisallowIn";
                // If this node was parsed in the 'yield' context created when parsing a generator.
                ParserContextFlags[ParserContextFlags["Yield"] = 4] = "Yield";
                // If this node was parsed in the parameters of a generator.
                ParserContextFlags[ParserContextFlags["GeneratorParameter"] = 8] = "GeneratorParameter";
                // If this node was parsed as part of a decorator
                ParserContextFlags[ParserContextFlags["Decorator"] = 16] = "Decorator";
                // If the parser encountered an error when parsing the code that created this node.  Note
                // the parser only sets this directly on the node it creates right after encountering the
                // error.
                ParserContextFlags[ParserContextFlags["ThisNodeHasError"] = 32] = "ThisNodeHasError";
                // Context flags set directly by the parser.
                ParserContextFlags[ParserContextFlags["ParserGeneratedFlags"] = 63] = "ParserGeneratedFlags";
                // Context flags computed by aggregating child flags upwards.
                // Used during incremental parsing to determine if this node or any of its children had an
                // error.  Computed only once and then cached.
                ParserContextFlags[ParserContextFlags["ThisNodeOrAnySubNodesHasError"] = 64] = "ThisNodeOrAnySubNodesHasError";
                // Used to know if we've computed data from children and cached it in this node.
                ParserContextFlags[ParserContextFlags["HasAggregatedChildData"] = 128] = "HasAggregatedChildData";
            })(ts.ParserContextFlags || (ts.ParserContextFlags = {}));
            var ParserContextFlags = ts.ParserContextFlags;
            /* @internal */
            (function (RelationComparisonResult) {
                RelationComparisonResult[RelationComparisonResult["Succeeded"] = 1] = "Succeeded";
                RelationComparisonResult[RelationComparisonResult["Failed"] = 2] = "Failed";
                RelationComparisonResult[RelationComparisonResult["FailedAndReported"] = 3] = "FailedAndReported";
            })(ts.RelationComparisonResult || (ts.RelationComparisonResult = {}));
            var RelationComparisonResult = ts.RelationComparisonResult;
            /** Return code used by getEmitOutput function to indicate status of the function */
            (function (ExitStatus) {
                // Compiler ran successfully.  Either this was a simple do-nothing compilation (for example,
                // when -version or -help was provided, or this was a normal compilation, no diagnostics
                // were produced, and all outputs were generated successfully.
                ExitStatus[ExitStatus["Success"] = 0] = "Success";
                // Diagnostics were produced and because of them no code was generated.
                ExitStatus[ExitStatus["DiagnosticsPresent_OutputsSkipped"] = 1] = "DiagnosticsPresent_OutputsSkipped";
                // Diagnostics were produced and outputs were generated in spite of them.
                ExitStatus[ExitStatus["DiagnosticsPresent_OutputsGenerated"] = 2] = "DiagnosticsPresent_OutputsGenerated";
            })(ts.ExitStatus || (ts.ExitStatus = {}));
            var ExitStatus = ts.ExitStatus;
            (function (TypeFormatFlags) {
                TypeFormatFlags[TypeFormatFlags["None"] = 0] = "None";
                TypeFormatFlags[TypeFormatFlags["WriteArrayAsGenericType"] = 1] = "WriteArrayAsGenericType";
                TypeFormatFlags[TypeFormatFlags["UseTypeOfFunction"] = 2] = "UseTypeOfFunction";
                TypeFormatFlags[TypeFormatFlags["NoTruncation"] = 4] = "NoTruncation";
                TypeFormatFlags[TypeFormatFlags["WriteArrowStyleSignature"] = 8] = "WriteArrowStyleSignature";
                TypeFormatFlags[TypeFormatFlags["WriteOwnNameForAnyLike"] = 16] = "WriteOwnNameForAnyLike";
                TypeFormatFlags[TypeFormatFlags["WriteTypeArgumentsOfSignature"] = 32] = "WriteTypeArgumentsOfSignature";
                TypeFormatFlags[TypeFormatFlags["InElementType"] = 64] = "InElementType";
                TypeFormatFlags[TypeFormatFlags["UseFullyQualifiedType"] = 128] = "UseFullyQualifiedType";
            })(ts.TypeFormatFlags || (ts.TypeFormatFlags = {}));
            var TypeFormatFlags = ts.TypeFormatFlags;
            (function (SymbolFormatFlags) {
                SymbolFormatFlags[SymbolFormatFlags["None"] = 0] = "None";
                // Write symbols's type argument if it is instantiated symbol
                // eg. class C<T> { p: T }   <-- Show p as C<T>.p here
                //     var a: C<number>;
                //     var p = a.p;  <--- Here p is property of C<number> so show it as C<number>.p instead of just C.p
                SymbolFormatFlags[SymbolFormatFlags["WriteTypeParametersOrArguments"] = 1] = "WriteTypeParametersOrArguments";
                // Use only external alias information to get the symbol name in the given context
                // eg.  module m { export class c { } } import x = m.c;
                // When this flag is specified m.c will be used to refer to the class instead of alias symbol x
                SymbolFormatFlags[SymbolFormatFlags["UseOnlyExternalAliasing"] = 2] = "UseOnlyExternalAliasing";
            })(ts.SymbolFormatFlags || (ts.SymbolFormatFlags = {}));
            var SymbolFormatFlags = ts.SymbolFormatFlags;
            /* @internal */
            (function (SymbolAccessibility) {
                SymbolAccessibility[SymbolAccessibility["Accessible"] = 0] = "Accessible";
                SymbolAccessibility[SymbolAccessibility["NotAccessible"] = 1] = "NotAccessible";
                SymbolAccessibility[SymbolAccessibility["CannotBeNamed"] = 2] = "CannotBeNamed";
            })(ts.SymbolAccessibility || (ts.SymbolAccessibility = {}));
            var SymbolAccessibility = ts.SymbolAccessibility;
            (function (SymbolFlags) {
                SymbolFlags[SymbolFlags["FunctionScopedVariable"] = 1] = "FunctionScopedVariable";
                SymbolFlags[SymbolFlags["BlockScopedVariable"] = 2] = "BlockScopedVariable";
                SymbolFlags[SymbolFlags["Property"] = 4] = "Property";
                SymbolFlags[SymbolFlags["EnumMember"] = 8] = "EnumMember";
                SymbolFlags[SymbolFlags["Function"] = 16] = "Function";
                SymbolFlags[SymbolFlags["Class"] = 32] = "Class";
                SymbolFlags[SymbolFlags["Interface"] = 64] = "Interface";
                SymbolFlags[SymbolFlags["ConstEnum"] = 128] = "ConstEnum";
                SymbolFlags[SymbolFlags["RegularEnum"] = 256] = "RegularEnum";
                SymbolFlags[SymbolFlags["ValueModule"] = 512] = "ValueModule";
                SymbolFlags[SymbolFlags["NamespaceModule"] = 1024] = "NamespaceModule";
                SymbolFlags[SymbolFlags["TypeLiteral"] = 2048] = "TypeLiteral";
                SymbolFlags[SymbolFlags["ObjectLiteral"] = 4096] = "ObjectLiteral";
                SymbolFlags[SymbolFlags["Method"] = 8192] = "Method";
                SymbolFlags[SymbolFlags["Constructor"] = 16384] = "Constructor";
                SymbolFlags[SymbolFlags["GetAccessor"] = 32768] = "GetAccessor";
                SymbolFlags[SymbolFlags["SetAccessor"] = 65536] = "SetAccessor";
                SymbolFlags[SymbolFlags["Signature"] = 131072] = "Signature";
                SymbolFlags[SymbolFlags["TypeParameter"] = 262144] = "TypeParameter";
                SymbolFlags[SymbolFlags["TypeAlias"] = 524288] = "TypeAlias";
                SymbolFlags[SymbolFlags["ExportValue"] = 1048576] = "ExportValue";
                SymbolFlags[SymbolFlags["ExportType"] = 2097152] = "ExportType";
                SymbolFlags[SymbolFlags["ExportNamespace"] = 4194304] = "ExportNamespace";
                SymbolFlags[SymbolFlags["Alias"] = 8388608] = "Alias";
                SymbolFlags[SymbolFlags["Instantiated"] = 16777216] = "Instantiated";
                SymbolFlags[SymbolFlags["Merged"] = 33554432] = "Merged";
                SymbolFlags[SymbolFlags["Transient"] = 67108864] = "Transient";
                SymbolFlags[SymbolFlags["Prototype"] = 134217728] = "Prototype";
                SymbolFlags[SymbolFlags["UnionProperty"] = 268435456] = "UnionProperty";
                SymbolFlags[SymbolFlags["Optional"] = 536870912] = "Optional";
                SymbolFlags[SymbolFlags["ExportStar"] = 1073741824] = "ExportStar";
                SymbolFlags[SymbolFlags["Enum"] = 384] = "Enum";
                SymbolFlags[SymbolFlags["Variable"] = 3] = "Variable";
                SymbolFlags[SymbolFlags["Value"] = 107455] = "Value";
                SymbolFlags[SymbolFlags["Type"] = 793056] = "Type";
                SymbolFlags[SymbolFlags["Namespace"] = 1536] = "Namespace";
                SymbolFlags[SymbolFlags["Module"] = 1536] = "Module";
                SymbolFlags[SymbolFlags["Accessor"] = 98304] = "Accessor";
                // Variables can be redeclared, but can not redeclare a block-scoped declaration with the
                // same name, or any other value that is not a variable, e.g. ValueModule or Class
                SymbolFlags[SymbolFlags["FunctionScopedVariableExcludes"] = 107454] = "FunctionScopedVariableExcludes";
                // Block-scoped declarations are not allowed to be re-declared
                // they can not merge with anything in the value space
                SymbolFlags[SymbolFlags["BlockScopedVariableExcludes"] = 107455] = "BlockScopedVariableExcludes";
                SymbolFlags[SymbolFlags["ParameterExcludes"] = 107455] = "ParameterExcludes";
                SymbolFlags[SymbolFlags["PropertyExcludes"] = 107455] = "PropertyExcludes";
                SymbolFlags[SymbolFlags["EnumMemberExcludes"] = 107455] = "EnumMemberExcludes";
                SymbolFlags[SymbolFlags["FunctionExcludes"] = 106927] = "FunctionExcludes";
                SymbolFlags[SymbolFlags["ClassExcludes"] = 899583] = "ClassExcludes";
                SymbolFlags[SymbolFlags["InterfaceExcludes"] = 792992] = "InterfaceExcludes";
                SymbolFlags[SymbolFlags["RegularEnumExcludes"] = 899327] = "RegularEnumExcludes";
                SymbolFlags[SymbolFlags["ConstEnumExcludes"] = 899967] = "ConstEnumExcludes";
                SymbolFlags[SymbolFlags["ValueModuleExcludes"] = 106639] = "ValueModuleExcludes";
                SymbolFlags[SymbolFlags["NamespaceModuleExcludes"] = 0] = "NamespaceModuleExcludes";
                SymbolFlags[SymbolFlags["MethodExcludes"] = 99263] = "MethodExcludes";
                SymbolFlags[SymbolFlags["GetAccessorExcludes"] = 41919] = "GetAccessorExcludes";
                SymbolFlags[SymbolFlags["SetAccessorExcludes"] = 74687] = "SetAccessorExcludes";
                SymbolFlags[SymbolFlags["TypeParameterExcludes"] = 530912] = "TypeParameterExcludes";
                SymbolFlags[SymbolFlags["TypeAliasExcludes"] = 793056] = "TypeAliasExcludes";
                SymbolFlags[SymbolFlags["AliasExcludes"] = 8388608] = "AliasExcludes";
                SymbolFlags[SymbolFlags["ModuleMember"] = 8914931] = "ModuleMember";
                SymbolFlags[SymbolFlags["ExportHasLocal"] = 944] = "ExportHasLocal";
                SymbolFlags[SymbolFlags["HasLocals"] = 255504] = "HasLocals";
                SymbolFlags[SymbolFlags["HasExports"] = 1952] = "HasExports";
                SymbolFlags[SymbolFlags["HasMembers"] = 6240] = "HasMembers";
                SymbolFlags[SymbolFlags["IsContainer"] = 262128] = "IsContainer";
                SymbolFlags[SymbolFlags["PropertyOrAccessor"] = 98308] = "PropertyOrAccessor";
                SymbolFlags[SymbolFlags["Export"] = 7340032] = "Export";
            })(ts.SymbolFlags || (ts.SymbolFlags = {}));
            var SymbolFlags = ts.SymbolFlags;
            /* @internal */
            (function (NodeCheckFlags) {
                NodeCheckFlags[NodeCheckFlags["TypeChecked"] = 1] = "TypeChecked";
                NodeCheckFlags[NodeCheckFlags["LexicalThis"] = 2] = "LexicalThis";
                NodeCheckFlags[NodeCheckFlags["CaptureThis"] = 4] = "CaptureThis";
                NodeCheckFlags[NodeCheckFlags["EmitExtends"] = 8] = "EmitExtends";
                NodeCheckFlags[NodeCheckFlags["SuperInstance"] = 16] = "SuperInstance";
                NodeCheckFlags[NodeCheckFlags["SuperStatic"] = 32] = "SuperStatic";
                NodeCheckFlags[NodeCheckFlags["ContextChecked"] = 64] = "ContextChecked";
                // Values for enum members have been computed, and any errors have been reported for them.
                NodeCheckFlags[NodeCheckFlags["EnumValuesComputed"] = 128] = "EnumValuesComputed";
                NodeCheckFlags[NodeCheckFlags["BlockScopedBindingInLoop"] = 256] = "BlockScopedBindingInLoop";
                NodeCheckFlags[NodeCheckFlags["EmitDecorate"] = 512] = "EmitDecorate";
                NodeCheckFlags[NodeCheckFlags["EmitParam"] = 1024] = "EmitParam";
                NodeCheckFlags[NodeCheckFlags["LexicalModuleMergesWithClass"] = 2048] = "LexicalModuleMergesWithClass";
            })(ts.NodeCheckFlags || (ts.NodeCheckFlags = {}));
            var NodeCheckFlags = ts.NodeCheckFlags;
            (function (TypeFlags) {
                TypeFlags[TypeFlags["Any"] = 1] = "Any";
                TypeFlags[TypeFlags["String"] = 2] = "String";
                TypeFlags[TypeFlags["Number"] = 4] = "Number";
                TypeFlags[TypeFlags["Boolean"] = 8] = "Boolean";
                TypeFlags[TypeFlags["Void"] = 16] = "Void";
                TypeFlags[TypeFlags["Undefined"] = 32] = "Undefined";
                TypeFlags[TypeFlags["Null"] = 64] = "Null";
                TypeFlags[TypeFlags["Enum"] = 128] = "Enum";
                TypeFlags[TypeFlags["StringLiteral"] = 256] = "StringLiteral";
                TypeFlags[TypeFlags["TypeParameter"] = 512] = "TypeParameter";
                TypeFlags[TypeFlags["Class"] = 1024] = "Class";
                TypeFlags[TypeFlags["Interface"] = 2048] = "Interface";
                TypeFlags[TypeFlags["Reference"] = 4096] = "Reference";
                TypeFlags[TypeFlags["Tuple"] = 8192] = "Tuple";
                TypeFlags[TypeFlags["Union"] = 16384] = "Union";
                TypeFlags[TypeFlags["Anonymous"] = 32768] = "Anonymous";
                /* @internal */
                TypeFlags[TypeFlags["FromSignature"] = 65536] = "FromSignature";
                TypeFlags[TypeFlags["ObjectLiteral"] = 131072] = "ObjectLiteral";
                /* @internal */
                TypeFlags[TypeFlags["ContainsUndefinedOrNull"] = 262144] = "ContainsUndefinedOrNull";
                /* @internal */
                TypeFlags[TypeFlags["ContainsObjectLiteral"] = 524288] = "ContainsObjectLiteral";
                TypeFlags[TypeFlags["ESSymbol"] = 1048576] = "ESSymbol";
                /* @internal */
                TypeFlags[TypeFlags["Intrinsic"] = 1048703] = "Intrinsic";
                /* @internal */
                TypeFlags[TypeFlags["Primitive"] = 1049086] = "Primitive";
                TypeFlags[TypeFlags["StringLike"] = 258] = "StringLike";
                TypeFlags[TypeFlags["NumberLike"] = 132] = "NumberLike";
                TypeFlags[TypeFlags["ObjectType"] = 48128] = "ObjectType";
                /* @internal */
                TypeFlags[TypeFlags["RequiresWidening"] = 786432] = "RequiresWidening";
            })(ts.TypeFlags || (ts.TypeFlags = {}));
            var TypeFlags = ts.TypeFlags;
            (function (SignatureKind) {
                SignatureKind[SignatureKind["Call"] = 0] = "Call";
                SignatureKind[SignatureKind["Construct"] = 1] = "Construct";
            })(ts.SignatureKind || (ts.SignatureKind = {}));
            var SignatureKind = ts.SignatureKind;
            (function (IndexKind) {
                IndexKind[IndexKind["String"] = 0] = "String";
                IndexKind[IndexKind["Number"] = 1] = "Number";
            })(ts.IndexKind || (ts.IndexKind = {}));
            var IndexKind = ts.IndexKind;
            (function (DiagnosticCategory) {
                DiagnosticCategory[DiagnosticCategory["Warning"] = 0] = "Warning";
                DiagnosticCategory[DiagnosticCategory["Error"] = 1] = "Error";
                DiagnosticCategory[DiagnosticCategory["Message"] = 2] = "Message";
            })(ts.DiagnosticCategory || (ts.DiagnosticCategory = {}));
            var DiagnosticCategory = ts.DiagnosticCategory;
            (function (ModuleKind) {
                ModuleKind[ModuleKind["None"] = 0] = "None";
                ModuleKind[ModuleKind["CommonJS"] = 1] = "CommonJS";
                ModuleKind[ModuleKind["AMD"] = 2] = "AMD";
                ModuleKind[ModuleKind["UMD"] = 3] = "UMD";
            })(ts.ModuleKind || (ts.ModuleKind = {}));
            var ModuleKind = ts.ModuleKind;
            (function (ScriptTarget) {
                ScriptTarget[ScriptTarget["ES3"] = 0] = "ES3";
                ScriptTarget[ScriptTarget["ES5"] = 1] = "ES5";
                ScriptTarget[ScriptTarget["ES6"] = 2] = "ES6";
                ScriptTarget[ScriptTarget["Latest"] = 2] = "Latest";
            })(ts.ScriptTarget || (ts.ScriptTarget = {}));
            var ScriptTarget = ts.ScriptTarget;
            /* @internal */
            (function (CharacterCodes) {
                CharacterCodes[CharacterCodes["nullCharacter"] = 0] = "nullCharacter";
                CharacterCodes[CharacterCodes["maxAsciiCharacter"] = 127] = "maxAsciiCharacter";
                CharacterCodes[CharacterCodes["lineFeed"] = 10] = "lineFeed";
                CharacterCodes[CharacterCodes["carriageReturn"] = 13] = "carriageReturn";
                CharacterCodes[CharacterCodes["lineSeparator"] = 8232] = "lineSeparator";
                CharacterCodes[CharacterCodes["paragraphSeparator"] = 8233] = "paragraphSeparator";
                CharacterCodes[CharacterCodes["nextLine"] = 133] = "nextLine";
                // Unicode 3.0 space characters
                CharacterCodes[CharacterCodes["space"] = 32] = "space";
                CharacterCodes[CharacterCodes["nonBreakingSpace"] = 160] = "nonBreakingSpace";
                CharacterCodes[CharacterCodes["enQuad"] = 8192] = "enQuad";
                CharacterCodes[CharacterCodes["emQuad"] = 8193] = "emQuad";
                CharacterCodes[CharacterCodes["enSpace"] = 8194] = "enSpace";
                CharacterCodes[CharacterCodes["emSpace"] = 8195] = "emSpace";
                CharacterCodes[CharacterCodes["threePerEmSpace"] = 8196] = "threePerEmSpace";
                CharacterCodes[CharacterCodes["fourPerEmSpace"] = 8197] = "fourPerEmSpace";
                CharacterCodes[CharacterCodes["sixPerEmSpace"] = 8198] = "sixPerEmSpace";
                CharacterCodes[CharacterCodes["figureSpace"] = 8199] = "figureSpace";
                CharacterCodes[CharacterCodes["punctuationSpace"] = 8200] = "punctuationSpace";
                CharacterCodes[CharacterCodes["thinSpace"] = 8201] = "thinSpace";
                CharacterCodes[CharacterCodes["hairSpace"] = 8202] = "hairSpace";
                CharacterCodes[CharacterCodes["zeroWidthSpace"] = 8203] = "zeroWidthSpace";
                CharacterCodes[CharacterCodes["narrowNoBreakSpace"] = 8239] = "narrowNoBreakSpace";
                CharacterCodes[CharacterCodes["ideographicSpace"] = 12288] = "ideographicSpace";
                CharacterCodes[CharacterCodes["mathematicalSpace"] = 8287] = "mathematicalSpace";
                CharacterCodes[CharacterCodes["ogham"] = 5760] = "ogham";
                CharacterCodes[CharacterCodes["_"] = 95] = "_";
                CharacterCodes[CharacterCodes["$"] = 36] = "$";
                CharacterCodes[CharacterCodes["_0"] = 48] = "_0";
                CharacterCodes[CharacterCodes["_1"] = 49] = "_1";
                CharacterCodes[CharacterCodes["_2"] = 50] = "_2";
                CharacterCodes[CharacterCodes["_3"] = 51] = "_3";
                CharacterCodes[CharacterCodes["_4"] = 52] = "_4";
                CharacterCodes[CharacterCodes["_5"] = 53] = "_5";
                CharacterCodes[CharacterCodes["_6"] = 54] = "_6";
                CharacterCodes[CharacterCodes["_7"] = 55] = "_7";
                CharacterCodes[CharacterCodes["_8"] = 56] = "_8";
                CharacterCodes[CharacterCodes["_9"] = 57] = "_9";
                CharacterCodes[CharacterCodes["a"] = 97] = "a";
                CharacterCodes[CharacterCodes["b"] = 98] = "b";
                CharacterCodes[CharacterCodes["c"] = 99] = "c";
                CharacterCodes[CharacterCodes["d"] = 100] = "d";
                CharacterCodes[CharacterCodes["e"] = 101] = "e";
                CharacterCodes[CharacterCodes["f"] = 102] = "f";
                CharacterCodes[CharacterCodes["g"] = 103] = "g";
                CharacterCodes[CharacterCodes["h"] = 104] = "h";
                CharacterCodes[CharacterCodes["i"] = 105] = "i";
                CharacterCodes[CharacterCodes["j"] = 106] = "j";
                CharacterCodes[CharacterCodes["k"] = 107] = "k";
                CharacterCodes[CharacterCodes["l"] = 108] = "l";
                CharacterCodes[CharacterCodes["m"] = 109] = "m";
                CharacterCodes[CharacterCodes["n"] = 110] = "n";
                CharacterCodes[CharacterCodes["o"] = 111] = "o";
                CharacterCodes[CharacterCodes["p"] = 112] = "p";
                CharacterCodes[CharacterCodes["q"] = 113] = "q";
                CharacterCodes[CharacterCodes["r"] = 114] = "r";
                CharacterCodes[CharacterCodes["s"] = 115] = "s";
                CharacterCodes[CharacterCodes["t"] = 116] = "t";
                CharacterCodes[CharacterCodes["u"] = 117] = "u";
                CharacterCodes[CharacterCodes["v"] = 118] = "v";
                CharacterCodes[CharacterCodes["w"] = 119] = "w";
                CharacterCodes[CharacterCodes["x"] = 120] = "x";
                CharacterCodes[CharacterCodes["y"] = 121] = "y";
                CharacterCodes[CharacterCodes["z"] = 122] = "z";
                CharacterCodes[CharacterCodes["A"] = 65] = "A";
                CharacterCodes[CharacterCodes["B"] = 66] = "B";
                CharacterCodes[CharacterCodes["C"] = 67] = "C";
                CharacterCodes[CharacterCodes["D"] = 68] = "D";
                CharacterCodes[CharacterCodes["E"] = 69] = "E";
                CharacterCodes[CharacterCodes["F"] = 70] = "F";
                CharacterCodes[CharacterCodes["G"] = 71] = "G";
                CharacterCodes[CharacterCodes["H"] = 72] = "H";
                CharacterCodes[CharacterCodes["I"] = 73] = "I";
                CharacterCodes[CharacterCodes["J"] = 74] = "J";
                CharacterCodes[CharacterCodes["K"] = 75] = "K";
                CharacterCodes[CharacterCodes["L"] = 76] = "L";
                CharacterCodes[CharacterCodes["M"] = 77] = "M";
                CharacterCodes[CharacterCodes["N"] = 78] = "N";
                CharacterCodes[CharacterCodes["O"] = 79] = "O";
                CharacterCodes[CharacterCodes["P"] = 80] = "P";
                CharacterCodes[CharacterCodes["Q"] = 81] = "Q";
                CharacterCodes[CharacterCodes["R"] = 82] = "R";
                CharacterCodes[CharacterCodes["S"] = 83] = "S";
                CharacterCodes[CharacterCodes["T"] = 84] = "T";
                CharacterCodes[CharacterCodes["U"] = 85] = "U";
                CharacterCodes[CharacterCodes["V"] = 86] = "V";
                CharacterCodes[CharacterCodes["W"] = 87] = "W";
                CharacterCodes[CharacterCodes["X"] = 88] = "X";
                CharacterCodes[CharacterCodes["Y"] = 89] = "Y";
                CharacterCodes[CharacterCodes["Z"] = 90] = "Z";
                CharacterCodes[CharacterCodes["ampersand"] = 38] = "ampersand";
                CharacterCodes[CharacterCodes["asterisk"] = 42] = "asterisk";
                CharacterCodes[CharacterCodes["at"] = 64] = "at";
                CharacterCodes[CharacterCodes["backslash"] = 92] = "backslash";
                CharacterCodes[CharacterCodes["backtick"] = 96] = "backtick";
                CharacterCodes[CharacterCodes["bar"] = 124] = "bar";
                CharacterCodes[CharacterCodes["caret"] = 94] = "caret";
                CharacterCodes[CharacterCodes["closeBrace"] = 125] = "closeBrace";
                CharacterCodes[CharacterCodes["closeBracket"] = 93] = "closeBracket";
                CharacterCodes[CharacterCodes["closeParen"] = 41] = "closeParen";
                CharacterCodes[CharacterCodes["colon"] = 58] = "colon";
                CharacterCodes[CharacterCodes["comma"] = 44] = "comma";
                CharacterCodes[CharacterCodes["dot"] = 46] = "dot";
                CharacterCodes[CharacterCodes["doubleQuote"] = 34] = "doubleQuote";
                CharacterCodes[CharacterCodes["equals"] = 61] = "equals";
                CharacterCodes[CharacterCodes["exclamation"] = 33] = "exclamation";
                CharacterCodes[CharacterCodes["greaterThan"] = 62] = "greaterThan";
                CharacterCodes[CharacterCodes["hash"] = 35] = "hash";
                CharacterCodes[CharacterCodes["lessThan"] = 60] = "lessThan";
                CharacterCodes[CharacterCodes["minus"] = 45] = "minus";
                CharacterCodes[CharacterCodes["openBrace"] = 123] = "openBrace";
                CharacterCodes[CharacterCodes["openBracket"] = 91] = "openBracket";
                CharacterCodes[CharacterCodes["openParen"] = 40] = "openParen";
                CharacterCodes[CharacterCodes["percent"] = 37] = "percent";
                CharacterCodes[CharacterCodes["plus"] = 43] = "plus";
                CharacterCodes[CharacterCodes["question"] = 63] = "question";
                CharacterCodes[CharacterCodes["semicolon"] = 59] = "semicolon";
                CharacterCodes[CharacterCodes["singleQuote"] = 39] = "singleQuote";
                CharacterCodes[CharacterCodes["slash"] = 47] = "slash";
                CharacterCodes[CharacterCodes["tilde"] = 126] = "tilde";
                CharacterCodes[CharacterCodes["backspace"] = 8] = "backspace";
                CharacterCodes[CharacterCodes["formFeed"] = 12] = "formFeed";
                CharacterCodes[CharacterCodes["byteOrderMark"] = 65279] = "byteOrderMark";
                CharacterCodes[CharacterCodes["tab"] = 9] = "tab";
                CharacterCodes[CharacterCodes["verticalTab"] = 11] = "verticalTab";
            })(ts.CharacterCodes || (ts.CharacterCodes = {}));
            var CharacterCodes = ts.CharacterCodes;
        })(ts || (ts = {}));
        /// <reference path="types.ts"/>
        /* @internal */
        var ts;
        (function (ts) {
            // Ternary values are defined such that
            // x & y is False if either x or y is False.
            // x & y is Maybe if either x or y is Maybe, but neither x or y is False.
            // x & y is True if both x and y are True.
            // x | y is False if both x and y are False.
            // x | y is Maybe if either x or y is Maybe, but neither x or y is True.
            // x | y is True if either x or y is True.
            (function (Ternary) {
                Ternary[Ternary["False"] = 0] = "False";
                Ternary[Ternary["Maybe"] = 1] = "Maybe";
                Ternary[Ternary["True"] = -1] = "True";
            })(ts.Ternary || (ts.Ternary = {}));
            var Ternary = ts.Ternary;
            (function (Comparison) {
                Comparison[Comparison["LessThan"] = -1] = "LessThan";
                Comparison[Comparison["EqualTo"] = 0] = "EqualTo";
                Comparison[Comparison["GreaterThan"] = 1] = "GreaterThan";
            })(ts.Comparison || (ts.Comparison = {}));
            var Comparison = ts.Comparison;
            function forEach(array, callback) {
                if (array) {
                    for (var i = 0, len = array.length; i < len; i++) {
                        var result = callback(array[i], i);
                        if (result) {
                            return result;
                        }
                    }
                }
                return undefined;
            }
            ts.forEach = forEach;
            function contains(array, value) {
                if (array) {
                    for (var _i = 0; _i < array.length; _i++) {
                        var v = array[_i];
                        if (v === value) {
                            return true;
                        }
                    }
                }
                return false;
            }
            ts.contains = contains;
            function indexOf(array, value) {
                if (array) {
                    for (var i = 0, len = array.length; i < len; i++) {
                        if (array[i] === value) {
                            return i;
                        }
                    }
                }
                return -1;
            }
            ts.indexOf = indexOf;
            function countWhere(array, predicate) {
                var count = 0;
                if (array) {
                    for (var _i = 0; _i < array.length; _i++) {
                        var v = array[_i];
                        if (predicate(v)) {
                            count++;
                        }
                    }
                }
                return count;
            }
            ts.countWhere = countWhere;
            function filter(array, f) {
                var result;
                if (array) {
                    result = [];
                    for (var _i = 0; _i < array.length; _i++) {
                        var item = array[_i];
                        if (f(item)) {
                            result.push(item);
                        }
                    }
                }
                return result;
            }
            ts.filter = filter;
            function map(array, f) {
                var result;
                if (array) {
                    result = [];
                    for (var _i = 0; _i < array.length; _i++) {
                        var v = array[_i];
                        result.push(f(v));
                    }
                }
                return result;
            }
            ts.map = map;
            function concatenate(array1, array2) {
                if (!array2 || !array2.length)
                    return array1;
                if (!array1 || !array1.length)
                    return array2;
                return array1.concat(array2);
            }
            ts.concatenate = concatenate;
            function deduplicate(array) {
                var result;
                if (array) {
                    result = [];
                    for (var _i = 0; _i < array.length; _i++) {
                        var item = array[_i];
                        if (!contains(result, item)) {
                            result.push(item);
                        }
                    }
                }
                return result;
            }
            ts.deduplicate = deduplicate;
            function sum(array, prop) {
                var result = 0;
                for (var _i = 0; _i < array.length; _i++) {
                    var v = array[_i];
                    result += v[prop];
                }
                return result;
            }
            ts.sum = sum;
            function addRange(to, from) {
                if (to && from) {
                    for (var _i = 0; _i < from.length; _i++) {
                        var v = from[_i];
                        to.push(v);
                    }
                }
            }
            ts.addRange = addRange;
            /**
             * Returns the last element of an array if non-empty, undefined otherwise.
             */
            function lastOrUndefined(array) {
                if (array.length === 0) {
                    return undefined;
                }
                return array[array.length - 1];
            }
            ts.lastOrUndefined = lastOrUndefined;
            function binarySearch(array, value) {
                var low = 0;
                var high = array.length - 1;
                while (low <= high) {
                    var middle = low + ((high - low) >> 1);
                    var midValue = array[middle];
                    if (midValue === value) {
                        return middle;
                    }
                    else if (midValue > value) {
                        high = middle - 1;
                    }
                    else {
                        low = middle + 1;
                    }
                }
                return ~low;
            }
            ts.binarySearch = binarySearch;
            function reduceLeft(array, f, initial) {
                if (array) {
                    var count = array.length;
                    if (count > 0) {
                        var pos = 0;
                        var result = arguments.length <= 2 ? array[pos++] : initial;
                        while (pos < count) {
                            result = f(result, array[pos++]);
                        }
                        return result;
                    }
                }
                return initial;
            }
            ts.reduceLeft = reduceLeft;
            function reduceRight(array, f, initial) {
                if (array) {
                    var pos = array.length - 1;
                    if (pos >= 0) {
                        var result = arguments.length <= 2 ? array[pos--] : initial;
                        while (pos >= 0) {
                            result = f(result, array[pos--]);
                        }
                        return result;
                    }
                }
                return initial;
            }
            ts.reduceRight = reduceRight;
            var hasOwnProperty = Object.prototype.hasOwnProperty;
            function hasProperty(map, key) {
                return hasOwnProperty.call(map, key);
            }
            ts.hasProperty = hasProperty;
            function getProperty(map, key) {
                return hasOwnProperty.call(map, key) ? map[key] : undefined;
            }
            ts.getProperty = getProperty;
            function isEmpty(map) {
                for (var id in map) {
                    if (hasProperty(map, id)) {
                        return false;
                    }
                }
                return true;
            }
            ts.isEmpty = isEmpty;
            function clone(object) {
                var result = {};
                for (var id in object) {
                    result[id] = object[id];
                }
                return result;
            }
            ts.clone = clone;
            function extend(first, second) {
                var result = {};
                for (var id in first) {
                    result[id] = first[id];
                }
                for (var id in second) {
                    if (!hasProperty(result, id)) {
                        result[id] = second[id];
                    }
                }
                return result;
            }
            ts.extend = extend;
            function forEachValue(map, callback) {
                var result;
                for (var id in map) {
                    if (result = callback(map[id]))
                        break;
                }
                return result;
            }
            ts.forEachValue = forEachValue;
            function forEachKey(map, callback) {
                var result;
                for (var id in map) {
                    if (result = callback(id))
                        break;
                }
                return result;
            }
            ts.forEachKey = forEachKey;
            function lookUp(map, key) {
                return hasProperty(map, key) ? map[key] : undefined;
            }
            ts.lookUp = lookUp;
            function copyMap(source, target) {
                for (var p in source) {
                    target[p] = source[p];
                }
            }
            ts.copyMap = copyMap;
            /**
             * Creates a map from the elements of an array.
             *
             * @param array the array of input elements.
             * @param makeKey a function that produces a key for a given element.
             *
             * This function makes no effort to avoid collisions; if any two elements produce
             * the same key with the given 'makeKey' function, then the element with the higher
             * index in the array will be the one associated with the produced key.
             */
            function arrayToMap(array, makeKey) {
                var result = {};
                forEach(array, function (value) {
                    result[makeKey(value)] = value;
                });
                return result;
            }
            ts.arrayToMap = arrayToMap;
            function memoize(callback) {
                var value;
                return function () {
                    if (callback) {
                        value = callback();
                        callback = undefined;
                    }
                    return value;
                };
            }
            ts.memoize = memoize;
            function formatStringFromArgs(text, args, baseIndex) {
                baseIndex = baseIndex || 0;
                return text.replace(/{(\d+)}/g, function (match, index) { return args[+index + baseIndex]; });
            }
            ts.localizedDiagnosticMessages = undefined;
            function getLocaleSpecificMessage(message) {
                return ts.localizedDiagnosticMessages && ts.localizedDiagnosticMessages[message]
                    ? ts.localizedDiagnosticMessages[message]
                    : message;
            }
            ts.getLocaleSpecificMessage = getLocaleSpecificMessage;
            function createFileDiagnostic(file, start, length, message) {
                var end = start + length;
                Debug.assert(start >= 0, "start must be non-negative, is " + start);
                Debug.assert(length >= 0, "length must be non-negative, is " + length);
                Debug.assert(start <= file.text.length, "start must be within the bounds of the file. " + start + " > " + file.text.length);
                Debug.assert(end <= file.text.length, "end must be the bounds of the file. " + end + " > " + file.text.length);
                var text = getLocaleSpecificMessage(message.key);
                if (arguments.length > 4) {
                    text = formatStringFromArgs(text, arguments, 4);
                }
                return {
                    file: file,
                    start: start,
                    length: length,
                    messageText: text,
                    category: message.category,
                    code: message.code
                };
            }
            ts.createFileDiagnostic = createFileDiagnostic;
            function createCompilerDiagnostic(message) {
                var text = getLocaleSpecificMessage(message.key);
                if (arguments.length > 1) {
                    text = formatStringFromArgs(text, arguments, 1);
                }
                return {
                    file: undefined,
                    start: undefined,
                    length: undefined,
                    messageText: text,
                    category: message.category,
                    code: message.code
                };
            }
            ts.createCompilerDiagnostic = createCompilerDiagnostic;
            function chainDiagnosticMessages(details, message) {
                var text = getLocaleSpecificMessage(message.key);
                if (arguments.length > 2) {
                    text = formatStringFromArgs(text, arguments, 2);
                }
                return {
                    messageText: text,
                    category: message.category,
                    code: message.code,
                    next: details
                };
            }
            ts.chainDiagnosticMessages = chainDiagnosticMessages;
            function concatenateDiagnosticMessageChains(headChain, tailChain) {
                Debug.assert(!headChain.next);
                headChain.next = tailChain;
                return headChain;
            }
            ts.concatenateDiagnosticMessageChains = concatenateDiagnosticMessageChains;
            function compareValues(a, b) {
                if (a === b)
                    return 0 /* EqualTo */;
                if (a === undefined)
                    return -1 /* LessThan */;
                if (b === undefined)
                    return 1 /* GreaterThan */;
                return a < b ? -1 /* LessThan */ : 1 /* GreaterThan */;
            }
            ts.compareValues = compareValues;
            function getDiagnosticFileName(diagnostic) {
                return diagnostic.file ? diagnostic.file.fileName : undefined;
            }
            function compareDiagnostics(d1, d2) {
                return compareValues(getDiagnosticFileName(d1), getDiagnosticFileName(d2)) ||
                    compareValues(d1.start, d2.start) ||
                    compareValues(d1.length, d2.length) ||
                    compareValues(d1.code, d2.code) ||
                    compareMessageText(d1.messageText, d2.messageText) ||
                    0 /* EqualTo */;
            }
            ts.compareDiagnostics = compareDiagnostics;
            function compareMessageText(text1, text2) {
                while (text1 && text2) {
                    // We still have both chains.
                    var string1 = typeof text1 === "string" ? text1 : text1.messageText;
                    var string2 = typeof text2 === "string" ? text2 : text2.messageText;
                    var res = compareValues(string1, string2);
                    if (res) {
                        return res;
                    }
                    text1 = typeof text1 === "string" ? undefined : text1.next;
                    text2 = typeof text2 === "string" ? undefined : text2.next;
                }
                if (!text1 && !text2) {
                    // if the chains are done, then these messages are the same.
                    return 0 /* EqualTo */;
                }
                // We still have one chain remaining.  The shorter chain should come first.
                return text1 ? 1 /* GreaterThan */ : -1 /* LessThan */;
            }
            function sortAndDeduplicateDiagnostics(diagnostics) {
                return deduplicateSortedDiagnostics(diagnostics.sort(compareDiagnostics));
            }
            ts.sortAndDeduplicateDiagnostics = sortAndDeduplicateDiagnostics;
            function deduplicateSortedDiagnostics(diagnostics) {
                if (diagnostics.length < 2) {
                    return diagnostics;
                }
                var newDiagnostics = [diagnostics[0]];
                var previousDiagnostic = diagnostics[0];
                for (var i = 1; i < diagnostics.length; i++) {
                    var currentDiagnostic = diagnostics[i];
                    var isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === 0 /* EqualTo */;
                    if (!isDupe) {
                        newDiagnostics.push(currentDiagnostic);
                        previousDiagnostic = currentDiagnostic;
                    }
                }
                return newDiagnostics;
            }
            ts.deduplicateSortedDiagnostics = deduplicateSortedDiagnostics;
            function normalizeSlashes(path) {
                return path.replace(/\\/g, "/");
            }
            ts.normalizeSlashes = normalizeSlashes;
            // Returns length of path root (i.e. length of "/", "x:/", "//server/share/, file:///user/files")
            function getRootLength(path) {
                if (path.charCodeAt(0) === 47 /* slash */) {
                    if (path.charCodeAt(1) !== 47 /* slash */)
                        return 1;
                    var p1 = path.indexOf("/", 2);
                    if (p1 < 0)
                        return 2;
                    var p2 = path.indexOf("/", p1 + 1);
                    if (p2 < 0)
                        return p1 + 1;
                    return p2 + 1;
                }
                if (path.charCodeAt(1) === 58 /* colon */) {
                    if (path.charCodeAt(2) === 47 /* slash */)
                        return 3;
                    return 2;
                }
                var idx = path.indexOf('://');
                if (idx !== -1)
                    return idx + 3;
                return 0;
            }
            ts.getRootLength = getRootLength;
            ts.directorySeparator = "/";
            function getNormalizedParts(normalizedSlashedPath, rootLength) {
                var parts = normalizedSlashedPath.substr(rootLength).split(ts.directorySeparator);
                var normalized = [];
                for (var _i = 0; _i < parts.length; _i++) {
                    var part = parts[_i];
                    if (part !== ".") {
                        if (part === ".." && normalized.length > 0 && normalized[normalized.length - 1] !== "..") {
                            normalized.pop();
                        }
                        else {
                            // A part may be an empty string (which is 'falsy') if the path had consecutive slashes,
                            // e.g. "path//file.ts".  Drop these before re-joining the parts.
                            if (part) {
                                normalized.push(part);
                            }
                        }
                    }
                }
                return normalized;
            }
            function normalizePath(path) {
                path = normalizeSlashes(path);
                var rootLength = getRootLength(path);
                var normalized = getNormalizedParts(path, rootLength);
                return path.substr(0, rootLength) + normalized.join(ts.directorySeparator);
            }
            ts.normalizePath = normalizePath;
            function getDirectoryPath(path) {
                return path.substr(0, Math.max(getRootLength(path), path.lastIndexOf(ts.directorySeparator)));
            }
            ts.getDirectoryPath = getDirectoryPath;
            function isUrl(path) {
                return path && !isRootedDiskPath(path) && path.indexOf("://") !== -1;
            }
            ts.isUrl = isUrl;
            function isRootedDiskPath(path) {
                return getRootLength(path) !== 0;
            }
            ts.isRootedDiskPath = isRootedDiskPath;
            function normalizedPathComponents(path, rootLength) {
                var normalizedParts = getNormalizedParts(path, rootLength);
                return [path.substr(0, rootLength)].concat(normalizedParts);
            }
            function getNormalizedPathComponents(path, currentDirectory) {
                path = normalizeSlashes(path);
                var rootLength = getRootLength(path);
                if (rootLength == 0) {
                    // If the path is not rooted it is relative to current directory
                    path = combinePaths(normalizeSlashes(currentDirectory), path);
                    rootLength = getRootLength(path);
                }
                return normalizedPathComponents(path, rootLength);
            }
            ts.getNormalizedPathComponents = getNormalizedPathComponents;
            function getNormalizedAbsolutePath(fileName, currentDirectory) {
                return getNormalizedPathFromPathComponents(getNormalizedPathComponents(fileName, currentDirectory));
            }
            ts.getNormalizedAbsolutePath = getNormalizedAbsolutePath;
            function getNormalizedPathFromPathComponents(pathComponents) {
                if (pathComponents && pathComponents.length) {
                    return pathComponents[0] + pathComponents.slice(1).join(ts.directorySeparator);
                }
            }
            ts.getNormalizedPathFromPathComponents = getNormalizedPathFromPathComponents;
            function getNormalizedPathComponentsOfUrl(url) {
                // Get root length of http://www.website.com/folder1/foler2/
                // In this example the root is:  http://www.website.com/ 
                // normalized path components should be ["http://www.website.com/", "folder1", "folder2"]
                var urlLength = url.length;
                // Initial root length is http:// part
                var rootLength = url.indexOf("://") + "://".length;
                while (rootLength < urlLength) {
                    // Consume all immediate slashes in the protocol 
                    // eg.initial rootlength is just file:// but it needs to consume another "/" in file:///
                    if (url.charCodeAt(rootLength) === 47 /* slash */) {
                        rootLength++;
                    }
                    else {
                        // non slash character means we continue proceeding to next component of root search 
                        break;
                    }
                }
                // there are no parts after http:// just return current string as the pathComponent
                if (rootLength === urlLength) {
                    return [url];
                }
                // Find the index of "/" after website.com so the root can be http://www.website.com/ (from existing http://)
                var indexOfNextSlash = url.indexOf(ts.directorySeparator, rootLength);
                if (indexOfNextSlash !== -1) {
                    // Found the "/" after the website.com so the root is length of http://www.website.com/ 
                    // and get components afetr the root normally like any other folder components
                    rootLength = indexOfNextSlash + 1;
                    return normalizedPathComponents(url, rootLength);
                }
                else {
                    // Can't find the host assume the rest of the string as component 
                    // but make sure we append "/"  to it as root is not joined using "/"
                    // eg. if url passed in was http://website.com we want to use root as [http://website.com/] 
                    // so that other path manipulations will be correct and it can be merged with relative paths correctly
                    return [url + ts.directorySeparator];
                }
            }
            function getNormalizedPathOrUrlComponents(pathOrUrl, currentDirectory) {
                if (isUrl(pathOrUrl)) {
                    return getNormalizedPathComponentsOfUrl(pathOrUrl);
                }
                else {
                    return getNormalizedPathComponents(pathOrUrl, currentDirectory);
                }
            }
            function getRelativePathToDirectoryOrUrl(directoryPathOrUrl, relativeOrAbsolutePath, currentDirectory, getCanonicalFileName, isAbsolutePathAnUrl) {
                var pathComponents = getNormalizedPathOrUrlComponents(relativeOrAbsolutePath, currentDirectory);
                var directoryComponents = getNormalizedPathOrUrlComponents(directoryPathOrUrl, currentDirectory);
                if (directoryComponents.length > 1 && directoryComponents[directoryComponents.length - 1] === "") {
                    // If the directory path given was of type test/cases/ then we really need components of directory to be only till its name
                    // that is  ["test", "cases", ""] needs to be actually ["test", "cases"]
                    directoryComponents.length--;
                }
                // Find the component that differs
                for (var joinStartIndex = 0; joinStartIndex < pathComponents.length && joinStartIndex < directoryComponents.length; joinStartIndex++) {
                    if (getCanonicalFileName(directoryComponents[joinStartIndex]) !== getCanonicalFileName(pathComponents[joinStartIndex])) {
                        break;
                    }
                }
                // Get the relative path
                if (joinStartIndex) {
                    var relativePath = "";
                    var relativePathComponents = pathComponents.slice(joinStartIndex, pathComponents.length);
                    for (; joinStartIndex < directoryComponents.length; joinStartIndex++) {
                        if (directoryComponents[joinStartIndex] !== "") {
                            relativePath = relativePath + ".." + ts.directorySeparator;
                        }
                    }
                    return relativePath + relativePathComponents.join(ts.directorySeparator);
                }
                // Cant find the relative path, get the absolute path
                var absolutePath = getNormalizedPathFromPathComponents(pathComponents);
                if (isAbsolutePathAnUrl && isRootedDiskPath(absolutePath)) {
                    absolutePath = "file:///" + absolutePath;
                }
                return absolutePath;
            }
            ts.getRelativePathToDirectoryOrUrl = getRelativePathToDirectoryOrUrl;
            function getBaseFileName(path) {
                var i = path.lastIndexOf(ts.directorySeparator);
                return i < 0 ? path : path.substring(i + 1);
            }
            ts.getBaseFileName = getBaseFileName;
            function combinePaths(path1, path2) {
                if (!(path1 && path1.length))
                    return path2;
                if (!(path2 && path2.length))
                    return path1;
                if (getRootLength(path2) !== 0)
                    return path2;
                if (path1.charAt(path1.length - 1) === ts.directorySeparator)
                    return path1 + path2;
                return path1 + ts.directorySeparator + path2;
            }
            ts.combinePaths = combinePaths;
            function fileExtensionIs(path, extension) {
                var pathLen = path.length;
                var extLen = extension.length;
                return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension;
            }
            ts.fileExtensionIs = fileExtensionIs;
            var supportedExtensions = [".d.ts", ".ts", ".js"];
            function removeFileExtension(path) {
                for (var _i = 0; _i < supportedExtensions.length; _i++) {
                    var ext = supportedExtensions[_i];
                    if (fileExtensionIs(path, ext)) {
                        return path.substr(0, path.length - ext.length);
                    }
                }
                return path;
            }
            ts.removeFileExtension = removeFileExtension;
            var backslashOrDoubleQuote = /[\"\\]/g;
            var escapedCharsRegExp = /[\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
            var escapedCharsMap = {
                "\0": "\\0",
                "\t": "\\t",
                "\v": "\\v",
                "\f": "\\f",
                "\b": "\\b",
                "\r": "\\r",
                "\n": "\\n",
                "\\": "\\\\",
                "\"": "\\\"",
                "\u2028": "\\u2028",
                "\u2029": "\\u2029",
                "\u0085": "\\u0085" // nextLine
            };
            function Symbol(flags, name) {
                this.flags = flags;
                this.name = name;
                this.declarations = undefined;
            }
            function Type(checker, flags) {
                this.flags = flags;
            }
            function Signature(checker) {
            }
            ts.objectAllocator = {
                getNodeConstructor: function (kind) {
                    function Node() {
                    }
                    Node.prototype = {
                        kind: kind,
                        pos: 0,
                        end: 0,
                        flags: 0,
                        parent: undefined
                    };
                    return Node;
                },
                getSymbolConstructor: function () { return Symbol; },
                getTypeConstructor: function () { return Type; },
                getSignatureConstructor: function () { return Signature; }
            };
            (function (AssertionLevel) {
                AssertionLevel[AssertionLevel["None"] = 0] = "None";
                AssertionLevel[AssertionLevel["Normal"] = 1] = "Normal";
                AssertionLevel[AssertionLevel["Aggressive"] = 2] = "Aggressive";
                AssertionLevel[AssertionLevel["VeryAggressive"] = 3] = "VeryAggressive";
            })(ts.AssertionLevel || (ts.AssertionLevel = {}));
            var AssertionLevel = ts.AssertionLevel;
            var Debug;
            (function (Debug) {
                var currentAssertionLevel = 0 /* None */;
                function shouldAssert(level) {
                    return currentAssertionLevel >= level;
                }
                Debug.shouldAssert = shouldAssert;
                function assert(expression, message, verboseDebugInfo) {
                    if (!expression) {
                        var verboseDebugString = "";
                        if (verboseDebugInfo) {
                            verboseDebugString = "\r\nVerbose Debug Information: " + verboseDebugInfo();
                        }
                        throw new Error("Debug Failure. False expression: " + (message || "") + verboseDebugString);
                    }
                }
                Debug.assert = assert;
                function fail(message) {
                    Debug.assert(false, message);
                }
                Debug.fail = fail;
            })(Debug = ts.Debug || (ts.Debug = {}));
        })(ts || (ts = {}));
        /// <reference path="core.ts"/>
        var ts;
        (function (ts) {
            ts.sys = (function () {
                function getWScriptSystem() {
                    var fso = new ActiveXObject("Scripting.FileSystemObject");
                    var fileStream = new ActiveXObject("ADODB.Stream");
                    fileStream.Type = 2 /*text*/;
                    var binaryStream = new ActiveXObject("ADODB.Stream");
                    binaryStream.Type = 1 /*binary*/;
                    var args = [];
                    for (var i = 0; i < WScript.Arguments.length; i++) {
                        args[i] = WScript.Arguments.Item(i);
                    }
                    function readFile(fileName, encoding) {
                        if (!fso.FileExists(fileName)) {
                            return undefined;
                        }
                        fileStream.Open();
                        try {
                            if (encoding) {
                                fileStream.Charset = encoding;
                                fileStream.LoadFromFile(fileName);
                            }
                            else {
                                // Load file and read the first two bytes into a string with no interpretation
                                fileStream.Charset = "x-ansi";
                                fileStream.LoadFromFile(fileName);
                                var bom = fileStream.ReadText(2) || "";
                                // Position must be at 0 before encoding can be changed
                                fileStream.Position = 0;
                                // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
                                fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8";
                            }
                            // ReadText method always strips byte order mark from resulting string
                            return fileStream.ReadText();
                        }
                        catch (e) {
                            throw e;
                        }
                        finally {
                            fileStream.Close();
                        }
                    }
                    function writeFile(fileName, data, writeByteOrderMark) {
                        fileStream.Open();
                        binaryStream.Open();
                        try {
                            // Write characters in UTF-8 encoding
                            fileStream.Charset = "utf-8";
                            fileStream.WriteText(data);
                            // If we don't want the BOM, then skip it by setting the starting location to 3 (size of BOM).
                            // If not, start from position 0, as the BOM will be added automatically when charset==utf8.
                            if (writeByteOrderMark) {
                                fileStream.Position = 0;
                            }
                            else {
                                fileStream.Position = 3;
                            }
                            fileStream.CopyTo(binaryStream);
                            binaryStream.SaveToFile(fileName, 2 /*overwrite*/);
                        }
                        finally {
                            binaryStream.Close();
                            fileStream.Close();
                        }
                    }
                    function getNames(collection) {
                        var result = [];
                        for (var e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
                            result.push(e.item().Name);
                        }
                        return result.sort();
                    }
                    function readDirectory(path, extension) {
                        var result = [];
                        visitDirectory(path);
                        return result;
                        function visitDirectory(path) {
                            var folder = fso.GetFolder(path || ".");
                            var files = getNames(folder.files);
                            for (var _i = 0; _i < files.length; _i++) {
                                var name_1 = files[_i];
                                if (!extension || ts.fileExtensionIs(name_1, extension)) {
                                    result.push(ts.combinePaths(path, name_1));
                                }
                            }
                            var subfolders = getNames(folder.subfolders);
                            for (var _a = 0; _a < subfolders.length; _a++) {
                                var current = subfolders[_a];
                                visitDirectory(ts.combinePaths(path, current));
                            }
                        }
                    }
                    return {
                        args: args,
                        newLine: "\r\n",
                        useCaseSensitiveFileNames: false,
                        write: function (s) {
                            WScript.StdOut.Write(s);
                        },
                        readFile: readFile,
                        writeFile: writeFile,
                        resolvePath: function (path) {
                            return fso.GetAbsolutePathName(path);
                        },
                        fileExists: function (path) {
                            return fso.FileExists(path);
                        },
                        directoryExists: function (path) {
                            return fso.FolderExists(path);
                        },
                        createDirectory: function (directoryName) {
                            if (!this.directoryExists(directoryName)) {
                                fso.CreateFolder(directoryName);
                            }
                        },
                        getExecutingFilePath: function () {
                            return WScript.ScriptFullName;
                        },
                        getCurrentDirectory: function () {
                            return new ActiveXObject("WScript.Shell").CurrentDirectory;
                        },
                        readDirectory: readDirectory,
                        exit: function (exitCode) {
                            try {
                                WScript.Quit(exitCode);
                            }
                            catch (e) {
                            }
                        }
                    };
                }
                function getNodeSystem() {
                    var _fs = require("fs");
                    var _path = require("path");
                    var _os = require('os');
                    var platform = _os.platform();
                    // win32\win64 are case insensitive platforms, MacOS (darwin) by default is also case insensitive
                    var useCaseSensitiveFileNames = platform !== "win32" && platform !== "win64" && platform !== "darwin";
                    function readFile(fileName, encoding) {
                        if (!_fs.existsSync(fileName)) {
                            return undefined;
                        }
                        var buffer = _fs.readFileSync(fileName);
                        var len = buffer.length;
                        if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) {
                            // Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js,
                            // flip all byte pairs and treat as little endian.
                            len &= ~1;
                            for (var i = 0; i < len; i += 2) {
                                var temp = buffer[i];
                                buffer[i] = buffer[i + 1];
                                buffer[i + 1] = temp;
                            }
                            return buffer.toString("utf16le", 2);
                        }
                        if (len >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) {
                            // Little endian UTF-16 byte order mark detected
                            return buffer.toString("utf16le", 2);
                        }
                        if (len >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) {
                            // UTF-8 byte order mark detected
                            return buffer.toString("utf8", 3);
                        }
                        // Default is UTF-8 with no byte order mark
                        return buffer.toString("utf8");
                    }
                    function writeFile(fileName, data, writeByteOrderMark) {
                        // If a BOM is required, emit one
                        if (writeByteOrderMark) {
                            data = '\uFEFF' + data;
                        }
                        _fs.writeFileSync(fileName, data, "utf8");
                    }
                    function readDirectory(path, extension) {
                        var result = [];
                        visitDirectory(path);
                        return result;
                        function visitDirectory(path) {
                            var files = _fs.readdirSync(path || ".").sort();
                            var directories = [];
                            for (var _i = 0; _i < files.length; _i++) {
                                var current = files[_i];
                                var name = ts.combinePaths(path, current);
                                var stat = _fs.lstatSync(name);
                                if (stat.isFile()) {
                                    if (!extension || ts.fileExtensionIs(name, extension)) {
                                        result.push(name);
                                    }
                                }
                                else if (stat.isDirectory()) {
                                    directories.push(name);
                                }
                            }
                            for (var _a = 0; _a < directories.length; _a++) {
                                var current = directories[_a];
                                visitDirectory(current);
                            }
                        }
                    }
                    return {
                        args: process.argv.slice(2),
                        newLine: _os.EOL,
                        useCaseSensitiveFileNames: useCaseSensitiveFileNames,
                        write: function (s) {
                            // 1 is a standard descriptor for stdout
                            _fs.writeSync(1, s);
                        },
                        readFile: readFile,
                        writeFile: writeFile,
                        watchFile: function (fileName, callback) {
                            // watchFile polls a file every 250ms, picking up file notifications.
                            _fs.watchFile(fileName, { persistent: true, interval: 250 }, fileChanged);
                            return {
                                close: function () { _fs.unwatchFile(fileName, fileChanged); }
                            };
                            function fileChanged(curr, prev) {
                                if (+curr.mtime <= +prev.mtime) {
                                    return;
                                }
                                callback(fileName);
                            }
                            ;
                        },
                        resolvePath: function (path) {
                            return _path.resolve(path);
                        },
                        fileExists: function (path) {
                            return _fs.existsSync(path);
                        },
                        directoryExists: function (path) {
                            return _fs.existsSync(path) && _fs.statSync(path).isDirectory();
                        },
                        createDirectory: function (directoryName) {
                            if (!this.directoryExists(directoryName)) {
                                _fs.mkdirSync(directoryName);
                            }
                        },
                        getExecutingFilePath: function () {
                            return __filename;
                        },
                        getCurrentDirectory: function () {
                            return process.cwd();
                        },
                        readDirectory: readDirectory,
                        getMemoryUsage: function () {
                            if (global.gc) {
                                global.gc();
                            }
                            return process.memoryUsage().heapUsed;
                        },
                        exit: function (exitCode) {
                            process.exit(exitCode);
                        }
                    };
                }
                if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
                    return getWScriptSystem();
                }
                else if (typeof module !== "undefined" && module.exports) {
                    return getNodeSystem();
                }
                else {
                    return undefined; // Unsupported host
                }
            })();
        })(ts || (ts = {}));
        // <auto-generated />
        /// <reference path="types.ts" />
        /* @internal */
        var ts;
        (function (ts) {
            ts.Diagnostics = {
                Unterminated_string_literal: { code: 1002, category: ts.DiagnosticCategory.Error, key: "Unterminated string literal." },
                Identifier_expected: { code: 1003, category: ts.DiagnosticCategory.Error, key: "Identifier expected." },
                _0_expected: { code: 1005, category: ts.DiagnosticCategory.Error, key: "'{0}' expected." },
                A_file_cannot_have_a_reference_to_itself: { code: 1006, category: ts.DiagnosticCategory.Error, key: "A file cannot have a reference to itself." },
                Trailing_comma_not_allowed: { code: 1009, category: ts.DiagnosticCategory.Error, key: "Trailing comma not allowed." },
                Asterisk_Slash_expected: { code: 1010, category: ts.DiagnosticCategory.Error, key: "'*/' expected." },
                Unexpected_token: { code: 1012, category: ts.DiagnosticCategory.Error, key: "Unexpected token." },
                A_rest_parameter_must_be_last_in_a_parameter_list: { code: 1014, category: ts.DiagnosticCategory.Error, key: "A rest parameter must be last in a parameter list." },
                Parameter_cannot_have_question_mark_and_initializer: { code: 1015, category: ts.DiagnosticCategory.Error, key: "Parameter cannot have question mark and initializer." },
                A_required_parameter_cannot_follow_an_optional_parameter: { code: 1016, category: ts.DiagnosticCategory.Error, key: "A required parameter cannot follow an optional parameter." },
                An_index_signature_cannot_have_a_rest_parameter: { code: 1017, category: ts.DiagnosticCategory.Error, key: "An index signature cannot have a rest parameter." },
                An_index_signature_parameter_cannot_have_an_accessibility_modifier: { code: 1018, category: ts.DiagnosticCategory.Error, key: "An index signature parameter cannot have an accessibility modifier." },
                An_index_signature_parameter_cannot_have_a_question_mark: { code: 1019, category: ts.DiagnosticCategory.Error, key: "An index signature parameter cannot have a question mark." },
                An_index_signature_parameter_cannot_have_an_initializer: { code: 1020, category: ts.DiagnosticCategory.Error, key: "An index signature parameter cannot have an initializer." },
                An_index_signature_must_have_a_type_annotation: { code: 1021, category: ts.DiagnosticCategory.Error, key: "An index signature must have a type annotation." },
                An_index_signature_parameter_must_have_a_type_annotation: { code: 1022, category: ts.DiagnosticCategory.Error, key: "An index signature parameter must have a type annotation." },
                An_index_signature_parameter_type_must_be_string_or_number: { code: 1023, category: ts.DiagnosticCategory.Error, key: "An index signature parameter type must be 'string' or 'number'." },
                A_class_or_interface_declaration_can_only_have_one_extends_clause: { code: 1024, category: ts.DiagnosticCategory.Error, key: "A class or interface declaration can only have one 'extends' clause." },
                An_extends_clause_must_precede_an_implements_clause: { code: 1025, category: ts.DiagnosticCategory.Error, key: "An 'extends' clause must precede an 'implements' clause." },
                A_class_can_only_extend_a_single_class: { code: 1026, category: ts.DiagnosticCategory.Error, key: "A class can only extend a single class." },
                A_class_declaration_can_only_have_one_implements_clause: { code: 1027, category: ts.DiagnosticCategory.Error, key: "A class declaration can only have one 'implements' clause." },
                Accessibility_modifier_already_seen: { code: 1028, category: ts.DiagnosticCategory.Error, key: "Accessibility modifier already seen." },
                _0_modifier_must_precede_1_modifier: { code: 1029, category: ts.DiagnosticCategory.Error, key: "'{0}' modifier must precede '{1}' modifier." },
                _0_modifier_already_seen: { code: 1030, category: ts.DiagnosticCategory.Error, key: "'{0}' modifier already seen." },
                _0_modifier_cannot_appear_on_a_class_element: { code: 1031, category: ts.DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a class element." },
                An_interface_declaration_cannot_have_an_implements_clause: { code: 1032, category: ts.DiagnosticCategory.Error, key: "An interface declaration cannot have an 'implements' clause." },
                super_must_be_followed_by_an_argument_list_or_member_access: { code: 1034, category: ts.DiagnosticCategory.Error, key: "'super' must be followed by an argument list or member access." },
                Only_ambient_modules_can_use_quoted_names: { code: 1035, category: ts.DiagnosticCategory.Error, key: "Only ambient modules can use quoted names." },
                Statements_are_not_allowed_in_ambient_contexts: { code: 1036, category: ts.DiagnosticCategory.Error, key: "Statements are not allowed in ambient contexts." },
                A_declare_modifier_cannot_be_used_in_an_already_ambient_context: { code: 1038, category: ts.DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used in an already ambient context." },
                Initializers_are_not_allowed_in_ambient_contexts: { code: 1039, category: ts.DiagnosticCategory.Error, key: "Initializers are not allowed in ambient contexts." },
                _0_modifier_cannot_appear_on_a_module_element: { code: 1044, category: ts.DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a module element." },
                A_declare_modifier_cannot_be_used_with_an_interface_declaration: { code: 1045, category: ts.DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used with an interface declaration." },
                A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file: { code: 1046, category: ts.DiagnosticCategory.Error, key: "A 'declare' modifier is required for a top level declaration in a .d.ts file." },
                A_rest_parameter_cannot_be_optional: { code: 1047, category: ts.DiagnosticCategory.Error, key: "A rest parameter cannot be optional." },
                A_rest_parameter_cannot_have_an_initializer: { code: 1048, category: ts.DiagnosticCategory.Error, key: "A rest parameter cannot have an initializer." },
                A_set_accessor_must_have_exactly_one_parameter: { code: 1049, category: ts.DiagnosticCategory.Error, key: "A 'set' accessor must have exactly one parameter." },
                A_set_accessor_cannot_have_an_optional_parameter: { code: 1051, category: ts.DiagnosticCategory.Error, key: "A 'set' accessor cannot have an optional parameter." },
                A_set_accessor_parameter_cannot_have_an_initializer: { code: 1052, category: ts.DiagnosticCategory.Error, key: "A 'set' accessor parameter cannot have an initializer." },
                A_set_accessor_cannot_have_rest_parameter: { code: 1053, category: ts.DiagnosticCategory.Error, key: "A 'set' accessor cannot have rest parameter." },
                A_get_accessor_cannot_have_parameters: { code: 1054, category: ts.DiagnosticCategory.Error, key: "A 'get' accessor cannot have parameters." },
                Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher: { code: 1056, category: ts.DiagnosticCategory.Error, key: "Accessors are only available when targeting ECMAScript 5 and higher." },
                Enum_member_must_have_initializer: { code: 1061, category: ts.DiagnosticCategory.Error, key: "Enum member must have initializer." },
                An_export_assignment_cannot_be_used_in_an_internal_module: { code: 1063, category: ts.DiagnosticCategory.Error, key: "An export assignment cannot be used in an internal module." },
                Ambient_enum_elements_can_only_have_integer_literal_initializers: { code: 1066, category: ts.DiagnosticCategory.Error, key: "Ambient enum elements can only have integer literal initializers." },
                Unexpected_token_A_constructor_method_accessor_or_property_was_expected: { code: 1068, category: ts.DiagnosticCategory.Error, key: "Unexpected token. A constructor, method, accessor, or property was expected." },
                A_declare_modifier_cannot_be_used_with_an_import_declaration: { code: 1079, category: ts.DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used with an import declaration." },
                Invalid_reference_directive_syntax: { code: 1084, category: ts.DiagnosticCategory.Error, key: "Invalid 'reference' directive syntax." },
                Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher: { code: 1085, category: ts.DiagnosticCategory.Error, key: "Octal literals are not available when targeting ECMAScript 5 and higher." },
                An_accessor_cannot_be_declared_in_an_ambient_context: { code: 1086, category: ts.DiagnosticCategory.Error, key: "An accessor cannot be declared in an ambient context." },
                _0_modifier_cannot_appear_on_a_constructor_declaration: { code: 1089, category: ts.DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a constructor declaration." },
                _0_modifier_cannot_appear_on_a_parameter: { code: 1090, category: ts.DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a parameter." },
                Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement: { code: 1091, category: ts.DiagnosticCategory.Error, key: "Only a single variable declaration is allowed in a 'for...in' statement." },
                Type_parameters_cannot_appear_on_a_constructor_declaration: { code: 1092, category: ts.DiagnosticCategory.Error, key: "Type parameters cannot appear on a constructor declaration." },
                Type_annotation_cannot_appear_on_a_constructor_declaration: { code: 1093, category: ts.DiagnosticCategory.Error, key: "Type annotation cannot appear on a constructor declaration." },
                An_accessor_cannot_have_type_parameters: { code: 1094, category: ts.DiagnosticCategory.Error, key: "An accessor cannot have type parameters." },
                A_set_accessor_cannot_have_a_return_type_annotation: { code: 1095, category: ts.DiagnosticCategory.Error, key: "A 'set' accessor cannot have a return type annotation." },
                An_index_signature_must_have_exactly_one_parameter: { code: 1096, category: ts.DiagnosticCategory.Error, key: "An index signature must have exactly one parameter." },
                _0_list_cannot_be_empty: { code: 1097, category: ts.DiagnosticCategory.Error, key: "'{0}' list cannot be empty." },
                Type_parameter_list_cannot_be_empty: { code: 1098, category: ts.DiagnosticCategory.Error, key: "Type parameter list cannot be empty." },
                Type_argument_list_cannot_be_empty: { code: 1099, category: ts.DiagnosticCategory.Error, key: "Type argument list cannot be empty." },
                Invalid_use_of_0_in_strict_mode: { code: 1100, category: ts.DiagnosticCategory.Error, key: "Invalid use of '{0}' in strict mode." },
                with_statements_are_not_allowed_in_strict_mode: { code: 1101, category: ts.DiagnosticCategory.Error, key: "'with' statements are not allowed in strict mode." },
                delete_cannot_be_called_on_an_identifier_in_strict_mode: { code: 1102, category: ts.DiagnosticCategory.Error, key: "'delete' cannot be called on an identifier in strict mode." },
                A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement: { code: 1104, category: ts.DiagnosticCategory.Error, key: "A 'continue' statement can only be used within an enclosing iteration statement." },
                A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement: { code: 1105, category: ts.DiagnosticCategory.Error, key: "A 'break' statement can only be used within an enclosing iteration or switch statement." },
                Jump_target_cannot_cross_function_boundary: { code: 1107, category: ts.DiagnosticCategory.Error, key: "Jump target cannot cross function boundary." },
                A_return_statement_can_only_be_used_within_a_function_body: { code: 1108, category: ts.DiagnosticCategory.Error, key: "A 'return' statement can only be used within a function body." },
                Expression_expected: { code: 1109, category: ts.DiagnosticCategory.Error, key: "Expression expected." },
                Type_expected: { code: 1110, category: ts.DiagnosticCategory.Error, key: "Type expected." },
                A_class_member_cannot_be_declared_optional: { code: 1112, category: ts.DiagnosticCategory.Error, key: "A class member cannot be declared optional." },
                A_default_clause_cannot_appear_more_than_once_in_a_switch_statement: { code: 1113, category: ts.DiagnosticCategory.Error, key: "A 'default' clause cannot appear more than once in a 'switch' statement." },
                Duplicate_label_0: { code: 1114, category: ts.DiagnosticCategory.Error, key: "Duplicate label '{0}'" },
                A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement: { code: 1115, category: ts.DiagnosticCategory.Error, key: "A 'continue' statement can only jump to a label of an enclosing iteration statement." },
                A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement: { code: 1116, category: ts.DiagnosticCategory.Error, key: "A 'break' statement can only jump to a label of an enclosing statement." },
                An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode: { code: 1117, category: ts.DiagnosticCategory.Error, key: "An object literal cannot have multiple properties with the same name in strict mode." },
                An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name: { code: 1118, category: ts.DiagnosticCategory.Error, key: "An object literal cannot have multiple get/set accessors with the same name." },
                An_object_literal_cannot_have_property_and_accessor_with_the_same_name: { code: 1119, category: ts.DiagnosticCategory.Error, key: "An object literal cannot have property and accessor with the same name." },
                An_export_assignment_cannot_have_modifiers: { code: 1120, category: ts.DiagnosticCategory.Error, key: "An export assignment cannot have modifiers." },
                Octal_literals_are_not_allowed_in_strict_mode: { code: 1121, category: ts.DiagnosticCategory.Error, key: "Octal literals are not allowed in strict mode." },
                A_tuple_type_element_list_cannot_be_empty: { code: 1122, category: ts.DiagnosticCategory.Error, key: "A tuple type element list cannot be empty." },
                Variable_declaration_list_cannot_be_empty: { code: 1123, category: ts.DiagnosticCategory.Error, key: "Variable declaration list cannot be empty." },
                Digit_expected: { code: 1124, category: ts.DiagnosticCategory.Error, key: "Digit expected." },
                Hexadecimal_digit_expected: { code: 1125, category: ts.DiagnosticCategory.Error, key: "Hexadecimal digit expected." },
                Unexpected_end_of_text: { code: 1126, category: ts.DiagnosticCategory.Error, key: "Unexpected end of text." },
                Invalid_character: { code: 1127, category: ts.DiagnosticCategory.Error, key: "Invalid character." },
                Declaration_or_statement_expected: { code: 1128, category: ts.DiagnosticCategory.Error, key: "Declaration or statement expected." },
                Statement_expected: { code: 1129, category: ts.DiagnosticCategory.Error, key: "Statement expected." },
                case_or_default_expected: { code: 1130, category: ts.DiagnosticCategory.Error, key: "'case' or 'default' expected." },
                Property_or_signature_expected: { code: 1131, category: ts.DiagnosticCategory.Error, key: "Property or signature expected." },
                Enum_member_expected: { code: 1132, category: ts.DiagnosticCategory.Error, key: "Enum member expected." },
                Type_reference_expected: { code: 1133, category: ts.DiagnosticCategory.Error, key: "Type reference expected." },
                Variable_declaration_expected: { code: 1134, category: ts.DiagnosticCategory.Error, key: "Variable declaration expected." },
                Argument_expression_expected: { code: 1135, category: ts.DiagnosticCategory.Error, key: "Argument expression expected." },
                Property_assignment_expected: { code: 1136, category: ts.DiagnosticCategory.Error, key: "Property assignment expected." },
                Expression_or_comma_expected: { code: 1137, category: ts.DiagnosticCategory.Error, key: "Expression or comma expected." },
                Parameter_declaration_expected: { code: 1138, category: ts.DiagnosticCategory.Error, key: "Parameter declaration expected." },
                Type_parameter_declaration_expected: { code: 1139, category: ts.DiagnosticCategory.Error, key: "Type parameter declaration expected." },
                Type_argument_expected: { code: 1140, category: ts.DiagnosticCategory.Error, key: "Type argument expected." },
                String_literal_expected: { code: 1141, category: ts.DiagnosticCategory.Error, key: "String literal expected." },
                Line_break_not_permitted_here: { code: 1142, category: ts.DiagnosticCategory.Error, key: "Line break not permitted here." },
                or_expected: { code: 1144, category: ts.DiagnosticCategory.Error, key: "'{' or ';' expected." },
                Modifiers_not_permitted_on_index_signature_members: { code: 1145, category: ts.DiagnosticCategory.Error, key: "Modifiers not permitted on index signature members." },
                Declaration_expected: { code: 1146, category: ts.DiagnosticCategory.Error, key: "Declaration expected." },
                Import_declarations_in_an_internal_module_cannot_reference_an_external_module: { code: 1147, category: ts.DiagnosticCategory.Error, key: "Import declarations in an internal module cannot reference an external module." },
                Cannot_compile_external_modules_unless_the_module_flag_is_provided: { code: 1148, category: ts.DiagnosticCategory.Error, key: "Cannot compile external modules unless the '--module' flag is provided." },
                File_name_0_differs_from_already_included_file_name_1_only_in_casing: { code: 1149, category: ts.DiagnosticCategory.Error, key: "File name '{0}' differs from already included file name '{1}' only in casing" },
                new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead: { code: 1150, category: ts.DiagnosticCategory.Error, key: "'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead." },
                var_let_or_const_expected: { code: 1152, category: ts.DiagnosticCategory.Error, key: "'var', 'let' or 'const' expected." },
                let_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1153, category: ts.DiagnosticCategory.Error, key: "'let' declarations are only available when targeting ECMAScript 6 and higher." },
                const_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1154, category: ts.DiagnosticCategory.Error, key: "'const' declarations are only available when targeting ECMAScript 6 and higher." },
                const_declarations_must_be_initialized: { code: 1155, category: ts.DiagnosticCategory.Error, key: "'const' declarations must be initialized" },
                const_declarations_can_only_be_declared_inside_a_block: { code: 1156, category: ts.DiagnosticCategory.Error, key: "'const' declarations can only be declared inside a block." },
                let_declarations_can_only_be_declared_inside_a_block: { code: 1157, category: ts.DiagnosticCategory.Error, key: "'let' declarations can only be declared inside a block." },
                Unterminated_template_literal: { code: 1160, category: ts.DiagnosticCategory.Error, key: "Unterminated template literal." },
                Unterminated_regular_expression_literal: { code: 1161, category: ts.DiagnosticCategory.Error, key: "Unterminated regular expression literal." },
                An_object_member_cannot_be_declared_optional: { code: 1162, category: ts.DiagnosticCategory.Error, key: "An object member cannot be declared optional." },
                yield_expression_must_be_contained_within_a_generator_declaration: { code: 1163, category: ts.DiagnosticCategory.Error, key: "'yield' expression must be contained_within a generator declaration." },
                Computed_property_names_are_not_allowed_in_enums: { code: 1164, category: ts.DiagnosticCategory.Error, key: "Computed property names are not allowed in enums." },
                A_computed_property_name_in_an_ambient_context_must_directly_refer_to_a_built_in_symbol: { code: 1165, category: ts.DiagnosticCategory.Error, key: "A computed property name in an ambient context must directly refer to a built-in symbol." },
                A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol: { code: 1166, category: ts.DiagnosticCategory.Error, key: "A computed property name in a class property declaration must directly refer to a built-in symbol." },
                Computed_property_names_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1167, category: ts.DiagnosticCategory.Error, key: "Computed property names are only available when targeting ECMAScript 6 and higher." },
                A_computed_property_name_in_a_method_overload_must_directly_refer_to_a_built_in_symbol: { code: 1168, category: ts.DiagnosticCategory.Error, key: "A computed property name in a method overload must directly refer to a built-in symbol." },
                A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol: { code: 1169, category: ts.DiagnosticCategory.Error, key: "A computed property name in an interface must directly refer to a built-in symbol." },
                A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol: { code: 1170, category: ts.DiagnosticCategory.Error, key: "A computed property name in a type literal must directly refer to a built-in symbol." },
                A_comma_expression_is_not_allowed_in_a_computed_property_name: { code: 1171, category: ts.DiagnosticCategory.Error, key: "A comma expression is not allowed in a computed property name." },
                extends_clause_already_seen: { code: 1172, category: ts.DiagnosticCategory.Error, key: "'extends' clause already seen." },
                extends_clause_must_precede_implements_clause: { code: 1173, category: ts.DiagnosticCategory.Error, key: "'extends' clause must precede 'implements' clause." },
                Classes_can_only_extend_a_single_class: { code: 1174, category: ts.DiagnosticCategory.Error, key: "Classes can only extend a single class." },
                implements_clause_already_seen: { code: 1175, category: ts.DiagnosticCategory.Error, key: "'implements' clause already seen." },
                Interface_declaration_cannot_have_implements_clause: { code: 1176, category: ts.DiagnosticCategory.Error, key: "Interface declaration cannot have 'implements' clause." },
                Binary_digit_expected: { code: 1177, category: ts.DiagnosticCategory.Error, key: "Binary digit expected." },
                Octal_digit_expected: { code: 1178, category: ts.DiagnosticCategory.Error, key: "Octal digit expected." },
                Unexpected_token_expected: { code: 1179, category: ts.DiagnosticCategory.Error, key: "Unexpected token. '{' expected." },
                Property_destructuring_pattern_expected: { code: 1180, category: ts.DiagnosticCategory.Error, key: "Property destructuring pattern expected." },
                Array_element_destructuring_pattern_expected: { code: 1181, category: ts.DiagnosticCategory.Error, key: "Array element destructuring pattern expected." },
                A_destructuring_declaration_must_have_an_initializer: { code: 1182, category: ts.DiagnosticCategory.Error, key: "A destructuring declaration must have an initializer." },
                Destructuring_declarations_are_not_allowed_in_ambient_contexts: { code: 1183, category: ts.DiagnosticCategory.Error, key: "Destructuring declarations are not allowed in ambient contexts." },
                An_implementation_cannot_be_declared_in_ambient_contexts: { code: 1184, category: ts.DiagnosticCategory.Error, key: "An implementation cannot be declared in ambient contexts." },
                Modifiers_cannot_appear_here: { code: 1184, category: ts.DiagnosticCategory.Error, key: "Modifiers cannot appear here." },
                Merge_conflict_marker_encountered: { code: 1185, category: ts.DiagnosticCategory.Error, key: "Merge conflict marker encountered." },
                A_rest_element_cannot_have_an_initializer: { code: 1186, category: ts.DiagnosticCategory.Error, key: "A rest element cannot have an initializer." },
                A_parameter_property_may_not_be_a_binding_pattern: { code: 1187, category: ts.DiagnosticCategory.Error, key: "A parameter property may not be a binding pattern." },
                Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement: { code: 1188, category: ts.DiagnosticCategory.Error, key: "Only a single variable declaration is allowed in a 'for...of' statement." },
                The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer: { code: 1189, category: ts.DiagnosticCategory.Error, key: "The variable declaration of a 'for...in' statement cannot have an initializer." },
                The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer: { code: 1190, category: ts.DiagnosticCategory.Error, key: "The variable declaration of a 'for...of' statement cannot have an initializer." },
                An_import_declaration_cannot_have_modifiers: { code: 1191, category: ts.DiagnosticCategory.Error, key: "An import declaration cannot have modifiers." },
                External_module_0_has_no_default_export: { code: 1192, category: ts.DiagnosticCategory.Error, key: "External module '{0}' has no default export." },
                An_export_declaration_cannot_have_modifiers: { code: 1193, category: ts.DiagnosticCategory.Error, key: "An export declaration cannot have modifiers." },
                Export_declarations_are_not_permitted_in_an_internal_module: { code: 1194, category: ts.DiagnosticCategory.Error, key: "Export declarations are not permitted in an internal module." },
                Catch_clause_variable_name_must_be_an_identifier: { code: 1195, category: ts.DiagnosticCategory.Error, key: "Catch clause variable name must be an identifier." },
                Catch_clause_variable_cannot_have_a_type_annotation: { code: 1196, category: ts.DiagnosticCategory.Error, key: "Catch clause variable cannot have a type annotation." },
                Catch_clause_variable_cannot_have_an_initializer: { code: 1197, category: ts.DiagnosticCategory.Error, key: "Catch clause variable cannot have an initializer." },
                An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive: { code: 1198, category: ts.DiagnosticCategory.Error, key: "An extended Unicode escape value must be between 0x0 and 0x10FFFF inclusive." },
                Unterminated_Unicode_escape_sequence: { code: 1199, category: ts.DiagnosticCategory.Error, key: "Unterminated Unicode escape sequence." },
                Line_terminator_not_permitted_before_arrow: { code: 1200, category: ts.DiagnosticCategory.Error, key: "Line terminator not permitted before arrow." },
                Import_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_or_import_d_from_mod_instead: { code: 1202, category: ts.DiagnosticCategory.Error, key: "Import assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'import * as ns from \"mod\"', 'import {a} from \"mod\"' or 'import d from \"mod\"' instead." },
                Export_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_export_default_instead: { code: 1203, category: ts.DiagnosticCategory.Error, key: "Export assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'export default' instead." },
                Cannot_compile_external_modules_into_amd_commonjs_or_umd_when_targeting_ES6_or_higher: { code: 1204, category: ts.DiagnosticCategory.Error, key: "Cannot compile external modules into 'amd', 'commonjs' or 'umd' when targeting 'ES6' or higher." },
                Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher: { code: 1205, category: ts.DiagnosticCategory.Error, key: "Decorators are only available when targeting ECMAScript 5 and higher." },
                Decorators_are_not_valid_here: { code: 1206, category: ts.DiagnosticCategory.Error, key: "Decorators are not valid here." },
                Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name: { code: 1207, category: ts.DiagnosticCategory.Error, key: "Decorators cannot be applied to multiple get/set accessors of the same name." },
                Cannot_compile_non_external_modules_when_the_separateCompilation_flag_is_provided: { code: 1208, category: ts.DiagnosticCategory.Error, key: "Cannot compile non-external modules when the '--separateCompilation' flag is provided." },
                Ambient_const_enums_are_not_allowed_when_the_separateCompilation_flag_is_provided: { code: 1209, category: ts.DiagnosticCategory.Error, key: "Ambient const enums are not allowed when the '--separateCompilation' flag is provided." },
                Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode: { code: 1210, category: ts.DiagnosticCategory.Error, key: "Invalid use of '{0}'. Class definitions are automatically in strict mode." },
                A_class_declaration_without_the_default_modifier_must_have_a_name: { code: 1211, category: ts.DiagnosticCategory.Error, key: "A class declaration without the 'default' modifier must have a name" },
                Identifier_expected_0_is_a_reserved_word_in_strict_mode: { code: 1212, category: ts.DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode" },
                Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1213, category: ts.DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
                Identifier_expected_0_is_a_reserved_word_in_strict_mode_External_Module_is_automatically_in_strict_mode: { code: 1214, category: ts.DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. External Module is automatically in strict mode." },
                Type_expected_0_is_a_reserved_word_in_strict_mode: { code: 1215, category: ts.DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode" },
                Type_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1216, category: ts.DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
                Type_expected_0_is_a_reserved_word_in_strict_mode_Module_is_automatically_in_strict_mode: { code: 1217, category: ts.DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Module is automatically in strict mode." },
                Duplicate_identifier_0: { code: 2300, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
                Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: ts.DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
                Static_members_cannot_reference_class_type_parameters: { code: 2302, category: ts.DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
                Circular_definition_of_import_alias_0: { code: 2303, category: ts.DiagnosticCategory.Error, key: "Circular definition of import alias '{0}'." },
                Cannot_find_name_0: { code: 2304, category: ts.DiagnosticCategory.Error, key: "Cannot find name '{0}'." },
                Module_0_has_no_exported_member_1: { code: 2305, category: ts.DiagnosticCategory.Error, key: "Module '{0}' has no exported member '{1}'." },
                File_0_is_not_an_external_module: { code: 2306, category: ts.DiagnosticCategory.Error, key: "File '{0}' is not an external module." },
                Cannot_find_external_module_0: { code: 2307, category: ts.DiagnosticCategory.Error, key: "Cannot find external module '{0}'." },
                A_module_cannot_have_more_than_one_export_assignment: { code: 2308, category: ts.DiagnosticCategory.Error, key: "A module cannot have more than one export assignment." },
                An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements: { code: 2309, category: ts.DiagnosticCategory.Error, key: "An export assignment cannot be used in a module with other exported elements." },
                Type_0_recursively_references_itself_as_a_base_type: { code: 2310, category: ts.DiagnosticCategory.Error, key: "Type '{0}' recursively references itself as a base type." },
                A_class_may_only_extend_another_class: { code: 2311, category: ts.DiagnosticCategory.Error, key: "A class may only extend another class." },
                An_interface_may_only_extend_a_class_or_another_interface: { code: 2312, category: ts.DiagnosticCategory.Error, key: "An interface may only extend a class or another interface." },
                Constraint_of_a_type_parameter_cannot_reference_any_type_parameter_from_the_same_type_parameter_list: { code: 2313, category: ts.DiagnosticCategory.Error, key: "Constraint of a type parameter cannot reference any type parameter from the same type parameter list." },
                Generic_type_0_requires_1_type_argument_s: { code: 2314, category: ts.DiagnosticCategory.Error, key: "Generic type '{0}' requires {1} type argument(s)." },
                Type_0_is_not_generic: { code: 2315, category: ts.DiagnosticCategory.Error, key: "Type '{0}' is not generic." },
                Global_type_0_must_be_a_class_or_interface_type: { code: 2316, category: ts.DiagnosticCategory.Error, key: "Global type '{0}' must be a class or interface type." },
                Global_type_0_must_have_1_type_parameter_s: { code: 2317, category: ts.DiagnosticCategory.Error, key: "Global type '{0}' must have {1} type parameter(s)." },
                Cannot_find_global_type_0: { code: 2318, category: ts.DiagnosticCategory.Error, key: "Cannot find global type '{0}'." },
                Named_property_0_of_types_1_and_2_are_not_identical: { code: 2319, category: ts.DiagnosticCategory.Error, key: "Named property '{0}' of types '{1}' and '{2}' are not identical." },
                Interface_0_cannot_simultaneously_extend_types_1_and_2: { code: 2320, category: ts.DiagnosticCategory.Error, key: "Interface '{0}' cannot simultaneously extend types '{1}' and '{2}'." },
                Excessive_stack_depth_comparing_types_0_and_1: { code: 2321, category: ts.DiagnosticCategory.Error, key: "Excessive stack depth comparing types '{0}' and '{1}'." },
                Type_0_is_not_assignable_to_type_1: { code: 2322, category: ts.DiagnosticCategory.Error, key: "Type '{0}' is not assignable to type '{1}'." },
                Property_0_is_missing_in_type_1: { code: 2324, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is missing in type '{1}'." },
                Property_0_is_private_in_type_1_but_not_in_type_2: { code: 2325, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is private in type '{1}' but not in type '{2}'." },
                Types_of_property_0_are_incompatible: { code: 2326, category: ts.DiagnosticCategory.Error, key: "Types of property '{0}' are incompatible." },
                Property_0_is_optional_in_type_1_but_required_in_type_2: { code: 2327, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is optional in type '{1}' but required in type '{2}'." },
                Types_of_parameters_0_and_1_are_incompatible: { code: 2328, category: ts.DiagnosticCategory.Error, key: "Types of parameters '{0}' and '{1}' are incompatible." },
                Index_signature_is_missing_in_type_0: { code: 2329, category: ts.DiagnosticCategory.Error, key: "Index signature is missing in type '{0}'." },
                Index_signatures_are_incompatible: { code: 2330, category: ts.DiagnosticCategory.Error, key: "Index signatures are incompatible." },
                this_cannot_be_referenced_in_a_module_body: { code: 2331, category: ts.DiagnosticCategory.Error, key: "'this' cannot be referenced in a module body." },
                this_cannot_be_referenced_in_current_location: { code: 2332, category: ts.DiagnosticCategory.Error, key: "'this' cannot be referenced in current location." },
                this_cannot_be_referenced_in_constructor_arguments: { code: 2333, category: ts.DiagnosticCategory.Error, key: "'this' cannot be referenced in constructor arguments." },
                this_cannot_be_referenced_in_a_static_property_initializer: { code: 2334, category: ts.DiagnosticCategory.Error, key: "'this' cannot be referenced in a static property initializer." },
                super_can_only_be_referenced_in_a_derived_class: { code: 2335, category: ts.DiagnosticCategory.Error, key: "'super' can only be referenced in a derived class." },
                super_cannot_be_referenced_in_constructor_arguments: { code: 2336, category: ts.DiagnosticCategory.Error, key: "'super' cannot be referenced in constructor arguments." },
                Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors: { code: 2337, category: ts.DiagnosticCategory.Error, key: "Super calls are not permitted outside constructors or in nested functions inside constructors" },
                super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class: { code: 2338, category: ts.DiagnosticCategory.Error, key: "'super' property access is permitted only in a constructor, member function, or member accessor of a derived class" },
                Property_0_does_not_exist_on_type_1: { code: 2339, category: ts.DiagnosticCategory.Error, key: "Property '{0}' does not exist on type '{1}'." },
                Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword: { code: 2340, category: ts.DiagnosticCategory.Error, key: "Only public and protected methods of the base class are accessible via the 'super' keyword" },
                Property_0_is_private_and_only_accessible_within_class_1: { code: 2341, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is private and only accessible within class '{1}'." },
                An_index_expression_argument_must_be_of_type_string_number_symbol_or_any: { code: 2342, category: ts.DiagnosticCategory.Error, key: "An index expression argument must be of type 'string', 'number', 'symbol, or 'any'." },
                Type_0_does_not_satisfy_the_constraint_1: { code: 2344, category: ts.DiagnosticCategory.Error, key: "Type '{0}' does not satisfy the constraint '{1}'." },
                Argument_of_type_0_is_not_assignable_to_parameter_of_type_1: { code: 2345, category: ts.DiagnosticCategory.Error, key: "Argument of type '{0}' is not assignable to parameter of type '{1}'." },
                Supplied_parameters_do_not_match_any_signature_of_call_target: { code: 2346, category: ts.DiagnosticCategory.Error, key: "Supplied parameters do not match any signature of call target." },
                Untyped_function_calls_may_not_accept_type_arguments: { code: 2347, category: ts.DiagnosticCategory.Error, key: "Untyped function calls may not accept type arguments." },
                Value_of_type_0_is_not_callable_Did_you_mean_to_include_new: { code: 2348, category: ts.DiagnosticCategory.Error, key: "Value of type '{0}' is not callable. Did you mean to include 'new'?" },
                Cannot_invoke_an_expression_whose_type_lacks_a_call_signature: { code: 2349, category: ts.DiagnosticCategory.Error, key: "Cannot invoke an expression whose type lacks a call signature." },
                Only_a_void_function_can_be_called_with_the_new_keyword: { code: 2350, category: ts.DiagnosticCategory.Error, key: "Only a void function can be called with the 'new' keyword." },
                Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature: { code: 2351, category: ts.DiagnosticCategory.Error, key: "Cannot use 'new' with an expression whose type lacks a call or construct signature." },
                Neither_type_0_nor_type_1_is_assignable_to_the_other: { code: 2352, category: ts.DiagnosticCategory.Error, key: "Neither type '{0}' nor type '{1}' is assignable to the other." },
                No_best_common_type_exists_among_return_expressions: { code: 2354, category: ts.DiagnosticCategory.Error, key: "No best common type exists among return expressions." },
                A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2355, category: ts.DiagnosticCategory.Error, key: "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement." },
                An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type: { code: 2356, category: ts.DiagnosticCategory.Error, key: "An arithmetic operand must be of type 'any', 'number' or an enum type." },
                The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer: { code: 2357, category: ts.DiagnosticCategory.Error, key: "The operand of an increment or decrement operator must be a variable, property or indexer." },
                The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2358, category: ts.DiagnosticCategory.Error, key: "The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter." },
                The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type: { code: 2359, category: ts.DiagnosticCategory.Error, key: "The right-hand side of an 'instanceof' expression must be of type 'any' or of a type assignable to the 'Function' interface type." },
                The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol: { code: 2360, category: ts.DiagnosticCategory.Error, key: "The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'." },
                The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2361, category: ts.DiagnosticCategory.Error, key: "The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter" },
                The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type: { code: 2362, category: ts.DiagnosticCategory.Error, key: "The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type." },
                The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type: { code: 2363, category: ts.DiagnosticCategory.Error, key: "The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type." },
                Invalid_left_hand_side_of_assignment_expression: { code: 2364, category: ts.DiagnosticCategory.Error, key: "Invalid left-hand side of assignment expression." },
                Operator_0_cannot_be_applied_to_types_1_and_2: { code: 2365, category: ts.DiagnosticCategory.Error, key: "Operator '{0}' cannot be applied to types '{1}' and '{2}'." },
                Type_parameter_name_cannot_be_0: { code: 2368, category: ts.DiagnosticCategory.Error, key: "Type parameter name cannot be '{0}'" },
                A_parameter_property_is_only_allowed_in_a_constructor_implementation: { code: 2369, category: ts.DiagnosticCategory.Error, key: "A parameter property is only allowed in a constructor implementation." },
                A_rest_parameter_must_be_of_an_array_type: { code: 2370, category: ts.DiagnosticCategory.Error, key: "A rest parameter must be of an array type." },
                A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation: { code: 2371, category: ts.DiagnosticCategory.Error, key: "A parameter initializer is only allowed in a function or constructor implementation." },
                Parameter_0_cannot_be_referenced_in_its_initializer: { code: 2372, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' cannot be referenced in its initializer." },
                Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it: { code: 2373, category: ts.DiagnosticCategory.Error, key: "Initializer of parameter '{0}' cannot reference identifier '{1}' declared after it." },
                Duplicate_string_index_signature: { code: 2374, category: ts.DiagnosticCategory.Error, key: "Duplicate string index signature." },
                Duplicate_number_index_signature: { code: 2375, category: ts.DiagnosticCategory.Error, key: "Duplicate number index signature." },
                A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties: { code: 2376, category: ts.DiagnosticCategory.Error, key: "A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties." },
                Constructors_for_derived_classes_must_contain_a_super_call: { code: 2377, category: ts.DiagnosticCategory.Error, key: "Constructors for derived classes must contain a 'super' call." },
                A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2378, category: ts.DiagnosticCategory.Error, key: "A 'get' accessor must return a value or consist of a single 'throw' statement." },
                Getter_and_setter_accessors_do_not_agree_in_visibility: { code: 2379, category: ts.DiagnosticCategory.Error, key: "Getter and setter accessors do not agree in visibility." },
                get_and_set_accessor_must_have_the_same_type: { code: 2380, category: ts.DiagnosticCategory.Error, key: "'get' and 'set' accessor must have the same type." },
                A_signature_with_an_implementation_cannot_use_a_string_literal_type: { code: 2381, category: ts.DiagnosticCategory.Error, key: "A signature with an implementation cannot use a string literal type." },
                Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature: { code: 2382, category: ts.DiagnosticCategory.Error, key: "Specialized overload signature is not assignable to any non-specialized signature." },
                Overload_signatures_must_all_be_exported_or_not_exported: { code: 2383, category: ts.DiagnosticCategory.Error, key: "Overload signatures must all be exported or not exported." },
                Overload_signatures_must_all_be_ambient_or_non_ambient: { code: 2384, category: ts.DiagnosticCategory.Error, key: "Overload signatures must all be ambient or non-ambient." },
                Overload_signatures_must_all_be_public_private_or_protected: { code: 2385, category: ts.DiagnosticCategory.Error, key: "Overload signatures must all be public, private or protected." },
                Overload_signatures_must_all_be_optional_or_required: { code: 2386, category: ts.DiagnosticCategory.Error, key: "Overload signatures must all be optional or required." },
                Function_overload_must_be_static: { code: 2387, category: ts.DiagnosticCategory.Error, key: "Function overload must be static." },
                Function_overload_must_not_be_static: { code: 2388, category: ts.DiagnosticCategory.Error, key: "Function overload must not be static." },
                Function_implementation_name_must_be_0: { code: 2389, category: ts.DiagnosticCategory.Error, key: "Function implementation name must be '{0}'." },
                Constructor_implementation_is_missing: { code: 2390, category: ts.DiagnosticCategory.Error, key: "Constructor implementation is missing." },
                Function_implementation_is_missing_or_not_immediately_following_the_declaration: { code: 2391, category: ts.DiagnosticCategory.Error, key: "Function implementation is missing or not immediately following the declaration." },
                Multiple_constructor_implementations_are_not_allowed: { code: 2392, category: ts.DiagnosticCategory.Error, key: "Multiple constructor implementations are not allowed." },
                Duplicate_function_implementation: { code: 2393, category: ts.DiagnosticCategory.Error, key: "Duplicate function implementation." },
                Overload_signature_is_not_compatible_with_function_implementation: { code: 2394, category: ts.DiagnosticCategory.Error, key: "Overload signature is not compatible with function implementation." },
                Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local: { code: 2395, category: ts.DiagnosticCategory.Error, key: "Individual declarations in merged declaration {0} must be all exported or all local." },
                Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters: { code: 2396, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier 'arguments'. Compiler uses 'arguments' to initialize rest parameters." },
                Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference: { code: 2399, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference." },
                Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference: { code: 2400, category: ts.DiagnosticCategory.Error, key: "Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference." },
                Duplicate_identifier_super_Compiler_uses_super_to_capture_base_class_reference: { code: 2401, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier '_super'. Compiler uses '_super' to capture base class reference." },
                Expression_resolves_to_super_that_compiler_uses_to_capture_base_class_reference: { code: 2402, category: ts.DiagnosticCategory.Error, key: "Expression resolves to '_super' that compiler uses to capture base class reference." },
                Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2: { code: 2403, category: ts.DiagnosticCategory.Error, key: "Subsequent variable declarations must have the same type.  Variable '{0}' must be of type '{1}', but here has type '{2}'." },
                The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation: { code: 2404, category: ts.DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot use a type annotation." },
                The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any: { code: 2405, category: ts.DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement must be of type 'string' or 'any'." },
                Invalid_left_hand_side_in_for_in_statement: { code: 2406, category: ts.DiagnosticCategory.Error, key: "Invalid left-hand side in 'for...in' statement." },
                The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2407, category: ts.DiagnosticCategory.Error, key: "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter." },
                Setters_cannot_return_a_value: { code: 2408, category: ts.DiagnosticCategory.Error, key: "Setters cannot return a value." },
                Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class: { code: 2409, category: ts.DiagnosticCategory.Error, key: "Return type of constructor signature must be assignable to the instance type of the class" },
                All_symbols_within_a_with_block_will_be_resolved_to_any: { code: 2410, category: ts.DiagnosticCategory.Error, key: "All symbols within a 'with' block will be resolved to 'any'." },
                Property_0_of_type_1_is_not_assignable_to_string_index_type_2: { code: 2411, category: ts.DiagnosticCategory.Error, key: "Property '{0}' of type '{1}' is not assignable to string index type '{2}'." },
                Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2: { code: 2412, category: ts.DiagnosticCategory.Error, key: "Property '{0}' of type '{1}' is not assignable to numeric index type '{2}'." },
                Numeric_index_type_0_is_not_assignable_to_string_index_type_1: { code: 2413, category: ts.DiagnosticCategory.Error, key: "Numeric index type '{0}' is not assignable to string index type '{1}'." },
                Class_name_cannot_be_0: { code: 2414, category: ts.DiagnosticCategory.Error, key: "Class name cannot be '{0}'" },
                Class_0_incorrectly_extends_base_class_1: { code: 2415, category: ts.DiagnosticCategory.Error, key: "Class '{0}' incorrectly extends base class '{1}'." },
                Class_static_side_0_incorrectly_extends_base_class_static_side_1: { code: 2417, category: ts.DiagnosticCategory.Error, key: "Class static side '{0}' incorrectly extends base class static side '{1}'." },
                Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0: { code: 2419, category: ts.DiagnosticCategory.Error, key: "Type name '{0}' in extends clause does not reference constructor function for '{0}'." },
                Class_0_incorrectly_implements_interface_1: { code: 2420, category: ts.DiagnosticCategory.Error, key: "Class '{0}' incorrectly implements interface '{1}'." },
                A_class_may_only_implement_another_class_or_interface: { code: 2422, category: ts.DiagnosticCategory.Error, key: "A class may only implement another class or interface." },
                Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor: { code: 2423, category: ts.DiagnosticCategory.Error, key: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member accessor." },
                Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property: { code: 2424, category: ts.DiagnosticCategory.Error, key: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member property." },
                Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function: { code: 2425, category: ts.DiagnosticCategory.Error, key: "Class '{0}' defines instance member property '{1}', but extended class '{2}' defines it as instance member function." },
                Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function: { code: 2426, category: ts.DiagnosticCategory.Error, key: "Class '{0}' defines instance member accessor '{1}', but extended class '{2}' defines it as instance member function." },
                Interface_name_cannot_be_0: { code: 2427, category: ts.DiagnosticCategory.Error, key: "Interface name cannot be '{0}'" },
                All_declarations_of_an_interface_must_have_identical_type_parameters: { code: 2428, category: ts.DiagnosticCategory.Error, key: "All declarations of an interface must have identical type parameters." },
                Interface_0_incorrectly_extends_interface_1: { code: 2430, category: ts.DiagnosticCategory.Error, key: "Interface '{0}' incorrectly extends interface '{1}'." },
                Enum_name_cannot_be_0: { code: 2431, category: ts.DiagnosticCategory.Error, key: "Enum name cannot be '{0}'" },
                In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element: { code: 2432, category: ts.DiagnosticCategory.Error, key: "In an enum with multiple declarations, only one declaration can omit an initializer for its first enum element." },
                A_module_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged: { code: 2433, category: ts.DiagnosticCategory.Error, key: "A module declaration cannot be in a different file from a class or function with which it is merged" },
                A_module_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged: { code: 2434, category: ts.DiagnosticCategory.Error, key: "A module declaration cannot be located prior to a class or function with which it is merged" },
                Ambient_external_modules_cannot_be_nested_in_other_modules: { code: 2435, category: ts.DiagnosticCategory.Error, key: "Ambient external modules cannot be nested in other modules." },
                Ambient_external_module_declaration_cannot_specify_relative_module_name: { code: 2436, category: ts.DiagnosticCategory.Error, key: "Ambient external module declaration cannot specify relative module name." },
                Module_0_is_hidden_by_a_local_declaration_with_the_same_name: { code: 2437, category: ts.DiagnosticCategory.Error, key: "Module '{0}' is hidden by a local declaration with the same name" },
                Import_name_cannot_be_0: { code: 2438, category: ts.DiagnosticCategory.Error, key: "Import name cannot be '{0}'" },
                Import_or_export_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name: { code: 2439, category: ts.DiagnosticCategory.Error, key: "Import or export declaration in an ambient external module declaration cannot reference external module through relative external module name." },
                Import_declaration_conflicts_with_local_declaration_of_0: { code: 2440, category: ts.DiagnosticCategory.Error, key: "Import declaration conflicts with local declaration of '{0}'" },
                Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module: { code: 2441, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier '{0}'. Compiler reserves name '{1}' in top level scope of an external module." },
                Types_have_separate_declarations_of_a_private_property_0: { code: 2442, category: ts.DiagnosticCategory.Error, key: "Types have separate declarations of a private property '{0}'." },
                Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2: { code: 2443, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is protected but type '{1}' is not a class derived from '{2}'." },
                Property_0_is_protected_in_type_1_but_public_in_type_2: { code: 2444, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is protected in type '{1}' but public in type '{2}'." },
                Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses: { code: 2445, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible within class '{1}' and its subclasses." },
                Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1: { code: 2446, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible through an instance of class '{1}'." },
                The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead: { code: 2447, category: ts.DiagnosticCategory.Error, key: "The '{0}' operator is not allowed for boolean types. Consider using '{1}' instead." },
                Block_scoped_variable_0_used_before_its_declaration: { code: 2448, category: ts.DiagnosticCategory.Error, key: "Block-scoped variable '{0}' used before its declaration." },
                The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant: { code: 2449, category: ts.DiagnosticCategory.Error, key: "The operand of an increment or decrement operator cannot be a constant." },
                Left_hand_side_of_assignment_expression_cannot_be_a_constant: { code: 2450, category: ts.DiagnosticCategory.Error, key: "Left-hand side of assignment expression cannot be a constant." },
                Cannot_redeclare_block_scoped_variable_0: { code: 2451, category: ts.DiagnosticCategory.Error, key: "Cannot redeclare block-scoped variable '{0}'." },
                An_enum_member_cannot_have_a_numeric_name: { code: 2452, category: ts.DiagnosticCategory.Error, key: "An enum member cannot have a numeric name." },
                The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly: { code: 2453, category: ts.DiagnosticCategory.Error, key: "The type argument for type parameter '{0}' cannot be inferred from the usage. Consider specifying the type arguments explicitly." },
                Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0: { code: 2455, category: ts.DiagnosticCategory.Error, key: "Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}'." },
                Type_alias_0_circularly_references_itself: { code: 2456, category: ts.DiagnosticCategory.Error, key: "Type alias '{0}' circularly references itself." },
                Type_alias_name_cannot_be_0: { code: 2457, category: ts.DiagnosticCategory.Error, key: "Type alias name cannot be '{0}'" },
                An_AMD_module_cannot_have_multiple_name_assignments: { code: 2458, category: ts.DiagnosticCategory.Error, key: "An AMD module cannot have multiple name assignments." },
                Type_0_has_no_property_1_and_no_string_index_signature: { code: 2459, category: ts.DiagnosticCategory.Error, key: "Type '{0}' has no property '{1}' and no string index signature." },
                Type_0_has_no_property_1: { code: 2460, category: ts.DiagnosticCategory.Error, key: "Type '{0}' has no property '{1}'." },
                Type_0_is_not_an_array_type: { code: 2461, category: ts.DiagnosticCategory.Error, key: "Type '{0}' is not an array type." },
                A_rest_element_must_be_last_in_an_array_destructuring_pattern: { code: 2462, category: ts.DiagnosticCategory.Error, key: "A rest element must be last in an array destructuring pattern" },
                A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature: { code: 2463, category: ts.DiagnosticCategory.Error, key: "A binding pattern parameter cannot be optional in an implementation signature." },
                A_computed_property_name_must_be_of_type_string_number_symbol_or_any: { code: 2464, category: ts.DiagnosticCategory.Error, key: "A computed property name must be of type 'string', 'number', 'symbol', or 'any'." },
                this_cannot_be_referenced_in_a_computed_property_name: { code: 2465, category: ts.DiagnosticCategory.Error, key: "'this' cannot be referenced in a computed property name." },
                super_cannot_be_referenced_in_a_computed_property_name: { code: 2466, category: ts.DiagnosticCategory.Error, key: "'super' cannot be referenced in a computed property name." },
                A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type: { code: 2467, category: ts.DiagnosticCategory.Error, key: "A computed property name cannot reference a type parameter from its containing type." },
                Cannot_find_global_value_0: { code: 2468, category: ts.DiagnosticCategory.Error, key: "Cannot find global value '{0}'." },
                The_0_operator_cannot_be_applied_to_type_symbol: { code: 2469, category: ts.DiagnosticCategory.Error, key: "The '{0}' operator cannot be applied to type 'symbol'." },
                Symbol_reference_does_not_refer_to_the_global_Symbol_constructor_object: { code: 2470, category: ts.DiagnosticCategory.Error, key: "'Symbol' reference does not refer to the global Symbol constructor object." },
                A_computed_property_name_of_the_form_0_must_be_of_type_symbol: { code: 2471, category: ts.DiagnosticCategory.Error, key: "A computed property name of the form '{0}' must be of type 'symbol'." },
                Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_6_and_higher: { code: 2472, category: ts.DiagnosticCategory.Error, key: "Spread operator in 'new' expressions is only available when targeting ECMAScript 6 and higher." },
                Enum_declarations_must_all_be_const_or_non_const: { code: 2473, category: ts.DiagnosticCategory.Error, key: "Enum declarations must all be const or non-const." },
                In_const_enum_declarations_member_initializer_must_be_constant_expression: { code: 2474, category: ts.DiagnosticCategory.Error, key: "In 'const' enum declarations member initializer must be constant expression." },
                const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment: { code: 2475, category: ts.DiagnosticCategory.Error, key: "'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment." },
                A_const_enum_member_can_only_be_accessed_using_a_string_literal: { code: 2476, category: ts.DiagnosticCategory.Error, key: "A const enum member can only be accessed using a string literal." },
                const_enum_member_initializer_was_evaluated_to_a_non_finite_value: { code: 2477, category: ts.DiagnosticCategory.Error, key: "'const' enum member initializer was evaluated to a non-finite value." },
                const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN: { code: 2478, category: ts.DiagnosticCategory.Error, key: "'const' enum member initializer was evaluated to disallowed value 'NaN'." },
                Property_0_does_not_exist_on_const_enum_1: { code: 2479, category: ts.DiagnosticCategory.Error, key: "Property '{0}' does not exist on 'const' enum '{1}'." },
                let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations: { code: 2480, category: ts.DiagnosticCategory.Error, key: "'let' is not allowed to be used as a name in 'let' or 'const' declarations." },
                Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1: { code: 2481, category: ts.DiagnosticCategory.Error, key: "Cannot initialize outer scoped variable '{0}' in the same scope as block scoped declaration '{1}'." },
                The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation: { code: 2483, category: ts.DiagnosticCategory.Error, key: "The left-hand side of a 'for...of' statement cannot use a type annotation." },
                Export_declaration_conflicts_with_exported_declaration_of_0: { code: 2484, category: ts.DiagnosticCategory.Error, key: "Export declaration conflicts with exported declaration of '{0}'" },
                The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant: { code: 2485, category: ts.DiagnosticCategory.Error, key: "The left-hand side of a 'for...of' statement cannot be a previously defined constant." },
                The_left_hand_side_of_a_for_in_statement_cannot_be_a_previously_defined_constant: { code: 2486, category: ts.DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot be a previously defined constant." },
                Invalid_left_hand_side_in_for_of_statement: { code: 2487, category: ts.DiagnosticCategory.Error, key: "Invalid left-hand side in 'for...of' statement." },
                Type_must_have_a_Symbol_iterator_method_that_returns_an_iterator: { code: 2488, category: ts.DiagnosticCategory.Error, key: "Type must have a '[Symbol.iterator]()' method that returns an iterator." },
                An_iterator_must_have_a_next_method: { code: 2489, category: ts.DiagnosticCategory.Error, key: "An iterator must have a 'next()' method." },
                The_type_returned_by_the_next_method_of_an_iterator_must_have_a_value_property: { code: 2490, category: ts.DiagnosticCategory.Error, key: "The type returned by the 'next()' method of an iterator must have a 'value' property." },
                The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern: { code: 2491, category: ts.DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot be a destructuring pattern." },
                Cannot_redeclare_identifier_0_in_catch_clause: { code: 2492, category: ts.DiagnosticCategory.Error, key: "Cannot redeclare identifier '{0}' in catch clause" },
                Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2: { code: 2493, category: ts.DiagnosticCategory.Error, key: "Tuple type '{0}' with length '{1}' cannot be assigned to tuple with length '{2}'." },
                Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher: { code: 2494, category: ts.DiagnosticCategory.Error, key: "Using a string in a 'for...of' statement is only supported in ECMAScript 5 and higher." },
                Type_0_is_not_an_array_type_or_a_string_type: { code: 2495, category: ts.DiagnosticCategory.Error, key: "Type '{0}' is not an array type or a string type." },
                The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression: { code: 2496, category: ts.DiagnosticCategory.Error, key: "The 'arguments' object cannot be referenced in an arrow function in ES3 and ES5. Consider using a standard function expression." },
                External_module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct: { code: 2497, category: ts.DiagnosticCategory.Error, key: "External module '{0}' resolves to a non-module entity and cannot be imported using this construct." },
                External_module_0_uses_export_and_cannot_be_used_with_export_Asterisk: { code: 2498, category: ts.DiagnosticCategory.Error, key: "External module '{0}' uses 'export =' and cannot be used with 'export *'." },
                An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments: { code: 2499, category: ts.DiagnosticCategory.Error, key: "An interface can only extend an identifier/qualified-name with optional type arguments." },
                A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments: { code: 2500, category: ts.DiagnosticCategory.Error, key: "A class can only implement an identifier/qualified-name with optional type arguments." },
                A_rest_element_cannot_contain_a_binding_pattern: { code: 2501, category: ts.DiagnosticCategory.Error, key: "A rest element cannot contain a binding pattern." },
                Import_declaration_0_is_using_private_name_1: { code: 4000, category: ts.DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
                Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
                Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." },
                Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4006, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'." },
                Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4008, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of call signature from exported interface has or is using private name '{1}'." },
                Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1: { code: 4010, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of public static method from exported class has or is using private name '{1}'." },
                Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1: { code: 4012, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of public method from exported class has or is using private name '{1}'." },
                Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1: { code: 4014, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of method from exported interface has or is using private name '{1}'." },
                Type_parameter_0_of_exported_function_has_or_is_using_private_name_1: { code: 4016, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of exported function has or is using private name '{1}'." },
                Implements_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 4019, category: ts.DiagnosticCategory.Error, key: "Implements clause of exported class '{0}' has or is using private name '{1}'." },
                Extends_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 4020, category: ts.DiagnosticCategory.Error, key: "Extends clause of exported class '{0}' has or is using private name '{1}'." },
                Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1: { code: 4022, category: ts.DiagnosticCategory.Error, key: "Extends clause of exported interface '{0}' has or is using private name '{1}'." },
                Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4023, category: ts.DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using name '{1}' from external module {2} but cannot be named." },
                Exported_variable_0_has_or_is_using_name_1_from_private_module_2: { code: 4024, category: ts.DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using name '{1}' from private module '{2}'." },
                Exported_variable_0_has_or_is_using_private_name_1: { code: 4025, category: ts.DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using private name '{1}'." },
                Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4026, category: ts.DiagnosticCategory.Error, key: "Public static property '{0}' of exported class has or is using name '{1}' from external module {2} but cannot be named." },
                Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4027, category: ts.DiagnosticCategory.Error, key: "Public static property '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
                Public_static_property_0_of_exported_class_has_or_is_using_private_name_1: { code: 4028, category: ts.DiagnosticCategory.Error, key: "Public static property '{0}' of exported class has or is using private name '{1}'." },
                Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4029, category: ts.DiagnosticCategory.Error, key: "Public property '{0}' of exported class has or is using name '{1}' from external module {2} but cannot be named." },
                Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4030, category: ts.DiagnosticCategory.Error, key: "Public property '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
                Public_property_0_of_exported_class_has_or_is_using_private_name_1: { code: 4031, category: ts.DiagnosticCategory.Error, key: "Public property '{0}' of exported class has or is using private name '{1}'." },
                Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4032, category: ts.DiagnosticCategory.Error, key: "Property '{0}' of exported interface has or is using name '{1}' from private module '{2}'." },
                Property_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4033, category: ts.DiagnosticCategory.Error, key: "Property '{0}' of exported interface has or is using private name '{1}'." },
                Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4034, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public static property setter from exported class has or is using name '{1}' from private module '{2}'." },
                Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1: { code: 4035, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public static property setter from exported class has or is using private name '{1}'." },
                Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4036, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public property setter from exported class has or is using name '{1}' from private module '{2}'." },
                Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1: { code: 4037, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public property setter from exported class has or is using private name '{1}'." },
                Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4038, category: ts.DiagnosticCategory.Error, key: "Return type of public static property getter from exported class has or is using name '{0}' from external module {1} but cannot be named." },
                Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4039, category: ts.DiagnosticCategory.Error, key: "Return type of public static property getter from exported class has or is using name '{0}' from private module '{1}'." },
                Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0: { code: 4040, category: ts.DiagnosticCategory.Error, key: "Return type of public static property getter from exported class has or is using private name '{0}'." },
                Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4041, category: ts.DiagnosticCategory.Error, key: "Return type of public property getter from exported class has or is using name '{0}' from external module {1} but cannot be named." },
                Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4042, category: ts.DiagnosticCategory.Error, key: "Return type of public property getter from exported class has or is using name '{0}' from private module '{1}'." },
                Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0: { code: 4043, category: ts.DiagnosticCategory.Error, key: "Return type of public property getter from exported class has or is using private name '{0}'." },
                Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4044, category: ts.DiagnosticCategory.Error, key: "Return type of constructor signature from exported interface has or is using name '{0}' from private module '{1}'." },
                Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0: { code: 4045, category: ts.DiagnosticCategory.Error, key: "Return type of constructor signature from exported interface has or is using private name '{0}'." },
                Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4046, category: ts.DiagnosticCategory.Error, key: "Return type of call signature from exported interface has or is using name '{0}' from private module '{1}'." },
                Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0: { code: 4047, category: ts.DiagnosticCategory.Error, key: "Return type of call signature from exported interface has or is using private name '{0}'." },
                Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4048, category: ts.DiagnosticCategory.Error, key: "Return type of index signature from exported interface has or is using name '{0}' from private module '{1}'." },
                Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0: { code: 4049, category: ts.DiagnosticCategory.Error, key: "Return type of index signature from exported interface has or is using private name '{0}'." },
                Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4050, category: ts.DiagnosticCategory.Error, key: "Return type of public static method from exported class has or is using name '{0}' from external module {1} but cannot be named." },
                Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4051, category: ts.DiagnosticCategory.Error, key: "Return type of public static method from exported class has or is using name '{0}' from private module '{1}'." },
                Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0: { code: 4052, category: ts.DiagnosticCategory.Error, key: "Return type of public static method from exported class has or is using private name '{0}'." },
                Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4053, category: ts.DiagnosticCategory.Error, key: "Return type of public method from exported class has or is using name '{0}' from external module {1} but cannot be named." },
                Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4054, category: ts.DiagnosticCategory.Error, key: "Return type of public method from exported class has or is using name '{0}' from private module '{1}'." },
                Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0: { code: 4055, category: ts.DiagnosticCategory.Error, key: "Return type of public method from exported class has or is using private name '{0}'." },
                Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4056, category: ts.DiagnosticCategory.Error, key: "Return type of method from exported interface has or is using name '{0}' from private module '{1}'." },
                Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0: { code: 4057, category: ts.DiagnosticCategory.Error, key: "Return type of method from exported interface has or is using private name '{0}'." },
                Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4058, category: ts.DiagnosticCategory.Error, key: "Return type of exported function has or is using name '{0}' from external module {1} but cannot be named." },
                Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1: { code: 4059, category: ts.DiagnosticCategory.Error, key: "Return type of exported function has or is using name '{0}' from private module '{1}'." },
                Return_type_of_exported_function_has_or_is_using_private_name_0: { code: 4060, category: ts.DiagnosticCategory.Error, key: "Return type of exported function has or is using private name '{0}'." },
                Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4061, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of constructor from exported class has or is using name '{1}' from external module {2} but cannot be named." },
                Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4062, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of constructor from exported class has or is using name '{1}' from private module '{2}'." },
                Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1: { code: 4063, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of constructor from exported class has or is using private name '{1}'." },
                Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4064, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of constructor signature from exported interface has or is using name '{1}' from private module '{2}'." },
                Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4065, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'." },
                Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4066, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of call signature from exported interface has or is using name '{1}' from private module '{2}'." },
                Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4067, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of call signature from exported interface has or is using private name '{1}'." },
                Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4068, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public static method from exported class has or is using name '{1}' from external module {2} but cannot be named." },
                Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4069, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public static method from exported class has or is using name '{1}' from private module '{2}'." },
                Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1: { code: 4070, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public static method from exported class has or is using private name '{1}'." },
                Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4071, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public method from exported class has or is using name '{1}' from external module {2} but cannot be named." },
                Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4072, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public method from exported class has or is using name '{1}' from private module '{2}'." },
                Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1: { code: 4073, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public method from exported class has or is using private name '{1}'." },
                Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4074, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of method from exported interface has or is using name '{1}' from private module '{2}'." },
                Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1: { code: 4075, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of method from exported interface has or is using private name '{1}'." },
                Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4076, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using name '{1}' from external module {2} but cannot be named." },
                Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2: { code: 4077, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using name '{1}' from private module '{2}'." },
                Parameter_0_of_exported_function_has_or_is_using_private_name_1: { code: 4078, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using private name '{1}'." },
                Exported_type_alias_0_has_or_is_using_private_name_1: { code: 4081, category: ts.DiagnosticCategory.Error, key: "Exported type alias '{0}' has or is using private name '{1}'." },
                Default_export_of_the_module_has_or_is_using_private_name_0: { code: 4082, category: ts.DiagnosticCategory.Error, key: "Default export of the module has or is using private name '{0}'." },
                Loop_contains_block_scoped_variable_0_referenced_by_a_function_in_the_loop_This_is_only_supported_in_ECMAScript_6_or_higher: { code: 4091, category: ts.DiagnosticCategory.Error, key: "Loop contains block-scoped variable '{0}' referenced by a function in the loop. This is only supported in ECMAScript 6 or higher." },
                The_current_host_does_not_support_the_0_option: { code: 5001, category: ts.DiagnosticCategory.Error, key: "The current host does not support the '{0}' option." },
                Cannot_find_the_common_subdirectory_path_for_the_input_files: { code: 5009, category: ts.DiagnosticCategory.Error, key: "Cannot find the common subdirectory path for the input files." },
                Cannot_read_file_0_Colon_1: { code: 5012, category: ts.DiagnosticCategory.Error, key: "Cannot read file '{0}': {1}" },
                Unsupported_file_encoding: { code: 5013, category: ts.DiagnosticCategory.Error, key: "Unsupported file encoding." },
                Unknown_compiler_option_0: { code: 5023, category: ts.DiagnosticCategory.Error, key: "Unknown compiler option '{0}'." },
                Compiler_option_0_requires_a_value_of_type_1: { code: 5024, category: ts.DiagnosticCategory.Error, key: "Compiler option '{0}' requires a value of type {1}." },
                Could_not_write_file_0_Colon_1: { code: 5033, category: ts.DiagnosticCategory.Error, key: "Could not write file '{0}': {1}" },
                Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option: { code: 5038, category: ts.DiagnosticCategory.Error, key: "Option 'mapRoot' cannot be specified without specifying 'sourcemap' option." },
                Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option: { code: 5039, category: ts.DiagnosticCategory.Error, key: "Option 'sourceRoot' cannot be specified without specifying 'sourcemap' option." },
                Option_noEmit_cannot_be_specified_with_option_out_or_outDir: { code: 5040, category: ts.DiagnosticCategory.Error, key: "Option 'noEmit' cannot be specified with option 'out' or 'outDir'." },
                Option_noEmit_cannot_be_specified_with_option_declaration: { code: 5041, category: ts.DiagnosticCategory.Error, key: "Option 'noEmit' cannot be specified with option 'declaration'." },
                Option_project_cannot_be_mixed_with_source_files_on_a_command_line: { code: 5042, category: ts.DiagnosticCategory.Error, key: "Option 'project' cannot be mixed with source files on a command line." },
                Option_sourceMap_cannot_be_specified_with_option_separateCompilation: { code: 5043, category: ts.DiagnosticCategory.Error, key: "Option 'sourceMap' cannot be specified with option 'separateCompilation'." },
                Option_declaration_cannot_be_specified_with_option_separateCompilation: { code: 5044, category: ts.DiagnosticCategory.Error, key: "Option 'declaration' cannot be specified with option 'separateCompilation'." },
                Option_noEmitOnError_cannot_be_specified_with_option_separateCompilation: { code: 5045, category: ts.DiagnosticCategory.Error, key: "Option 'noEmitOnError' cannot be specified with option 'separateCompilation'." },
                Option_out_cannot_be_specified_with_option_separateCompilation: { code: 5046, category: ts.DiagnosticCategory.Error, key: "Option 'out' cannot be specified with option 'separateCompilation'." },
                Option_separateCompilation_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher: { code: 5047, category: ts.DiagnosticCategory.Error, key: "Option 'separateCompilation' can only be used when either option'--module' is provided or option 'target' is 'ES6' or higher." },
                Concatenate_and_emit_output_to_single_file: { code: 6001, category: ts.DiagnosticCategory.Message, key: "Concatenate and emit output to single file." },
                Generates_corresponding_d_ts_file: { code: 6002, category: ts.DiagnosticCategory.Message, key: "Generates corresponding '.d.ts' file." },
                Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations: { code: 6003, category: ts.DiagnosticCategory.Message, key: "Specifies the location where debugger should locate map files instead of generated locations." },
                Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations: { code: 6004, category: ts.DiagnosticCategory.Message, key: "Specifies the location where debugger should locate TypeScript files instead of source locations." },
                Watch_input_files: { code: 6005, category: ts.DiagnosticCategory.Message, key: "Watch input files." },
                Redirect_output_structure_to_the_directory: { code: 6006, category: ts.DiagnosticCategory.Message, key: "Redirect output structure to the directory." },
                Do_not_erase_const_enum_declarations_in_generated_code: { code: 6007, category: ts.DiagnosticCategory.Message, key: "Do not erase const enum declarations in generated code." },
                Do_not_emit_outputs_if_any_type_checking_errors_were_reported: { code: 6008, category: ts.DiagnosticCategory.Message, key: "Do not emit outputs if any type checking errors were reported." },
                Do_not_emit_comments_to_output: { code: 6009, category: ts.DiagnosticCategory.Message, key: "Do not emit comments to output." },
                Do_not_emit_outputs: { code: 6010, category: ts.DiagnosticCategory.Message, key: "Do not emit outputs." },
                Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental: { code: 6015, category: ts.DiagnosticCategory.Message, key: "Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES6' (experimental)" },
                Specify_module_code_generation_Colon_commonjs_amd_or_umd: { code: 6016, category: ts.DiagnosticCategory.Message, key: "Specify module code generation: 'commonjs', 'amd', or 'umd'." },
                Print_this_message: { code: 6017, category: ts.DiagnosticCategory.Message, key: "Print this message." },
                Print_the_compiler_s_version: { code: 6019, category: ts.DiagnosticCategory.Message, key: "Print the compiler's version." },
                Compile_the_project_in_the_given_directory: { code: 6020, category: ts.DiagnosticCategory.Message, key: "Compile the project in the given directory." },
                Syntax_Colon_0: { code: 6023, category: ts.DiagnosticCategory.Message, key: "Syntax: {0}" },
                options: { code: 6024, category: ts.DiagnosticCategory.Message, key: "options" },
                file: { code: 6025, category: ts.DiagnosticCategory.Message, key: "file" },
                Examples_Colon_0: { code: 6026, category: ts.DiagnosticCategory.Message, key: "Examples: {0}" },
                Options_Colon: { code: 6027, category: ts.DiagnosticCategory.Message, key: "Options:" },
                Version_0: { code: 6029, category: ts.DiagnosticCategory.Message, key: "Version {0}" },
                Insert_command_line_options_and_files_from_a_file: { code: 6030, category: ts.DiagnosticCategory.Message, key: "Insert command line options and files from a file." },
                File_change_detected_Starting_incremental_compilation: { code: 6032, category: ts.DiagnosticCategory.Message, key: "File change detected. Starting incremental compilation..." },
                KIND: { code: 6034, category: ts.DiagnosticCategory.Message, key: "KIND" },
                FILE: { code: 6035, category: ts.DiagnosticCategory.Message, key: "FILE" },
                VERSION: { code: 6036, category: ts.DiagnosticCategory.Message, key: "VERSION" },
                LOCATION: { code: 6037, category: ts.DiagnosticCategory.Message, key: "LOCATION" },
                DIRECTORY: { code: 6038, category: ts.DiagnosticCategory.Message, key: "DIRECTORY" },
                Compilation_complete_Watching_for_file_changes: { code: 6042, category: ts.DiagnosticCategory.Message, key: "Compilation complete. Watching for file changes." },
                Generates_corresponding_map_file: { code: 6043, category: ts.DiagnosticCategory.Message, key: "Generates corresponding '.map' file." },
                Compiler_option_0_expects_an_argument: { code: 6044, category: ts.DiagnosticCategory.Error, key: "Compiler option '{0}' expects an argument." },
                Unterminated_quoted_string_in_response_file_0: { code: 6045, category: ts.DiagnosticCategory.Error, key: "Unterminated quoted string in response file '{0}'." },
                Argument_for_module_option_must_be_commonjs_amd_or_umd: { code: 6046, category: ts.DiagnosticCategory.Error, key: "Argument for '--module' option must be 'commonjs', 'amd', or 'umd'." },
                Argument_for_target_option_must_be_ES3_ES5_or_ES6: { code: 6047, category: ts.DiagnosticCategory.Error, key: "Argument for '--target' option must be 'ES3', 'ES5', or 'ES6'." },
                Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1: { code: 6048, category: ts.DiagnosticCategory.Error, key: "Locale must be of the form <language> or <language>-<territory>. For example '{0}' or '{1}'." },
                Unsupported_locale_0: { code: 6049, category: ts.DiagnosticCategory.Error, key: "Unsupported locale '{0}'." },
                Unable_to_open_file_0: { code: 6050, category: ts.DiagnosticCategory.Error, key: "Unable to open file '{0}'." },
                Corrupted_locale_file_0: { code: 6051, category: ts.DiagnosticCategory.Error, key: "Corrupted locale file {0}." },
                Raise_error_on_expressions_and_declarations_with_an_implied_any_type: { code: 6052, category: ts.DiagnosticCategory.Message, key: "Raise error on expressions and declarations with an implied 'any' type." },
                File_0_not_found: { code: 6053, category: ts.DiagnosticCategory.Error, key: "File '{0}' not found." },
                File_0_must_have_extension_ts_or_d_ts: { code: 6054, category: ts.DiagnosticCategory.Error, key: "File '{0}' must have extension '.ts' or '.d.ts'." },
                Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: ts.DiagnosticCategory.Message, key: "Suppress noImplicitAny errors for indexing objects lacking index signatures." },
                Do_not_emit_declarations_for_code_that_has_an_internal_annotation: { code: 6056, category: ts.DiagnosticCategory.Message, key: "Do not emit declarations for code that has an '@internal' annotation." },
                Preserve_new_lines_when_emitting_code: { code: 6057, category: ts.DiagnosticCategory.Message, key: "Preserve new-lines when emitting code." },
                Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir: { code: 6058, category: ts.DiagnosticCategory.Message, key: "Specifies the root directory of input files. Use to control the output directory structure with --outDir." },
                File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files: { code: 6059, category: ts.DiagnosticCategory.Error, key: "File '{0}' is not under 'rootDir' '{1}'. 'rootDir' is expected to contain all source files." },
                Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." },
                Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." },
                Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." },
                new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type: { code: 7009, category: ts.DiagnosticCategory.Error, key: "'new' expression, whose target lacks a construct signature, implicitly has an 'any' type." },
                _0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type: { code: 7010, category: ts.DiagnosticCategory.Error, key: "'{0}', which lacks return-type annotation, implicitly has an '{1}' return type." },
                Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type: { code: 7011, category: ts.DiagnosticCategory.Error, key: "Function expression, which lacks return-type annotation, implicitly has an '{0}' return type." },
                Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: { code: 7013, category: ts.DiagnosticCategory.Error, key: "Construct signature, which lacks return-type annotation, implicitly has an 'any' return type." },
                Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation: { code: 7016, category: ts.DiagnosticCategory.Error, key: "Property '{0}' implicitly has type 'any', because its 'set' accessor lacks a type annotation." },
                Index_signature_of_object_type_implicitly_has_an_any_type: { code: 7017, category: ts.DiagnosticCategory.Error, key: "Index signature of object type implicitly has an 'any' type." },
                Object_literal_s_property_0_implicitly_has_an_1_type: { code: 7018, category: ts.DiagnosticCategory.Error, key: "Object literal's property '{0}' implicitly has an '{1}' type." },
                Rest_parameter_0_implicitly_has_an_any_type: { code: 7019, category: ts.DiagnosticCategory.Error, key: "Rest parameter '{0}' implicitly has an 'any[]' type." },
                Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: { code: 7020, category: ts.DiagnosticCategory.Error, key: "Call signature, which lacks return-type annotation, implicitly has an 'any' return type." },
                _0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation: { code: 7021, category: ts.DiagnosticCategory.Error, key: "'{0}' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation." },
                _0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer: { code: 7022, category: ts.DiagnosticCategory.Error, key: "'{0}' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer." },
                _0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7023, category: ts.DiagnosticCategory.Error, key: "'{0}' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
                Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7024, category: ts.DiagnosticCategory.Error, key: "Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
                You_cannot_rename_this_element: { code: 8000, category: ts.DiagnosticCategory.Error, key: "You cannot rename this element." },
                You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library: { code: 8001, category: ts.DiagnosticCategory.Error, key: "You cannot rename elements that are defined in the standard TypeScript library." },
                import_can_only_be_used_in_a_ts_file: { code: 8002, category: ts.DiagnosticCategory.Error, key: "'import ... =' can only be used in a .ts file." },
                export_can_only_be_used_in_a_ts_file: { code: 8003, category: ts.DiagnosticCategory.Error, key: "'export=' can only be used in a .ts file." },
                type_parameter_declarations_can_only_be_used_in_a_ts_file: { code: 8004, category: ts.DiagnosticCategory.Error, key: "'type parameter declarations' can only be used in a .ts file." },
                implements_clauses_can_only_be_used_in_a_ts_file: { code: 8005, category: ts.DiagnosticCategory.Error, key: "'implements clauses' can only be used in a .ts file." },
                interface_declarations_can_only_be_used_in_a_ts_file: { code: 8006, category: ts.DiagnosticCategory.Error, key: "'interface declarations' can only be used in a .ts file." },
                module_declarations_can_only_be_used_in_a_ts_file: { code: 8007, category: ts.DiagnosticCategory.Error, key: "'module declarations' can only be used in a .ts file." },
                type_aliases_can_only_be_used_in_a_ts_file: { code: 8008, category: ts.DiagnosticCategory.Error, key: "'type aliases' can only be used in a .ts file." },
                _0_can_only_be_used_in_a_ts_file: { code: 8009, category: ts.DiagnosticCategory.Error, key: "'{0}' can only be used in a .ts file." },
                types_can_only_be_used_in_a_ts_file: { code: 8010, category: ts.DiagnosticCategory.Error, key: "'types' can only be used in a .ts file." },
                type_arguments_can_only_be_used_in_a_ts_file: { code: 8011, category: ts.DiagnosticCategory.Error, key: "'type arguments' can only be used in a .ts file." },
                parameter_modifiers_can_only_be_used_in_a_ts_file: { code: 8012, category: ts.DiagnosticCategory.Error, key: "'parameter modifiers' can only be used in a .ts file." },
                can_only_be_used_in_a_ts_file: { code: 8013, category: ts.DiagnosticCategory.Error, key: "'?' can only be used in a .ts file." },
                property_declarations_can_only_be_used_in_a_ts_file: { code: 8014, category: ts.DiagnosticCategory.Error, key: "'property declarations' can only be used in a .ts file." },
                enum_declarations_can_only_be_used_in_a_ts_file: { code: 8015, category: ts.DiagnosticCategory.Error, key: "'enum declarations' can only be used in a .ts file." },
                type_assertion_expressions_can_only_be_used_in_a_ts_file: { code: 8016, category: ts.DiagnosticCategory.Error, key: "'type assertion expressions' can only be used in a .ts file." },
                decorators_can_only_be_used_in_a_ts_file: { code: 8017, category: ts.DiagnosticCategory.Error, key: "'decorators' can only be used in a .ts file." },
                yield_expressions_are_not_currently_supported: { code: 9000, category: ts.DiagnosticCategory.Error, key: "'yield' expressions are not currently supported." },
                Generators_are_not_currently_supported: { code: 9001, category: ts.DiagnosticCategory.Error, key: "Generators are not currently supported." },
                Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_class_extends_clauses: { code: 9002, category: ts.DiagnosticCategory.Error, key: "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses." },
                class_expressions_are_not_currently_supported: { code: 9003, category: ts.DiagnosticCategory.Error, key: "'class' expressions are not currently supported." },
                class_declarations_are_only_supported_directly_inside_a_module_or_as_a_top_level_declaration: { code: 9004, category: ts.DiagnosticCategory.Error, key: "'class' declarations are only supported directly inside a module or as a top level declaration." }
            };
        })(ts || (ts = {}));
        /// <reference path="core.ts"/>
        /// <reference path="diagnosticInformationMap.generated.ts"/>
        var ts;
        (function (ts) {
            var textToToken = {
                "any": 112 /* AnyKeyword */,
                "as": 111 /* AsKeyword */,
                "boolean": 113 /* BooleanKeyword */,
                "break": 66 /* BreakKeyword */,
                "case": 67 /* CaseKeyword */,
                "catch": 68 /* CatchKeyword */,
                "class": 69 /* ClassKeyword */,
                "continue": 71 /* ContinueKeyword */,
                "const": 70 /* ConstKeyword */,
                "constructor": 114 /* ConstructorKeyword */,
                "debugger": 72 /* DebuggerKeyword */,
                "declare": 115 /* DeclareKeyword */,
                "default": 73 /* DefaultKeyword */,
                "delete": 74 /* DeleteKeyword */,
                "do": 75 /* DoKeyword */,
                "else": 76 /* ElseKeyword */,
                "enum": 77 /* EnumKeyword */,
                "export": 78 /* ExportKeyword */,
                "extends": 79 /* ExtendsKeyword */,
                "false": 80 /* FalseKeyword */,
                "finally": 81 /* FinallyKeyword */,
                "for": 82 /* ForKeyword */,
                "from": 124 /* FromKeyword */,
                "function": 83 /* FunctionKeyword */,
                "get": 116 /* GetKeyword */,
                "if": 84 /* IfKeyword */,
                "implements": 102 /* ImplementsKeyword */,
                "import": 85 /* ImportKeyword */,
                "in": 86 /* InKeyword */,
                "instanceof": 87 /* InstanceOfKeyword */,
                "interface": 103 /* InterfaceKeyword */,
                "let": 104 /* LetKeyword */,
                "module": 117 /* ModuleKeyword */,
                "new": 88 /* NewKeyword */,
                "null": 89 /* NullKeyword */,
                "number": 119 /* NumberKeyword */,
                "package": 105 /* PackageKeyword */,
                "private": 106 /* PrivateKeyword */,
                "protected": 107 /* ProtectedKeyword */,
                "public": 108 /* PublicKeyword */,
                "require": 118 /* RequireKeyword */,
                "return": 90 /* ReturnKeyword */,
                "set": 120 /* SetKeyword */,
                "static": 109 /* StaticKeyword */,
                "string": 121 /* StringKeyword */,
                "super": 91 /* SuperKeyword */,
                "switch": 92 /* SwitchKeyword */,
                "symbol": 122 /* SymbolKeyword */,
                "this": 93 /* ThisKeyword */,
                "throw": 94 /* ThrowKeyword */,
                "true": 95 /* TrueKeyword */,
                "try": 96 /* TryKeyword */,
                "type": 123 /* TypeKeyword */,
                "typeof": 97 /* TypeOfKeyword */,
                "var": 98 /* VarKeyword */,
                "void": 99 /* VoidKeyword */,
                "while": 100 /* WhileKeyword */,
                "with": 101 /* WithKeyword */,
                "yield": 110 /* YieldKeyword */,
                "of": 125 /* OfKeyword */,
                "{": 14 /* OpenBraceToken */,
                "}": 15 /* CloseBraceToken */,
                "(": 16 /* OpenParenToken */,
                ")": 17 /* CloseParenToken */,
                "[": 18 /* OpenBracketToken */,
                "]": 19 /* CloseBracketToken */,
                ".": 20 /* DotToken */,
                "...": 21 /* DotDotDotToken */,
                ";": 22 /* SemicolonToken */,
                ",": 23 /* CommaToken */,
                "<": 24 /* LessThanToken */,
                ">": 25 /* GreaterThanToken */,
                "<=": 26 /* LessThanEqualsToken */,
                ">=": 27 /* GreaterThanEqualsToken */,
                "==": 28 /* EqualsEqualsToken */,
                "!=": 29 /* ExclamationEqualsToken */,
                "===": 30 /* EqualsEqualsEqualsToken */,
                "!==": 31 /* ExclamationEqualsEqualsToken */,
                "=>": 32 /* EqualsGreaterThanToken */,
                "+": 33 /* PlusToken */,
                "-": 34 /* MinusToken */,
                "*": 35 /* AsteriskToken */,
                "/": 36 /* SlashToken */,
                "%": 37 /* PercentToken */,
                "++": 38 /* PlusPlusToken */,
                "--": 39 /* MinusMinusToken */,
                "<<": 40 /* LessThanLessThanToken */,
                ">>": 41 /* GreaterThanGreaterThanToken */,
                ">>>": 42 /* GreaterThanGreaterThanGreaterThanToken */,
                "&": 43 /* AmpersandToken */,
                "|": 44 /* BarToken */,
                "^": 45 /* CaretToken */,
                "!": 46 /* ExclamationToken */,
                "~": 47 /* TildeToken */,
                "&&": 48 /* AmpersandAmpersandToken */,
                "||": 49 /* BarBarToken */,
                "?": 50 /* QuestionToken */,
                ":": 51 /* ColonToken */,
                "=": 53 /* EqualsToken */,
                "+=": 54 /* PlusEqualsToken */,
                "-=": 55 /* MinusEqualsToken */,
                "*=": 56 /* AsteriskEqualsToken */,
                "/=": 57 /* SlashEqualsToken */,
                "%=": 58 /* PercentEqualsToken */,
                "<<=": 59 /* LessThanLessThanEqualsToken */,
                ">>=": 60 /* GreaterThanGreaterThanEqualsToken */,
                ">>>=": 61 /* GreaterThanGreaterThanGreaterThanEqualsToken */,
                "&=": 62 /* AmpersandEqualsToken */,
                "|=": 63 /* BarEqualsToken */,
                "^=": 64 /* CaretEqualsToken */,
                "@": 52 /* AtToken */
            };
            /*
                As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers
                IdentifierStart ::
                    Can contain Unicode 3.0.0  categories:
                    Uppercase letter (Lu),
                    Lowercase letter (Ll),
                    Titlecase letter (Lt),
                    Modifier letter (Lm),
                    Other letter (Lo), or
                    Letter number (Nl).
                IdentifierPart :: =
                    Can contain IdentifierStart + Unicode 3.0.0  categories:
                    Non-spacing mark (Mn),
                    Combining spacing mark (Mc),
                    Decimal number (Nd), or
                    Connector punctuation (Pc).
        
                Codepoint ranges for ES3 Identifiers are extracted from the Unicode 3.0.0 specification at:
                http://www.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.txt
            */
            var unicodeES3IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1610, 1649, 1747, 1749, 1749, 1765, 1766, 1786, 1788, 1808, 1808, 1810, 1836, 1920, 1957, 2309, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2784, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3294, 3294, 3296, 3297, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3424, 3425, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805, 3840, 3840, 3904, 3911, 3913, 3946, 3976, 3979, 4096, 4129, 4131, 4135, 4137, 4138, 4176, 4181, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6067, 6176, 6263, 6272, 6312, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8319, 8319, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12346, 12353, 12436, 12445, 12446, 12449, 12538, 12540, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65138, 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,];
            var unicodeES3IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 768, 846, 864, 866, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1155, 1158, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1441, 1443, 1465, 1467, 1469, 1471, 1471, 1473, 1474, 1476, 1476, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1621, 1632, 1641, 1648, 1747, 1749, 1756, 1759, 1768, 1770, 1773, 1776, 1788, 1808, 1836, 1840, 1866, 1920, 1968, 2305, 2307, 2309, 2361, 2364, 2381, 2384, 2388, 2392, 2403, 2406, 2415, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2492, 2494, 2500, 2503, 2504, 2507, 2509, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2562, 2562, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2649, 2652, 2654, 2654, 2662, 2676, 2689, 2691, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2784, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2876, 2883, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2913, 2918, 2927, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3031, 3031, 3047, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3134, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3168, 3169, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3262, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3297, 3302, 3311, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3390, 3395, 3398, 3400, 3402, 3405, 3415, 3415, 3424, 3425, 3430, 3439, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3946, 3953, 3972, 3974, 3979, 3984, 3991, 3993, 4028, 4038, 4038, 4096, 4129, 4131, 4135, 4137, 4138, 4140, 4146, 4150, 4153, 4160, 4169, 4176, 4185, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 4969, 4977, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6099, 6112, 6121, 6160, 6169, 6176, 6263, 6272, 6313, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8255, 8256, 8319, 8319, 8400, 8412, 8417, 8417, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12346, 12353, 12436, 12441, 12442, 12445, 12446, 12449, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65056, 65059, 65075, 65076, 65101, 65103, 65136, 65138, 65140, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65381, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,];
            /*
                As per ECMAScript Language Specification 5th Edition, Section 7.6: ISyntaxToken Names and Identifiers
                IdentifierStart ::
                    Can contain Unicode 6.2  categories:
                    Uppercase letter (Lu),
                    Lowercase letter (Ll),
                    Titlecase letter (Lt),
                    Modifier letter (Lm),
                    Other letter (Lo), or
                    Letter number (Nl).
                IdentifierPart ::
                    Can contain IdentifierStart + Unicode 6.2  categories:
                    Non-spacing mark (Mn),
                    Combining spacing mark (Mc),
                    Decimal number (Nd),
                    Connector punctuation (Pc),
                    <ZWNJ>, or
                    <ZWJ>.
        
                Codepoint ranges for ES5 Identifiers are extracted from the Unicode 6.2 specification at:
                http://www.unicode.org/Public/6.2.0/ucd/UnicodeData.txt
            */
            var unicodeES5IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2208, 2208, 2210, 2220, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516, 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409, 7413, 7414, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11502, 11506, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539, 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595, 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44002, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,];
            var unicodeES5IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 768, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1469, 1471, 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1520, 1522, 1552, 1562, 1568, 1641, 1646, 1747, 1749, 1756, 1759, 1768, 1770, 1788, 1791, 1791, 1808, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2048, 2093, 2112, 2139, 2208, 2208, 2210, 2220, 2276, 2302, 2304, 2403, 2406, 2415, 2417, 2423, 2425, 2431, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2787, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, 3161, 3168, 3171, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302, 3311, 3313, 3314, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3396, 3398, 3400, 3402, 3406, 3415, 3415, 3424, 3427, 3430, 3439, 3450, 3455, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3948, 3953, 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, 6103, 6108, 6109, 6112, 6121, 6155, 6157, 6160, 6169, 6176, 6263, 6272, 6314, 6320, 6389, 6400, 6428, 6432, 6443, 6448, 6459, 6470, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6617, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6912, 6987, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7376, 7378, 7380, 7414, 7424, 7654, 7676, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8204, 8205, 8255, 8256, 8276, 8276, 8305, 8305, 8319, 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 11823, 11823, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12442, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, 42623, 42647, 42655, 42737, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43047, 43072, 43123, 43136, 43204, 43216, 43225, 43232, 43255, 43259, 43259, 43264, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43520, 43574, 43584, 43597, 43600, 43609, 43616, 43638, 43642, 43643, 43648, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65062, 65075, 65076, 65101, 65103, 65136, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,];
            function lookupInUnicodeMap(code, map) {
                // Bail out quickly if it couldn't possibly be in the map.
                if (code < map[0]) {
                    return false;
                }
                // Perform binary search in one of the Unicode range maps
                var lo = 0;
                var hi = map.length;
                var mid;
                while (lo + 1 < hi) {
                    mid = lo + (hi - lo) / 2;
                    // mid has to be even to catch a range's beginning
                    mid -= mid % 2;
                    if (map[mid] <= code && code <= map[mid + 1]) {
                        return true;
                    }
                    if (code < map[mid]) {
                        hi = mid;
                    }
                    else {
                        lo = mid + 2;
                    }
                }
                return false;
            }
            /* @internal */ function isUnicodeIdentifierStart(code, languageVersion) {
                return languageVersion >= 1 /* ES5 */ ?
                    lookupInUnicodeMap(code, unicodeES5IdentifierStart) :
                    lookupInUnicodeMap(code, unicodeES3IdentifierStart);
            }
            ts.isUnicodeIdentifierStart = isUnicodeIdentifierStart;
            function isUnicodeIdentifierPart(code, languageVersion) {
                return languageVersion >= 1 /* ES5 */ ?
                    lookupInUnicodeMap(code, unicodeES5IdentifierPart) :
                    lookupInUnicodeMap(code, unicodeES3IdentifierPart);
            }
            function makeReverseMap(source) {
                var result = [];
                for (var name_2 in source) {
                    if (source.hasOwnProperty(name_2)) {
                        result[source[name_2]] = name_2;
                    }
                }
                return result;
            }
            var tokenStrings = makeReverseMap(textToToken);
            function tokenToString(t) {
                return tokenStrings[t];
            }
            ts.tokenToString = tokenToString;
            /* @internal */
            function stringToToken(s) {
                return textToToken[s];
            }
            ts.stringToToken = stringToToken;
            /* @internal */
            function computeLineStarts(text) {
                var result = new Array();
                var pos = 0;
                var lineStart = 0;
                while (pos < text.length) {
                    var ch = text.charCodeAt(pos++);
                    switch (ch) {
                        case 13 /* carriageReturn */:
                            if (text.charCodeAt(pos) === 10 /* lineFeed */) {
                                pos++;
                            }
                        case 10 /* lineFeed */:
                            result.push(lineStart);
                            lineStart = pos;
                            break;
                        default:
                            if (ch > 127 /* maxAsciiCharacter */ && isLineBreak(ch)) {
                                result.push(lineStart);
                                lineStart = pos;
                            }
                            break;
                    }
                }
                result.push(lineStart);
                return result;
            }
            ts.computeLineStarts = computeLineStarts;
            function getPositionOfLineAndCharacter(sourceFile, line, character) {
                return computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character);
            }
            ts.getPositionOfLineAndCharacter = getPositionOfLineAndCharacter;
            /* @internal */
            function computePositionOfLineAndCharacter(lineStarts, line, character) {
                ts.Debug.assert(line >= 0 && line < lineStarts.length);
                return lineStarts[line] + character;
            }
            ts.computePositionOfLineAndCharacter = computePositionOfLineAndCharacter;
            /* @internal */
            function getLineStarts(sourceFile) {
                return sourceFile.lineMap || (sourceFile.lineMap = computeLineStarts(sourceFile.text));
            }
            ts.getLineStarts = getLineStarts;
            /* @internal */
            function computeLineAndCharacterOfPosition(lineStarts, position) {
                var lineNumber = ts.binarySearch(lineStarts, position);
                if (lineNumber < 0) {
                    // If the actual position was not found, 
                    // the binary search returns the negative value of the next line start
                    // e.g. if the line starts at [5, 10, 23, 80] and the position requested was 20
                    // then the search will return -2
                    lineNumber = ~lineNumber - 1;
                }
                return {
                    line: lineNumber,
                    character: position - lineStarts[lineNumber]
                };
            }
            ts.computeLineAndCharacterOfPosition = computeLineAndCharacterOfPosition;
            function getLineAndCharacterOfPosition(sourceFile, position) {
                return computeLineAndCharacterOfPosition(getLineStarts(sourceFile), position);
            }
            ts.getLineAndCharacterOfPosition = getLineAndCharacterOfPosition;
            var hasOwnProperty = Object.prototype.hasOwnProperty;
            function isWhiteSpace(ch) {
                // Note: nextLine is in the Zs space, and should be considered to be a whitespace.
                // It is explicitly not a line-break as it isn't in the exact set specified by EcmaScript.
                return ch === 32 /* space */ ||
                    ch === 9 /* tab */ ||
                    ch === 11 /* verticalTab */ ||
                    ch === 12 /* formFeed */ ||
                    ch === 160 /* nonBreakingSpace */ ||
                    ch === 133 /* nextLine */ ||
                    ch === 5760 /* ogham */ ||
                    ch >= 8192 /* enQuad */ && ch <= 8203 /* zeroWidthSpace */ ||
                    ch === 8239 /* narrowNoBreakSpace */ ||
                    ch === 8287 /* mathematicalSpace */ ||
                    ch === 12288 /* ideographicSpace */ ||
                    ch === 65279 /* byteOrderMark */;
            }
            ts.isWhiteSpace = isWhiteSpace;
            function isLineBreak(ch) {
                // ES5 7.3:
                // The ECMAScript line terminator characters are listed in Table 3.
                //     Table 3: Line Terminator Characters
                //     Code Unit Value     Name                    Formal Name
                //     \u000A              Line Feed               <LF>
                //     \u000D              Carriage Return         <CR>
                //     \u2028              Line separator          <LS>
                //     \u2029              Paragraph separator     <PS>
                // Only the characters in Table 3 are treated as line terminators. Other new line or line 
                // breaking characters are treated as white space but not as line terminators. 
                return ch === 10 /* lineFeed */ ||
                    ch === 13 /* carriageReturn */ ||
                    ch === 8232 /* lineSeparator */ ||
                    ch === 8233 /* paragraphSeparator */;
            }
            ts.isLineBreak = isLineBreak;
            function isDigit(ch) {
                return ch >= 48 /* _0 */ && ch <= 57 /* _9 */;
            }
            /* @internal */
            function isOctalDigit(ch) {
                return ch >= 48 /* _0 */ && ch <= 55 /* _7 */;
            }
            ts.isOctalDigit = isOctalDigit;
            /* @internal */
            function skipTrivia(text, pos, stopAfterLineBreak) {
                while (true) {
                    var ch = text.charCodeAt(pos);
                    switch (ch) {
                        case 13 /* carriageReturn */:
                            if (text.charCodeAt(pos + 1) === 10 /* lineFeed */) {
                                pos++;
                            }
                        case 10 /* lineFeed */:
                            pos++;
                            if (stopAfterLineBreak) {
                                return pos;
                            }
                            continue;
                        case 9 /* tab */:
                        case 11 /* verticalTab */:
                        case 12 /* formFeed */:
                        case 32 /* space */:
                            pos++;
                            continue;
                        case 47 /* slash */:
                            if (text.charCodeAt(pos + 1) === 47 /* slash */) {
                                pos += 2;
                                while (pos < text.length) {
                                    if (isLineBreak(text.charCodeAt(pos))) {
                                        break;
                                    }
                                    pos++;
                                }
                                continue;
                            }
                            if (text.charCodeAt(pos + 1) === 42 /* asterisk */) {
                                pos += 2;
                                while (pos < text.length) {
                                    if (text.charCodeAt(pos) === 42 /* asterisk */ && text.charCodeAt(pos + 1) === 47 /* slash */) {
                                        pos += 2;
                                        break;
                                    }
                                    pos++;
                                }
                                continue;
                            }
                            break;
                        case 60 /* lessThan */:
                        case 61 /* equals */:
                        case 62 /* greaterThan */:
                            if (isConflictMarkerTrivia(text, pos)) {
                                pos = scanConflictMarkerTrivia(text, pos);
                                continue;
                            }
                            break;
                        default:
                            if (ch > 127 /* maxAsciiCharacter */ && (isWhiteSpace(ch) || isLineBreak(ch))) {
                                pos++;
                                continue;
                            }
                            break;
                    }
                    return pos;
                }
            }
            ts.skipTrivia = skipTrivia;
            // All conflict markers consist of the same character repeated seven times.  If it is 
            // a <<<<<<< or >>>>>>> marker then it is also followd by a space.
            var mergeConflictMarkerLength = "<<<<<<<".length;
            function isConflictMarkerTrivia(text, pos) {
                ts.Debug.assert(pos >= 0);
                // Conflict markers must be at the start of a line.
                if (pos === 0 || isLineBreak(text.charCodeAt(pos - 1))) {
                    var ch = text.charCodeAt(pos);
                    if ((pos + mergeConflictMarkerLength) < text.length) {
                        for (var i = 0, n = mergeConflictMarkerLength; i < n; i++) {
                            if (text.charCodeAt(pos + i) !== ch) {
                                return false;
                            }
                        }
                        return ch === 61 /* equals */ ||
                            text.charCodeAt(pos + mergeConflictMarkerLength) === 32 /* space */;
                    }
                }
                return false;
            }
            function scanConflictMarkerTrivia(text, pos, error) {
                if (error) {
                    error(ts.Diagnostics.Merge_conflict_marker_encountered, mergeConflictMarkerLength);
                }
                var ch = text.charCodeAt(pos);
                var len = text.length;
                if (ch === 60 /* lessThan */ || ch === 62 /* greaterThan */) {
                    while (pos < len && !isLineBreak(text.charCodeAt(pos))) {
                        pos++;
                    }
                }
                else {
                    ts.Debug.assert(ch === 61 /* equals */);
                    // Consume everything from the start of the mid-conlict marker to the start of the next
                    // end-conflict marker.
                    while (pos < len) {
                        var ch_1 = text.charCodeAt(pos);
                        if (ch_1 === 62 /* greaterThan */ && isConflictMarkerTrivia(text, pos)) {
                            break;
                        }
                        pos++;
                    }
                }
                return pos;
            }
            // Extract comments from the given source text starting at the given position. If trailing is 
            // false, whitespace is skipped until the first line break and comments between that location 
            // and the next token are returned.If trailing is true, comments occurring between the given 
            // position and the next line break are returned.The return value is an array containing a 
            // TextRange for each comment. Single-line comment ranges include the beginning '//' characters 
            // but not the ending line break. Multi - line comment ranges include the beginning '/* and 
            // ending '*/' characters.The return value is undefined if no comments were found.
            function getCommentRanges(text, pos, trailing) {
                var result;
                var collecting = trailing || pos === 0;
                while (true) {
                    var ch = text.charCodeAt(pos);
                    switch (ch) {
                        case 13 /* carriageReturn */:
                            if (text.charCodeAt(pos + 1) === 10 /* lineFeed */) {
                                pos++;
                            }
                        case 10 /* lineFeed */:
                            pos++;
                            if (trailing) {
                                return result;
                            }
                            collecting = true;
                            if (result && result.length) {
                                result[result.length - 1].hasTrailingNewLine = true;
                            }
                            continue;
                        case 9 /* tab */:
                        case 11 /* verticalTab */:
                        case 12 /* formFeed */:
                        case 32 /* space */:
                            pos++;
                            continue;
                        case 47 /* slash */:
                            var nextChar = text.charCodeAt(pos + 1);
                            var hasTrailingNewLine = false;
                            if (nextChar === 47 /* slash */ || nextChar === 42 /* asterisk */) {
                                var kind = nextChar === 47 /* slash */ ? 2 /* SingleLineCommentTrivia */ : 3 /* MultiLineCommentTrivia */;
                                var startPos = pos;
                                pos += 2;
                                if (nextChar === 47 /* slash */) {
                                    while (pos < text.length) {
                                        if (isLineBreak(text.charCodeAt(pos))) {
                                            hasTrailingNewLine = true;
                                            break;
                                        }
                                        pos++;
                                    }
                                }
                                else {
                                    while (pos < text.length) {
                                        if (text.charCodeAt(pos) === 42 /* asterisk */ && text.charCodeAt(pos + 1) === 47 /* slash */) {
                                            pos += 2;
                                            break;
                                        }
                                        pos++;
                                    }
                                }
                                if (collecting) {
                                    if (!result) {
                                        result = [];
                                    }
                                    result.push({ pos: startPos, end: pos, hasTrailingNewLine: hasTrailingNewLine, kind: kind });
                                }
                                continue;
                            }
                            break;
                        default:
                            if (ch > 127 /* maxAsciiCharacter */ && (isWhiteSpace(ch) || isLineBreak(ch))) {
                                if (result && result.length && isLineBreak(ch)) {
                                    result[result.length - 1].hasTrailingNewLine = true;
                                }
                                pos++;
                                continue;
                            }
                            break;
                    }
                    return result;
                }
            }
            function getLeadingCommentRanges(text, pos) {
                return getCommentRanges(text, pos, false);
            }
            ts.getLeadingCommentRanges = getLeadingCommentRanges;
            function getTrailingCommentRanges(text, pos) {
                return getCommentRanges(text, pos, true);
            }
            ts.getTrailingCommentRanges = getTrailingCommentRanges;
            function isIdentifierStart(ch, languageVersion) {
                return ch >= 65 /* A */ && ch <= 90 /* Z */ || ch >= 97 /* a */ && ch <= 122 /* z */ ||
                    ch === 36 /* $ */ || ch === 95 /* _ */ ||
                    ch > 127 /* maxAsciiCharacter */ && isUnicodeIdentifierStart(ch, languageVersion);
            }
            ts.isIdentifierStart = isIdentifierStart;
            function isIdentifierPart(ch, languageVersion) {
                return ch >= 65 /* A */ && ch <= 90 /* Z */ || ch >= 97 /* a */ && ch <= 122 /* z */ ||
                    ch >= 48 /* _0 */ && ch <= 57 /* _9 */ || ch === 36 /* $ */ || ch === 95 /* _ */ ||
                    ch > 127 /* maxAsciiCharacter */ && isUnicodeIdentifierPart(ch, languageVersion);
            }
            ts.isIdentifierPart = isIdentifierPart;
            // Creates a scanner over a (possibly unspecified) range of a piece of text.
            /* @internal */
            function createScanner(languageVersion, skipTrivia, text, onError, start, length) {
                var pos; // Current position (end position of text of current token)
                var end; // end of text
                var startPos; // Start position of whitespace before current token
                var tokenPos; // Start position of text of current token
                var token;
                var tokenValue;
                var precedingLineBreak;
                var hasExtendedUnicodeEscape;
                var tokenIsUnterminated;
                setText(text, start, length);
                return {
                    getStartPos: function () { return startPos; },
                    getTextPos: function () { return pos; },
                    getToken: function () { return token; },
                    getTokenPos: function () { return tokenPos; },
                    getTokenText: function () { return text.substring(tokenPos, pos); },
                    getTokenValue: function () { return tokenValue; },
                    hasExtendedUnicodeEscape: function () { return hasExtendedUnicodeEscape; },
                    hasPrecedingLineBreak: function () { return precedingLineBreak; },
                    isIdentifier: function () { return token === 65 /* Identifier */ || token > 101 /* LastReservedWord */; },
                    isReservedWord: function () { return token >= 66 /* FirstReservedWord */ && token <= 101 /* LastReservedWord */; },
                    isUnterminated: function () { return tokenIsUnterminated; },
                    reScanGreaterToken: reScanGreaterToken,
                    reScanSlashToken: reScanSlashToken,
                    reScanTemplateToken: reScanTemplateToken,
                    scan: scan,
                    setText: setText,
                    setScriptTarget: setScriptTarget,
                    setOnError: setOnError,
                    setTextPos: setTextPos,
                    tryScan: tryScan,
                    lookAhead: lookAhead
                };
                function error(message, length) {
                    if (onError) {
                        onError(message, length || 0);
                    }
                }
                function isIdentifierStart(ch) {
                    return ch >= 65 /* A */ && ch <= 90 /* Z */ || ch >= 97 /* a */ && ch <= 122 /* z */ ||
                        ch === 36 /* $ */ || ch === 95 /* _ */ ||
                        ch > 127 /* maxAsciiCharacter */ && isUnicodeIdentifierStart(ch, languageVersion);
                }
                function isIdentifierPart(ch) {
                    return ch >= 65 /* A */ && ch <= 90 /* Z */ || ch >= 97 /* a */ && ch <= 122 /* z */ ||
                        ch >= 48 /* _0 */ && ch <= 57 /* _9 */ || ch === 36 /* $ */ || ch === 95 /* _ */ ||
                        ch > 127 /* maxAsciiCharacter */ && isUnicodeIdentifierPart(ch, languageVersion);
                }
                function scanNumber() {
                    var start = pos;
                    while (isDigit(text.charCodeAt(pos)))
                        pos++;
                    if (text.charCodeAt(pos) === 46 /* dot */) {
                        pos++;
                        while (isDigit(text.charCodeAt(pos)))
                            pos++;
                    }
                    var end = pos;
                    if (text.charCodeAt(pos) === 69 /* E */ || text.charCodeAt(pos) === 101 /* e */) {
                        pos++;
                        if (text.charCodeAt(pos) === 43 /* plus */ || text.charCodeAt(pos) === 45 /* minus */)
                            pos++;
                        if (isDigit(text.charCodeAt(pos))) {
                            pos++;
                            while (isDigit(text.charCodeAt(pos)))
                                pos++;
                            end = pos;
                        }
                        else {
                            error(ts.Diagnostics.Digit_expected);
                        }
                    }
                    return +(text.substring(start, end));
                }
                function scanOctalDigits() {
                    var start = pos;
                    while (isOctalDigit(text.charCodeAt(pos))) {
                        pos++;
                    }
                    return +(text.substring(start, pos));
                }
                /**
                 * Scans the given number of hexadecimal digits in the text,
                 * returning -1 if the given number is unavailable.
                 */
                function scanExactNumberOfHexDigits(count) {
                    return scanHexDigits(count, false);
                }
                /**
                 * Scans as many hexadecimal digits as are available in the text,
                 * returning -1 if the given number of digits was unavailable.
                 */
                function scanMinimumNumberOfHexDigits(count) {
                    return scanHexDigits(count, true);
                }
                function scanHexDigits(minCount, scanAsManyAsPossible) {
                    var digits = 0;
                    var value = 0;
                    while (digits < minCount || scanAsManyAsPossible) {
                        var ch = text.charCodeAt(pos);
                        if (ch >= 48 /* _0 */ && ch <= 57 /* _9 */) {
                            value = value * 16 + ch - 48 /* _0 */;
                        }
                        else if (ch >= 65 /* A */ && ch <= 70 /* F */) {
                            value = value * 16 + ch - 65 /* A */ + 10;
                        }
                        else if (ch >= 97 /* a */ && ch <= 102 /* f */) {
                            value = value * 16 + ch - 97 /* a */ + 10;
                        }
                        else {
                            break;
                        }
                        pos++;
                        digits++;
                    }
                    if (digits < minCount) {
                        value = -1;
                    }
                    return value;
                }
                function scanString() {
                    var quote = text.charCodeAt(pos++);
                    var result = "";
                    var start = pos;
                    while (true) {
                        if (pos >= end) {
                            result += text.substring(start, pos);
                            tokenIsUnterminated = true;
                            error(ts.Diagnostics.Unterminated_string_literal);
                            break;
                        }
                        var ch = text.charCodeAt(pos);
                        if (ch === quote) {
                            result += text.substring(start, pos);
                            pos++;
                            break;
                        }
                        if (ch === 92 /* backslash */) {
                            result += text.substring(start, pos);
                            result += scanEscapeSequence();
                            start = pos;
                            continue;
                        }
                        if (isLineBreak(ch)) {
                            result += text.substring(start, pos);
                            tokenIsUnterminated = true;
                            error(ts.Diagnostics.Unterminated_string_literal);
                            break;
                        }
                        pos++;
                    }
                    return result;
                }
                /**
                 * Sets the current 'tokenValue' and returns a NoSubstitutionTemplateLiteral or
                 * a literal component of a TemplateExpression.
                 */
                function scanTemplateAndSetTokenValue() {
                    var startedWithBacktick = text.charCodeAt(pos) === 96 /* backtick */;
                    pos++;
                    var start = pos;
                    var contents = "";
                    var resultingToken;
                    while (true) {
                        if (pos >= end) {
                            contents += text.substring(start, pos);
                            tokenIsUnterminated = true;
                            error(ts.Diagnostics.Unterminated_template_literal);
                            resultingToken = startedWithBacktick ? 10 /* NoSubstitutionTemplateLiteral */ : 13 /* TemplateTail */;
                            break;
                        }
                        var currChar = text.charCodeAt(pos);
                        // '`'
                        if (currChar === 96 /* backtick */) {
                            contents += text.substring(start, pos);
                            pos++;
                            resultingToken = startedWithBacktick ? 10 /* NoSubstitutionTemplateLiteral */ : 13 /* TemplateTail */;
                            break;
                        }
                        // '${'
                        if (currChar === 36 /* $ */ && pos + 1 < end && text.charCodeAt(pos + 1) === 123 /* openBrace */) {
                            contents += text.substring(start, pos);
                            pos += 2;
                            resultingToken = startedWithBacktick ? 11 /* TemplateHead */ : 12 /* TemplateMiddle */;
                            break;
                        }
                        // Escape character
                        if (currChar === 92 /* backslash */) {
                            contents += text.substring(start, pos);
                            contents += scanEscapeSequence();
                            start = pos;
                            continue;
                        }
                        // Speculated ECMAScript 6 Spec 11.8.6.1:
                        // <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> for Template Values
                        if (currChar === 13 /* carriageReturn */) {
                            contents += text.substring(start, pos);
                            pos++;
                            if (pos < end && text.charCodeAt(pos) === 10 /* lineFeed */) {
                                pos++;
                            }
                            contents += "\n";
                            start = pos;
                            continue;
                        }
                        pos++;
                    }
                    ts.Debug.assert(resultingToken !== undefined);
                    tokenValue = contents;
                    return resultingToken;
                }
                function scanEscapeSequence() {
                    pos++;
                    if (pos >= end) {
                        error(ts.Diagnostics.Unexpected_end_of_text);
                        return "";
                    }
                    var ch = text.charCodeAt(pos++);
                    switch (ch) {
                        case 48 /* _0 */:
                            return "\0";
                        case 98 /* b */:
                            return "\b";
                        case 116 /* t */:
                            return "\t";
                        case 110 /* n */:
                            return "\n";
                        case 118 /* v */:
                            return "\v";
                        case 102 /* f */:
                            return "\f";
                        case 114 /* r */:
                            return "\r";
                        case 39 /* singleQuote */:
                            return "\'";
                        case 34 /* doubleQuote */:
                            return "\"";
                        case 117 /* u */:
                            // '\u{DDDDDDDD}'
                            if (pos < end && text.charCodeAt(pos) === 123 /* openBrace */) {
                                hasExtendedUnicodeEscape = true;
                                pos++;
                                return scanExtendedUnicodeEscape();
                            }
                            // '\uDDDD'
                            return scanHexadecimalEscape(4);
                        case 120 /* x */:
                            // '\xDD'
                            return scanHexadecimalEscape(2);
                        // when encountering a LineContinuation (i.e. a backslash and a line terminator sequence),
                        // the line terminator is interpreted to be "the empty code unit sequence".
                        case 13 /* carriageReturn */:
                            if (pos < end && text.charCodeAt(pos) === 10 /* lineFeed */) {
                                pos++;
                            }
                        // fall through
                        case 10 /* lineFeed */:
                        case 8232 /* lineSeparator */:
                        case 8233 /* paragraphSeparator */:
                            return "";
                        default:
                            return String.fromCharCode(ch);
                    }
                }
                function scanHexadecimalEscape(numDigits) {
                    var escapedValue = scanExactNumberOfHexDigits(numDigits);
                    if (escapedValue >= 0) {
                        return String.fromCharCode(escapedValue);
                    }
                    else {
                        error(ts.Diagnostics.Hexadecimal_digit_expected);
                        return "";
                    }
                }
                function scanExtendedUnicodeEscape() {
                    var escapedValue = scanMinimumNumberOfHexDigits(1);
                    var isInvalidExtendedEscape = false;
                    // Validate the value of the digit
                    if (escapedValue < 0) {
                        error(ts.Diagnostics.Hexadecimal_digit_expected);
                        isInvalidExtendedEscape = true;
                    }
                    else if (escapedValue > 0x10FFFF) {
                        error(ts.Diagnostics.An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive);
                        isInvalidExtendedEscape = true;
                    }
                    if (pos >= end) {
                        error(ts.Diagnostics.Unexpected_end_of_text);
                        isInvalidExtendedEscape = true;
                    }
                    else if (text.charCodeAt(pos) == 125 /* closeBrace */) {
                        // Only swallow the following character up if it's a '}'.
                        pos++;
                    }
                    else {
                        error(ts.Diagnostics.Unterminated_Unicode_escape_sequence);
                        isInvalidExtendedEscape = true;
                    }
                    if (isInvalidExtendedEscape) {
                        return "";
                    }
                    return utf16EncodeAsString(escapedValue);
                }
                // Derived from the 10.1.1 UTF16Encoding of the ES6 Spec.
                function utf16EncodeAsString(codePoint) {
                    ts.Debug.assert(0x0 <= codePoint && codePoint <= 0x10FFFF);
                    if (codePoint <= 65535) {
                        return String.fromCharCode(codePoint);
                    }
                    var codeUnit1 = Math.floor((codePoint - 65536) / 1024) + 0xD800;
                    var codeUnit2 = ((codePoint - 65536) % 1024) + 0xDC00;
                    return String.fromCharCode(codeUnit1, codeUnit2);
                }
                // Current character is known to be a backslash. Check for Unicode escape of the form '\uXXXX'
                // and return code point value if valid Unicode escape is found. Otherwise return -1.
                function peekUnicodeEscape() {
                    if (pos + 5 < end && text.charCodeAt(pos + 1) === 117 /* u */) {
                        var start_1 = pos;
                        pos += 2;
                        var value = scanExactNumberOfHexDigits(4);
                        pos = start_1;
                        return value;
                    }
                    return -1;
                }
                function scanIdentifierParts() {
                    var result = "";
                    var start = pos;
                    while (pos < end) {
                        var ch = text.charCodeAt(pos);
                        if (isIdentifierPart(ch)) {
                            pos++;
                        }
                        else if (ch === 92 /* backslash */) {
                            ch = peekUnicodeEscape();
                            if (!(ch >= 0 && isIdentifierPart(ch))) {
                                break;
                            }
                            result += text.substring(start, pos);
                            result += String.fromCharCode(ch);
                            // Valid Unicode escape is always six characters
                            pos += 6;
                            start = pos;
                        }
                        else {
                            break;
                        }
                    }
                    result += text.substring(start, pos);
                    return result;
                }
                function getIdentifierToken() {
                    // Reserved words are between 2 and 11 characters long and start with a lowercase letter
                    var len = tokenValue.length;
                    if (len >= 2 && len <= 11) {
                        var ch = tokenValue.charCodeAt(0);
                        if (ch >= 97 /* a */ && ch <= 122 /* z */ && hasOwnProperty.call(textToToken, tokenValue)) {
                            return token = textToToken[tokenValue];
                        }
                    }
                    return token = 65 /* Identifier */;
                }
                function scanBinaryOrOctalDigits(base) {
                    ts.Debug.assert(base !== 2 || base !== 8, "Expected either base 2 or base 8");
                    var value = 0;
                    // For counting number of digits; Valid binaryIntegerLiteral must have at least one binary digit following B or b.
                    // Similarly valid octalIntegerLiteral must have at least one octal digit following o or O.
                    var numberOfDigits = 0;
                    while (true) {
                        var ch = text.charCodeAt(pos);
                        var valueOfCh = ch - 48 /* _0 */;
                        if (!isDigit(ch) || valueOfCh >= base) {
                            break;
                        }
                        value = value * base + valueOfCh;
                        pos++;
                        numberOfDigits++;
                    }
                    // Invalid binaryIntegerLiteral or octalIntegerLiteral
                    if (numberOfDigits === 0) {
                        return -1;
                    }
                    return value;
                }
                function scan() {
                    startPos = pos;
                    hasExtendedUnicodeEscape = false;
                    precedingLineBreak = false;
                    tokenIsUnterminated = false;
                    while (true) {
                        tokenPos = pos;
                        if (pos >= end) {
                            return token = 1 /* EndOfFileToken */;
                        }
                        var ch = text.charCodeAt(pos);
                        switch (ch) {
                            case 10 /* lineFeed */:
                            case 13 /* carriageReturn */:
                                precedingLineBreak = true;
                                if (skipTrivia) {
                                    pos++;
                                    continue;
                                }
                                else {
                                    if (ch === 13 /* carriageReturn */ && pos + 1 < end && text.charCodeAt(pos + 1) === 10 /* lineFeed */) {
                                        // consume both CR and LF
                                        pos += 2;
                                    }
                                    else {
                                        pos++;
                                    }
                                    return token = 4 /* NewLineTrivia */;
                                }
                            case 9 /* tab */:
                            case 11 /* verticalTab */:
                            case 12 /* formFeed */:
                            case 32 /* space */:
                                if (skipTrivia) {
                                    pos++;
                                    continue;
                                }
                                else {
                                    while (pos < end && isWhiteSpace(text.charCodeAt(pos))) {
                                        pos++;
                                    }
                                    return token = 5 /* WhitespaceTrivia */;
                                }
                            case 33 /* exclamation */:
                                if (text.charCodeAt(pos + 1) === 61 /* equals */) {
                                    if (text.charCodeAt(pos + 2) === 61 /* equals */) {
                                        return pos += 3, token = 31 /* ExclamationEqualsEqualsToken */;
                                    }
                                    return pos += 2, token = 29 /* ExclamationEqualsToken */;
                                }
                                return pos++, token = 46 /* ExclamationToken */;
                            case 34 /* doubleQuote */:
                            case 39 /* singleQuote */:
                                tokenValue = scanString();
                                return token = 8 /* StringLiteral */;
                            case 96 /* backtick */:
                                return token = scanTemplateAndSetTokenValue();
                            case 37 /* percent */:
                                if (text.charCodeAt(pos + 1) === 61 /* equals */) {
                                    return pos += 2, token = 58 /* PercentEqualsToken */;
                                }
                                return pos++, token = 37 /* PercentToken */;
                            case 38 /* ampersand */:
                                if (text.charCodeAt(pos + 1) === 38 /* ampersand */) {
                                    return pos += 2, token = 48 /* AmpersandAmpersandToken */;
                                }
                                if (text.charCodeAt(pos + 1) === 61 /* equals */) {
                                    return pos += 2, token = 62 /* AmpersandEqualsToken */;
                                }
                                return pos++, token = 43 /* AmpersandToken */;
                            case 40 /* openParen */:
                                return pos++, token = 16 /* OpenParenToken */;
                            case 41 /* closeParen */:
                                return pos++, token = 17 /* CloseParenToken */;
                            case 42 /* asterisk */:
                                if (text.charCodeAt(pos + 1) === 61 /* equals */) {
                                    return pos += 2, token = 56 /* AsteriskEqualsToken */;
                                }
                                return pos++, token = 35 /* AsteriskToken */;
                            case 43 /* plus */:
                                if (text.charCodeAt(pos + 1) === 43 /* plus */) {
                                    return pos += 2, token = 38 /* PlusPlusToken */;
                                }
                                if (text.charCodeAt(pos + 1) === 61 /* equals */) {
                                    return pos += 2, token = 54 /* PlusEqualsToken */;
                                }
                                return pos++, token = 33 /* PlusToken */;
                            case 44 /* comma */:
                                return pos++, token = 23 /* CommaToken */;
                            case 45 /* minus */:
                                if (text.charCodeAt(pos + 1) === 45 /* minus */) {
                                    return pos += 2, token = 39 /* MinusMinusToken */;
                                }
                                if (text.charCodeAt(pos + 1) === 61 /* equals */) {
                                    return pos += 2, token = 55 /* MinusEqualsToken */;
                                }
                                return pos++, token = 34 /* MinusToken */;
                            case 46 /* dot */:
                                if (isDigit(text.charCodeAt(pos + 1))) {
                                    tokenValue = "" + scanNumber();
                                    return token = 7 /* NumericLiteral */;
                                }
                                if (text.charCodeAt(pos + 1) === 46 /* dot */ && text.charCodeAt(pos + 2) === 46 /* dot */) {
                                    return pos += 3, token = 21 /* DotDotDotToken */;
                                }
                                return pos++, token = 20 /* DotToken */;
                            case 47 /* slash */:
                                // Single-line comment
                                if (text.charCodeAt(pos + 1) === 47 /* slash */) {
                                    pos += 2;
                                    while (pos < end) {
                                        if (isLineBreak(text.charCodeAt(pos))) {
                                            break;
                                        }
                                        pos++;
                                    }
                                    if (skipTrivia) {
                                        continue;
                                    }
                                    else {
                                        return token = 2 /* SingleLineCommentTrivia */;
                                    }
                                }
                                // Multi-line comment
                                if (text.charCodeAt(pos + 1) === 42 /* asterisk */) {
                                    pos += 2;
                                    var commentClosed = false;
                                    while (pos < end) {
                                        var ch_2 = text.charCodeAt(pos);
                                        if (ch_2 === 42 /* asterisk */ && text.charCodeAt(pos + 1) === 47 /* slash */) {
                                            pos += 2;
                                            commentClosed = true;
                                            break;
                                        }
                                        if (isLineBreak(ch_2)) {
                                            precedingLineBreak = true;
                                        }
                                        pos++;
                                    }
                                    if (!commentClosed) {
                                        error(ts.Diagnostics.Asterisk_Slash_expected);
                                    }
                                    if (skipTrivia) {
                                        continue;
                                    }
                                    else {
                                        tokenIsUnterminated = !commentClosed;
                                        return token = 3 /* MultiLineCommentTrivia */;
                                    }
                                }
                                if (text.charCodeAt(pos + 1) === 61 /* equals */) {
                                    return pos += 2, token = 57 /* SlashEqualsToken */;
                                }
                                return pos++, token = 36 /* SlashToken */;
                            case 48 /* _0 */:
                                if (pos + 2 < end && (text.charCodeAt(pos + 1) === 88 /* X */ || text.charCodeAt(pos + 1) === 120 /* x */)) {
                                    pos += 2;
                                    var value = scanMinimumNumberOfHexDigits(1);
                                    if (value < 0) {
                                        error(ts.Diagnostics.Hexadecimal_digit_expected);
                                        value = 0;
                                    }
                                    tokenValue = "" + value;
                                    return token = 7 /* NumericLiteral */;
                                }
                                else if (pos + 2 < end && (text.charCodeAt(pos + 1) === 66 /* B */ || text.charCodeAt(pos + 1) === 98 /* b */)) {
                                    pos += 2;
                                    var value = scanBinaryOrOctalDigits(2);
                                    if (value < 0) {
                                        error(ts.Diagnostics.Binary_digit_expected);
                                        value = 0;
                                    }
                                    tokenValue = "" + value;
                                    return token = 7 /* NumericLiteral */;
                                }
                                else if (pos + 2 < end && (text.charCodeAt(pos + 1) === 79 /* O */ || text.charCodeAt(pos + 1) === 111 /* o */)) {
                                    pos += 2;
                                    var value = scanBinaryOrOctalDigits(8);
                                    if (value < 0) {
                                        error(ts.Diagnostics.Octal_digit_expected);
                                        value = 0;
                                    }
                                    tokenValue = "" + value;
                                    return token = 7 /* NumericLiteral */;
                                }
                                // Try to parse as an octal
                                if (pos + 1 < end && isOctalDigit(text.charCodeAt(pos + 1))) {
                                    tokenValue = "" + scanOctalDigits();
                                    return token = 7 /* NumericLiteral */;
                                }
                            // This fall-through is a deviation from the EcmaScript grammar. The grammar says that a leading zero
                            // can only be followed by an octal digit, a dot, or the end of the number literal. However, we are being
                            // permissive and allowing decimal digits of the form 08* and 09* (which many browsers also do).
                            case 49 /* _1 */:
                            case 50 /* _2 */:
                            case 51 /* _3 */:
                            case 52 /* _4 */:
                            case 53 /* _5 */:
                            case 54 /* _6 */:
                            case 55 /* _7 */:
                            case 56 /* _8 */:
                            case 57 /* _9 */:
                                tokenValue = "" + scanNumber();
                                return token = 7 /* NumericLiteral */;
                            case 58 /* colon */:
                                return pos++, token = 51 /* ColonToken */;
                            case 59 /* semicolon */:
                                return pos++, token = 22 /* SemicolonToken */;
                            case 60 /* lessThan */:
                                if (isConflictMarkerTrivia(text, pos)) {
                                    pos = scanConflictMarkerTrivia(text, pos, error);
                                    if (skipTrivia) {
                                        continue;
                                    }
                                    else {
                                        return token = 6 /* ConflictMarkerTrivia */;
                                    }
                                }
                                if (text.charCodeAt(pos + 1) === 60 /* lessThan */) {
                                    if (text.charCodeAt(pos + 2) === 61 /* equals */) {
                                        return pos += 3, token = 59 /* LessThanLessThanEqualsToken */;
                                    }
                                    return pos += 2, token = 40 /* LessThanLessThanToken */;
                                }
                                if (text.charCodeAt(pos + 1) === 61 /* equals */) {
                                    return pos += 2, token = 26 /* LessThanEqualsToken */;
                                }
                                return pos++, token = 24 /* LessThanToken */;
                            case 61 /* equals */:
                                if (isConflictMarkerTrivia(text, pos)) {
                                    pos = scanConflictMarkerTrivia(text, pos, error);
                                    if (skipTrivia) {
                                        continue;
                                    }
                                    else {
                                        return token = 6 /* ConflictMarkerTrivia */;
                                    }
                                }
                                if (text.charCodeAt(pos + 1) === 61 /* equals */) {
                                    if (text.charCodeAt(pos + 2) === 61 /* equals */) {
                                        return pos += 3, token = 30 /* EqualsEqualsEqualsToken */;
                                    }
                                    return pos += 2, token = 28 /* EqualsEqualsToken */;
                                }
                                if (text.charCodeAt(pos + 1) === 62 /* greaterThan */) {
                                    return pos += 2, token = 32 /* EqualsGreaterThanToken */;
                                }
                                return pos++, token = 53 /* EqualsToken */;
                            case 62 /* greaterThan */:
                                if (isConflictMarkerTrivia(text, pos)) {
                                    pos = scanConflictMarkerTrivia(text, pos, error);
                                    if (skipTrivia) {
                                        continue;
                                    }
                                    else {
                                        return token = 6 /* ConflictMarkerTrivia */;
                                    }
                                }
                                return pos++, token = 25 /* GreaterThanToken */;
                            case 63 /* question */:
                                return pos++, token = 50 /* QuestionToken */;
                            case 91 /* openBracket */:
                                return pos++, token = 18 /* OpenBracketToken */;
                            case 93 /* closeBracket */:
                                return pos++, token = 19 /* CloseBracketToken */;
                            case 94 /* caret */:
                                if (text.charCodeAt(pos + 1) === 61 /* equals */) {
                                    return pos += 2, token = 64 /* CaretEqualsToken */;
                                }
                                return pos++, token = 45 /* CaretToken */;
                            case 123 /* openBrace */:
                                return pos++, token = 14 /* OpenBraceToken */;
                            case 124 /* bar */:
                                if (text.charCodeAt(pos + 1) === 124 /* bar */) {
                                    return pos += 2, token = 49 /* BarBarToken */;
                                }
                                if (text.charCodeAt(pos + 1) === 61 /* equals */) {
                                    return pos += 2, token = 63 /* BarEqualsToken */;
                                }
                                return pos++, token = 44 /* BarToken */;
                            case 125 /* closeBrace */:
                                return pos++, token = 15 /* CloseBraceToken */;
                            case 126 /* tilde */:
                                return pos++, token = 47 /* TildeToken */;
                            case 64 /* at */:
                                return pos++, token = 52 /* AtToken */;
                            case 92 /* backslash */:
                                var cookedChar = peekUnicodeEscape();
                                if (cookedChar >= 0 && isIdentifierStart(cookedChar)) {
                                    pos += 6;
                                    tokenValue = String.fromCharCode(cookedChar) + scanIdentifierParts();
                                    return token = getIdentifierToken();
                                }
                                error(ts.Diagnostics.Invalid_character);
                                return pos++, token = 0 /* Unknown */;
                            default:
                                if (isIdentifierStart(ch)) {
                                    pos++;
                                    while (pos < end && isIdentifierPart(ch = text.charCodeAt(pos)))
                                        pos++;
                                    tokenValue = text.substring(tokenPos, pos);
                                    if (ch === 92 /* backslash */) {
                                        tokenValue += scanIdentifierParts();
                                    }
                                    return token = getIdentifierToken();
                                }
                                else if (isWhiteSpace(ch)) {
                                    pos++;
                                    continue;
                                }
                                else if (isLineBreak(ch)) {
                                    precedingLineBreak = true;
                                    pos++;
                                    continue;
                                }
                                error(ts.Diagnostics.Invalid_character);
                                return pos++, token = 0 /* Unknown */;
                        }
                    }
                }
                function reScanGreaterToken() {
                    if (token === 25 /* GreaterThanToken */) {
                        if (text.charCodeAt(pos) === 62 /* greaterThan */) {
                            if (text.charCodeAt(pos + 1) === 62 /* greaterThan */) {
                                if (text.charCodeAt(pos + 2) === 61 /* equals */) {
                                    return pos += 3, token = 61 /* GreaterThanGreaterThanGreaterThanEqualsToken */;
                                }
                                return pos += 2, token = 42 /* GreaterThanGreaterThanGreaterThanToken */;
                            }
                            if (text.charCodeAt(pos + 1) === 61 /* equals */) {
                                return pos += 2, token = 60 /* GreaterThanGreaterThanEqualsToken */;
                            }
                            return pos++, token = 41 /* GreaterThanGreaterThanToken */;
                        }
                        if (text.charCodeAt(pos) === 61 /* equals */) {
                            return pos++, token = 27 /* GreaterThanEqualsToken */;
                        }
                    }
                    return token;
                }
                function reScanSlashToken() {
                    if (token === 36 /* SlashToken */ || token === 57 /* SlashEqualsToken */) {
                        var p = tokenPos + 1;
                        var inEscape = false;
                        var inCharacterClass = false;
                        while (true) {
                            // If we reach the end of a file, or hit a newline, then this is an unterminated
                            // regex.  Report error and return what we have so far.
                            if (p >= end) {
                                tokenIsUnterminated = true;
                                error(ts.Diagnostics.Unterminated_regular_expression_literal);
                                break;
                            }
                            var ch = text.charCodeAt(p);
                            if (isLineBreak(ch)) {
                                tokenIsUnterminated = true;
                                error(ts.Diagnostics.Unterminated_regular_expression_literal);
                                break;
                            }
                            if (inEscape) {
                                // Parsing an escape character;
                                // reset the flag and just advance to the next char.
                                inEscape = false;
                            }
                            else if (ch === 47 /* slash */ && !inCharacterClass) {
                                // A slash within a character class is permissible,
                                // but in general it signals the end of the regexp literal.
                                p++;
                                break;
                            }
                            else if (ch === 91 /* openBracket */) {
                                inCharacterClass = true;
                            }
                            else if (ch === 92 /* backslash */) {
                                inEscape = true;
                            }
                            else if (ch === 93 /* closeBracket */) {
                                inCharacterClass = false;
                            }
                            p++;
                        }
                        while (p < end && isIdentifierPart(text.charCodeAt(p))) {
                            p++;
                        }
                        pos = p;
                        tokenValue = text.substring(tokenPos, pos);
                        token = 9 /* RegularExpressionLiteral */;
                    }
                    return token;
                }
                /**
                 * Unconditionally back up and scan a template expression portion.
                 */
                function reScanTemplateToken() {
                    ts.Debug.assert(token === 15 /* CloseBraceToken */, "'reScanTemplateToken' should only be called on a '}'");
                    pos = tokenPos;
                    return token = scanTemplateAndSetTokenValue();
                }
                function speculationHelper(callback, isLookahead) {
                    var savePos = pos;
                    var saveStartPos = startPos;
                    var saveTokenPos = tokenPos;
                    var saveToken = token;
                    var saveTokenValue = tokenValue;
                    var savePrecedingLineBreak = precedingLineBreak;
                    var result = callback();
                    // If our callback returned something 'falsy' or we're just looking ahead,
                    // then unconditionally restore us to where we were.
                    if (!result || isLookahead) {
                        pos = savePos;
                        startPos = saveStartPos;
                        tokenPos = saveTokenPos;
                        token = saveToken;
                        tokenValue = saveTokenValue;
                        precedingLineBreak = savePrecedingLineBreak;
                    }
                    return result;
                }
                function lookAhead(callback) {
                    return speculationHelper(callback, true);
                }
                function tryScan(callback) {
                    return speculationHelper(callback, false);
                }
                function setText(newText, start, length) {
                    text = newText || "";
                    end = length === undefined ? text.length : start + length;
                    setTextPos(start || 0);
                }
                function setOnError(errorCallback) {
                    onError = errorCallback;
                }
                function setScriptTarget(scriptTarget) {
                    languageVersion = scriptTarget;
                }
                function setTextPos(textPos) {
                    ts.Debug.assert(textPos >= 0);
                    pos = textPos;
                    startPos = textPos;
                    tokenPos = textPos;
                    token = 0 /* Unknown */;
                    precedingLineBreak = false;
                    tokenValue = undefined;
                    hasExtendedUnicodeEscape = false;
                    tokenIsUnterminated = false;
                }
            }
            ts.createScanner = createScanner;
        })(ts || (ts = {}));
        /// <reference path="parser.ts"/>
        /* @internal */
        var ts;
        (function (ts) {
            ts.bindTime = 0;
            (function (ModuleInstanceState) {
                ModuleInstanceState[ModuleInstanceState["NonInstantiated"] = 0] = "NonInstantiated";
                ModuleInstanceState[ModuleInstanceState["Instantiated"] = 1] = "Instantiated";
                ModuleInstanceState[ModuleInstanceState["ConstEnumOnly"] = 2] = "ConstEnumOnly";
            })(ts.ModuleInstanceState || (ts.ModuleInstanceState = {}));
            var ModuleInstanceState = ts.ModuleInstanceState;
            function getModuleInstanceState(node) {
                // A module is uninstantiated if it contains only 
                // 1. interface declarations, type alias declarations
                if (node.kind === 202 /* InterfaceDeclaration */ || node.kind === 203 /* TypeAliasDeclaration */) {
                    return 0 /* NonInstantiated */;
                }
                else if (ts.isConstEnumDeclaration(node)) {
                    return 2 /* ConstEnumOnly */;
                }
                else if ((node.kind === 209 /* ImportDeclaration */ || node.kind === 208 /* ImportEqualsDeclaration */) && !(node.flags & 1 /* Export */)) {
                    return 0 /* NonInstantiated */;
                }
                else if (node.kind === 206 /* ModuleBlock */) {
                    var state = 0 /* NonInstantiated */;
                    ts.forEachChild(node, function (n) {
                        switch (getModuleInstanceState(n)) {
                            case 0 /* NonInstantiated */:
                                // child is non-instantiated - continue searching
                                return false;
                            case 2 /* ConstEnumOnly */:
                                // child is const enum only - record state and continue searching
                                state = 2 /* ConstEnumOnly */;
                                return false;
                            case 1 /* Instantiated */:
                                // child is instantiated - record state and stop
                                state = 1 /* Instantiated */;
                                return true;
                        }
                    });
                    return state;
                }
                else if (node.kind === 205 /* ModuleDeclaration */) {
                    return getModuleInstanceState(node.body);
                }
                else {
                    return 1 /* Instantiated */;
                }
            }
            ts.getModuleInstanceState = getModuleInstanceState;
            function bindSourceFile(file) {
                var start = new Date().getTime();
                bindSourceFileWorker(file);
                ts.bindTime += new Date().getTime() - start;
            }
            ts.bindSourceFile = bindSourceFile;
            function bindSourceFileWorker(file) {
                var parent;
                var container;
                var blockScopeContainer;
                var lastContainer;
                var symbolCount = 0;
                var Symbol = ts.objectAllocator.getSymbolConstructor();
                if (!file.locals) {
                    file.locals = {};
                    container = file;
                    setBlockScopeContainer(file, false);
                    bind(file);
                    file.symbolCount = symbolCount;
                }
                function createSymbol(flags, name) {
                    symbolCount++;
                    return new Symbol(flags, name);
                }
                function setBlockScopeContainer(node, cleanLocals) {
                    blockScopeContainer = node;
                    if (cleanLocals) {
                        blockScopeContainer.locals = undefined;
                    }
                }
                function addDeclarationToSymbol(symbol, node, symbolKind) {
                    symbol.flags |= symbolKind;
                    if (!symbol.declarations)
                        symbol.declarations = [];
                    symbol.declarations.push(node);
                    if (symbolKind & 1952 /* HasExports */ && !symbol.exports)
                        symbol.exports = {};
                    if (symbolKind & 6240 /* HasMembers */ && !symbol.members)
                        symbol.members = {};
                    node.symbol = symbol;
                    if (symbolKind & 107455 /* Value */ && !symbol.valueDeclaration)
                        symbol.valueDeclaration = node;
                }
                // Should not be called on a declaration with a computed property name,
                // unless it is a well known Symbol.
                function getDeclarationName(node) {
                    if (node.name) {
                        if (node.kind === 205 /* ModuleDeclaration */ && node.name.kind === 8 /* StringLiteral */) {
                            return '"' + node.name.text + '"';
                        }
                        if (node.name.kind === 127 /* ComputedPropertyName */) {
                            var nameExpression = node.name.expression;
                            ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression));
                            return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text);
                        }
                        return node.name.text;
                    }
                    switch (node.kind) {
                        case 143 /* ConstructorType */:
                        case 135 /* Constructor */:
                            return "__constructor";
                        case 142 /* FunctionType */:
                        case 138 /* CallSignature */:
                            return "__call";
                        case 139 /* ConstructSignature */:
                            return "__new";
                        case 140 /* IndexSignature */:
                            return "__index";
                        case 215 /* ExportDeclaration */:
                            return "__export";
                        case 214 /* ExportAssignment */:
                            return node.isExportEquals ? "export=" : "default";
                        case 200 /* FunctionDeclaration */:
                        case 201 /* ClassDeclaration */:
                            return node.flags & 256 /* Default */ ? "default" : undefined;
                    }
                }
                function getDisplayName(node) {
                    return node.name ? ts.declarationNameToString(node.name) : getDeclarationName(node);
                }
                function declareSymbol(symbols, parent, node, includes, excludes) {
                    ts.Debug.assert(!ts.hasDynamicName(node));
                    // The exported symbol for an export default function/class node is always named "default"
                    var name = node.flags & 256 /* Default */ && parent ? "default" : getDeclarationName(node);
                    var symbol;
                    if (name !== undefined) {
                        symbol = ts.hasProperty(symbols, name) ? symbols[name] : (symbols[name] = createSymbol(0, name));
                        if (symbol.flags & excludes) {
                            if (node.name) {
                                node.name.parent = node;
                            }
                            // Report errors every position with duplicate declaration
                            // Report errors on previous encountered declarations
                            var message = symbol.flags & 2 /* BlockScopedVariable */
                                ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0
                                : ts.Diagnostics.Duplicate_identifier_0;
                            ts.forEach(symbol.declarations, function (declaration) {
                                file.bindDiagnostics.push(ts.createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
                            });
                            file.bindDiagnostics.push(ts.createDiagnosticForNode(node.name || node, message, getDisplayName(node)));
                            symbol = createSymbol(0, name);
                        }
                    }
                    else {
                        symbol = createSymbol(0, "__missing");
                    }
                    addDeclarationToSymbol(symbol, node, includes);
                    symbol.parent = parent;
                    if ((node.kind === 201 /* ClassDeclaration */ || node.kind === 174 /* ClassExpression */) && symbol.exports) {
                        // TypeScript 1.0 spec (April 2014): 8.4
                        // Every class automatically contains a static property member named 'prototype', 
                        // the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter.
                        // It is an error to explicitly declare a static property member with the name 'prototype'.
                        var prototypeSymbol = createSymbol(4 /* Property */ | 134217728 /* Prototype */, "prototype");
                        if (ts.hasProperty(symbol.exports, prototypeSymbol.name)) {
                            if (node.name) {
                                node.name.parent = node;
                            }
                            file.bindDiagnostics.push(ts.createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0], ts.Diagnostics.Duplicate_identifier_0, prototypeSymbol.name));
                        }
                        symbol.exports[prototypeSymbol.name] = prototypeSymbol;
                        prototypeSymbol.parent = symbol;
                    }
                    return symbol;
                }
                function declareModuleMember(node, symbolKind, symbolExcludes) {
                    var hasExportModifier = ts.getCombinedNodeFlags(node) & 1 /* Export */;
                    if (symbolKind & 8388608 /* Alias */) {
                        if (node.kind === 217 /* ExportSpecifier */ || (node.kind === 208 /* ImportEqualsDeclaration */ && hasExportModifier)) {
                            declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
                        }
                        else {
                            declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
                        }
                    }
                    else {
                        // Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue,
                        // ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set
                        // on it. There are 2 main reasons:
                        //
                        //   1. We treat locals and exports of the same name as mutually exclusive within a container. 
                        //      That means the binder will issue a Duplicate Identifier error if you mix locals and exports
                        //      with the same name in the same container.
                        //      TODO: Make this a more specific error and decouple it from the exclusion logic.
                        //   2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol,
                        //      but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way
                        //      when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope.
                        if (hasExportModifier || container.flags & 32768 /* ExportContext */) {
                            var exportKind = (symbolKind & 107455 /* Value */ ? 1048576 /* ExportValue */ : 0) |
                                (symbolKind & 793056 /* Type */ ? 2097152 /* ExportType */ : 0) |
                                (symbolKind & 1536 /* Namespace */ ? 4194304 /* ExportNamespace */ : 0);
                            var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes);
                            local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
                            node.localSymbol = local;
                        }
                        else {
                            declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
                        }
                    }
                }
                // All container nodes are kept on a linked list in declaration order. This list is used by the getLocalNameOfContainer function
                // in the type checker to validate that the local name used for a container is unique.
                function bindChildren(node, symbolKind, isBlockScopeContainer) {
                    if (symbolKind & 255504 /* HasLocals */) {
                        node.locals = {};
                    }
                    var saveParent = parent;
                    var saveContainer = container;
                    var savedBlockScopeContainer = blockScopeContainer;
                    parent = node;
                    if (symbolKind & 262128 /* IsContainer */) {
                        container = node;
                        addToContainerChain(container);
                    }
                    if (isBlockScopeContainer) {
                        // in incremental scenarios we might reuse nodes that already have locals being allocated
                        // during the bind step these locals should be dropped to prevent using stale data.
                        // locals should always be dropped unless they were previously initialized by the binder
                        // these cases are:
                        // - node has locals (symbolKind & HasLocals) !== 0
                        // - node is a source file
                        setBlockScopeContainer(node, (symbolKind & 255504 /* HasLocals */) === 0 && node.kind !== 227 /* SourceFile */);
                    }
                    ts.forEachChild(node, bind);
                    container = saveContainer;
                    parent = saveParent;
                    blockScopeContainer = savedBlockScopeContainer;
                }
                function addToContainerChain(node) {
                    if (lastContainer) {
                        lastContainer.nextContainer = node;
                    }
                    lastContainer = node;
                }
                function bindDeclaration(node, symbolKind, symbolExcludes, isBlockScopeContainer) {
                    switch (container.kind) {
                        case 205 /* ModuleDeclaration */:
                            declareModuleMember(node, symbolKind, symbolExcludes);
                            break;
                        case 227 /* SourceFile */:
                            if (ts.isExternalModule(container)) {
                                declareModuleMember(node, symbolKind, symbolExcludes);
                                break;
                            }
                        case 142 /* FunctionType */:
                        case 143 /* ConstructorType */:
                        case 138 /* CallSignature */:
                        case 139 /* ConstructSignature */:
                        case 140 /* IndexSignature */:
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                        case 135 /* Constructor */:
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                        case 200 /* FunctionDeclaration */:
                        case 162 /* FunctionExpression */:
                        case 163 /* ArrowFunction */:
                            declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
                            break;
                        case 174 /* ClassExpression */:
                        case 201 /* ClassDeclaration */:
                            if (node.flags & 128 /* Static */) {
                                declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
                                break;
                            }
                        case 145 /* TypeLiteral */:
                        case 154 /* ObjectLiteralExpression */:
                        case 202 /* InterfaceDeclaration */:
                            declareSymbol(container.symbol.members, container.symbol, node, symbolKind, symbolExcludes);
                            break;
                        case 204 /* EnumDeclaration */:
                            declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
                            break;
                    }
                    bindChildren(node, symbolKind, isBlockScopeContainer);
                }
                function isAmbientContext(node) {
                    while (node) {
                        if (node.flags & 2 /* Ambient */)
                            return true;
                        node = node.parent;
                    }
                    return false;
                }
                function hasExportDeclarations(node) {
                    var body = node.kind === 227 /* SourceFile */ ? node : node.body;
                    if (body.kind === 227 /* SourceFile */ || body.kind === 206 /* ModuleBlock */) {
                        for (var _i = 0, _a = body.statements; _i < _a.length; _i++) {
                            var stat = _a[_i];
                            if (stat.kind === 215 /* ExportDeclaration */ || stat.kind === 214 /* ExportAssignment */) {
                                return true;
                            }
                        }
                    }
                    return false;
                }
                function setExportContextFlag(node) {
                    // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular
                    // declarations with export modifiers) is an export context in which declarations are implicitly exported.
                    if (isAmbientContext(node) && !hasExportDeclarations(node)) {
                        node.flags |= 32768 /* ExportContext */;
                    }
                    else {
                        node.flags &= ~32768 /* ExportContext */;
                    }
                }
                function bindModuleDeclaration(node) {
                    setExportContextFlag(node);
                    if (node.name.kind === 8 /* StringLiteral */) {
                        bindDeclaration(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */, true);
                    }
                    else {
                        var state = getModuleInstanceState(node);
                        if (state === 0 /* NonInstantiated */) {
                            bindDeclaration(node, 1024 /* NamespaceModule */, 0 /* NamespaceModuleExcludes */, true);
                        }
                        else {
                            bindDeclaration(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */, true);
                            var currentModuleIsConstEnumOnly = state === 2 /* ConstEnumOnly */;
                            if (node.symbol.constEnumOnlyModule === undefined) {
                                // non-merged case - use the current state
                                node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly;
                            }
                            else {
                                // merged case: module is const enum only if all its pieces are non-instantiated or const enum
                                node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly;
                            }
                        }
                    }
                }
                function bindFunctionOrConstructorType(node) {
                    // For a given function symbol "<...>(...) => T" we want to generate a symbol identical
                    // to the one we would get for: { <...>(...): T }
                    //
                    // We do that by making an anonymous type literal symbol, and then setting the function 
                    // symbol as its sole member. To the rest of the system, this symbol will be  indistinguishable 
                    // from an actual type literal symbol you would have gotten had you used the long form.
                    var symbol = createSymbol(131072 /* Signature */, getDeclarationName(node));
                    addDeclarationToSymbol(symbol, node, 131072 /* Signature */);
                    bindChildren(node, 131072 /* Signature */, false);
                    var typeLiteralSymbol = createSymbol(2048 /* TypeLiteral */, "__type");
                    addDeclarationToSymbol(typeLiteralSymbol, node, 2048 /* TypeLiteral */);
                    typeLiteralSymbol.members = {};
                    typeLiteralSymbol.members[node.kind === 142 /* FunctionType */ ? "__call" : "__new"] = symbol;
                }
                function bindAnonymousDeclaration(node, symbolKind, name, isBlockScopeContainer) {
                    var symbol = createSymbol(symbolKind, name);
                    addDeclarationToSymbol(symbol, node, symbolKind);
                    bindChildren(node, symbolKind, isBlockScopeContainer);
                }
                function bindCatchVariableDeclaration(node) {
                    bindChildren(node, 0, true);
                }
                function bindBlockScopedDeclaration(node, symbolKind, symbolExcludes) {
                    switch (blockScopeContainer.kind) {
                        case 205 /* ModuleDeclaration */:
                            declareModuleMember(node, symbolKind, symbolExcludes);
                            break;
                        case 227 /* SourceFile */:
                            if (ts.isExternalModule(container)) {
                                declareModuleMember(node, symbolKind, symbolExcludes);
                                break;
                            }
                        // fall through.
                        default:
                            if (!blockScopeContainer.locals) {
                                blockScopeContainer.locals = {};
                                addToContainerChain(blockScopeContainer);
                            }
                            declareSymbol(blockScopeContainer.locals, undefined, node, symbolKind, symbolExcludes);
                    }
                    bindChildren(node, symbolKind, false);
                }
                function bindBlockScopedVariableDeclaration(node) {
                    bindBlockScopedDeclaration(node, 2 /* BlockScopedVariable */, 107455 /* BlockScopedVariableExcludes */);
                }
                function getDestructuringParameterName(node) {
                    return "__" + ts.indexOf(node.parent.parameters, node);
                }
                function bind(node) {
                    node.parent = parent;
                    switch (node.kind) {
                        case 128 /* TypeParameter */:
                            bindDeclaration(node, 262144 /* TypeParameter */, 530912 /* TypeParameterExcludes */, false);
                            break;
                        case 129 /* Parameter */:
                            bindParameter(node);
                            break;
                        case 198 /* VariableDeclaration */:
                        case 152 /* BindingElement */:
                            if (ts.isBindingPattern(node.name)) {
                                bindChildren(node, 0, false);
                            }
                            else if (ts.isBlockOrCatchScoped(node)) {
                                bindBlockScopedVariableDeclaration(node);
                            }
                            else {
                                bindDeclaration(node, 1 /* FunctionScopedVariable */, 107454 /* FunctionScopedVariableExcludes */, false);
                            }
                            break;
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                            bindPropertyOrMethodOrAccessor(node, 4 /* Property */ | (node.questionToken ? 536870912 /* Optional */ : 0), 107455 /* PropertyExcludes */, false);
                            break;
                        case 224 /* PropertyAssignment */:
                        case 225 /* ShorthandPropertyAssignment */:
                            bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 107455 /* PropertyExcludes */, false);
                            break;
                        case 226 /* EnumMember */:
                            bindPropertyOrMethodOrAccessor(node, 8 /* EnumMember */, 107455 /* EnumMemberExcludes */, false);
                            break;
                        case 138 /* CallSignature */:
                        case 139 /* ConstructSignature */:
                        case 140 /* IndexSignature */:
                            bindDeclaration(node, 131072 /* Signature */, 0, false);
                            break;
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                            // If this is an ObjectLiteralExpression method, then it sits in the same space
                            // as other properties in the object literal.  So we use SymbolFlags.PropertyExcludes
                            // so that it will conflict with any other object literal members with the same
                            // name.
                            bindPropertyOrMethodOrAccessor(node, 8192 /* Method */ | (node.questionToken ? 536870912 /* Optional */ : 0), ts.isObjectLiteralMethod(node) ? 107455 /* PropertyExcludes */ : 99263 /* MethodExcludes */, true);
                            break;
                        case 200 /* FunctionDeclaration */:
                            bindDeclaration(node, 16 /* Function */, 106927 /* FunctionExcludes */, true);
                            break;
                        case 135 /* Constructor */:
                            bindDeclaration(node, 16384 /* Constructor */, 0, true);
                            break;
                        case 136 /* GetAccessor */:
                            bindPropertyOrMethodOrAccessor(node, 32768 /* GetAccessor */, 41919 /* GetAccessorExcludes */, true);
                            break;
                        case 137 /* SetAccessor */:
                            bindPropertyOrMethodOrAccessor(node, 65536 /* SetAccessor */, 74687 /* SetAccessorExcludes */, true);
                            break;
                        case 142 /* FunctionType */:
                        case 143 /* ConstructorType */:
                            bindFunctionOrConstructorType(node);
                            break;
                        case 145 /* TypeLiteral */:
                            bindAnonymousDeclaration(node, 2048 /* TypeLiteral */, "__type", false);
                            break;
                        case 154 /* ObjectLiteralExpression */:
                            bindAnonymousDeclaration(node, 4096 /* ObjectLiteral */, "__object", false);
                            break;
                        case 162 /* FunctionExpression */:
                        case 163 /* ArrowFunction */:
                            bindAnonymousDeclaration(node, 16 /* Function */, "__function", true);
                            break;
                        case 174 /* ClassExpression */:
                            bindAnonymousDeclaration(node, 32 /* Class */, "__class", false);
                            break;
                        case 223 /* CatchClause */:
                            bindCatchVariableDeclaration(node);
                            break;
                        case 201 /* ClassDeclaration */:
                            bindBlockScopedDeclaration(node, 32 /* Class */, 899583 /* ClassExcludes */);
                            break;
                        case 202 /* InterfaceDeclaration */:
                            bindDeclaration(node, 64 /* Interface */, 792992 /* InterfaceExcludes */, false);
                            break;
                        case 203 /* TypeAliasDeclaration */:
                            bindDeclaration(node, 524288 /* TypeAlias */, 793056 /* TypeAliasExcludes */, false);
                            break;
                        case 204 /* EnumDeclaration */:
                            if (ts.isConst(node)) {
                                bindDeclaration(node, 128 /* ConstEnum */, 899967 /* ConstEnumExcludes */, false);
                            }
                            else {
                                bindDeclaration(node, 256 /* RegularEnum */, 899327 /* RegularEnumExcludes */, false);
                            }
                            break;
                        case 205 /* ModuleDeclaration */:
                            bindModuleDeclaration(node);
                            break;
                        case 208 /* ImportEqualsDeclaration */:
                        case 211 /* NamespaceImport */:
                        case 213 /* ImportSpecifier */:
                        case 217 /* ExportSpecifier */:
                            bindDeclaration(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */, false);
                            break;
                        case 210 /* ImportClause */:
                            if (node.name) {
                                bindDeclaration(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */, false);
                            }
                            else {
                                bindChildren(node, 0, false);
                            }
                            break;
                        case 215 /* ExportDeclaration */:
                            if (!node.exportClause) {
                                // All export * declarations are collected in an __export symbol
                                declareSymbol(container.symbol.exports, container.symbol, node, 1073741824 /* ExportStar */, 0);
                            }
                            bindChildren(node, 0, false);
                            break;
                        case 214 /* ExportAssignment */:
                            if (node.expression.kind === 65 /* Identifier */) {
                                // An export default clause with an identifier exports all meanings of that identifier
                                declareSymbol(container.symbol.exports, container.symbol, node, 8388608 /* Alias */, 107455 /* PropertyExcludes */ | 8388608 /* AliasExcludes */);
                            }
                            else {
                                // An export default clause with an expression exports a value
                                declareSymbol(container.symbol.exports, container.symbol, node, 4 /* Property */, 107455 /* PropertyExcludes */ | 8388608 /* AliasExcludes */);
                            }
                            bindChildren(node, 0, false);
                            break;
                        case 227 /* SourceFile */:
                            setExportContextFlag(node);
                            if (ts.isExternalModule(node)) {
                                bindAnonymousDeclaration(node, 512 /* ValueModule */, '"' + ts.removeFileExtension(node.fileName) + '"', true);
                                break;
                            }
                        case 179 /* Block */:
                            // do not treat function block a block-scope container
                            // all block-scope locals that reside in this block should go to the function locals.
                            // Otherwise this won't be considered as redeclaration of a block scoped local:
                            // function foo() {
                            //  let x;
                            //  let x;
                            // }
                            // 'let x' will be placed into the function locals and 'let x' - into the locals of the block
                            bindChildren(node, 0, !ts.isFunctionLike(node.parent));
                            break;
                        case 223 /* CatchClause */:
                        case 186 /* ForStatement */:
                        case 187 /* ForInStatement */:
                        case 188 /* ForOfStatement */:
                        case 207 /* CaseBlock */:
                            bindChildren(node, 0, true);
                            break;
                        default:
                            var saveParent = parent;
                            parent = node;
                            ts.forEachChild(node, bind);
                            parent = saveParent;
                    }
                }
                function bindParameter(node) {
                    if (ts.isBindingPattern(node.name)) {
                        bindAnonymousDeclaration(node, 1 /* FunctionScopedVariable */, getDestructuringParameterName(node), false);
                    }
                    else {
                        bindDeclaration(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */, false);
                    }
                    // If this is a property-parameter, then also declare the property symbol into the 
                    // containing class.
                    if (node.flags & 112 /* AccessibilityModifier */ &&
                        node.parent.kind === 135 /* Constructor */ &&
                        (node.parent.parent.kind === 201 /* ClassDeclaration */ || node.parent.parent.kind === 174 /* ClassExpression */)) {
                        var classDeclaration = node.parent.parent;
                        declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4 /* Property */, 107455 /* PropertyExcludes */);
                    }
                }
                function bindPropertyOrMethodOrAccessor(node, symbolKind, symbolExcludes, isBlockScopeContainer) {
                    if (ts.hasDynamicName(node)) {
                        bindAnonymousDeclaration(node, symbolKind, "__computed", isBlockScopeContainer);
                    }
                    else {
                        bindDeclaration(node, symbolKind, symbolExcludes, isBlockScopeContainer);
                    }
                }
            }
        })(ts || (ts = {}));
        /// <reference path="binder.ts" />
        /* @internal */
        var ts;
        (function (ts) {
            function getDeclarationOfKind(symbol, kind) {
                var declarations = symbol.declarations;
                for (var _i = 0; _i < declarations.length; _i++) {
                    var declaration = declarations[_i];
                    if (declaration.kind === kind) {
                        return declaration;
                    }
                }
                return undefined;
            }
            ts.getDeclarationOfKind = getDeclarationOfKind;
            // Pool writers to avoid needing to allocate them for every symbol we write.
            var stringWriters = [];
            function getSingleLineStringWriter() {
                if (stringWriters.length == 0) {
                    var str = "";
                    var writeText = function (text) { return str += text; };
                    return {
                        string: function () { return str; },
                        writeKeyword: writeText,
                        writeOperator: writeText,
                        writePunctuation: writeText,
                        writeSpace: writeText,
                        writeStringLiteral: writeText,
                        writeParameter: writeText,
                        writeSymbol: writeText,
                        // Completely ignore indentation for string writers.  And map newlines to
                        // a single space.
                        writeLine: function () { return str += " "; },
                        increaseIndent: function () { },
                        decreaseIndent: function () { },
                        clear: function () { return str = ""; },
                        trackSymbol: function () { }
                    };
                }
                return stringWriters.pop();
            }
            ts.getSingleLineStringWriter = getSingleLineStringWriter;
            function releaseStringWriter(writer) {
                writer.clear();
                stringWriters.push(writer);
            }
            ts.releaseStringWriter = releaseStringWriter;
            function getFullWidth(node) {
                return node.end - node.pos;
            }
            ts.getFullWidth = getFullWidth;
            // Returns true if this node contains a parse error anywhere underneath it.
            function containsParseError(node) {
                aggregateChildData(node);
                return (node.parserContextFlags & 64 /* ThisNodeOrAnySubNodesHasError */) !== 0;
            }
            ts.containsParseError = containsParseError;
            function aggregateChildData(node) {
                if (!(node.parserContextFlags & 128 /* HasAggregatedChildData */)) {
                    // A node is considered to contain a parse error if:
                    //  a) the parser explicitly marked that it had an error
                    //  b) any of it's children reported that it had an error.
                    var thisNodeOrAnySubNodesHasError = ((node.parserContextFlags & 32 /* ThisNodeHasError */) !== 0) ||
                        ts.forEachChild(node, containsParseError);
                    // If so, mark ourselves accordingly. 
                    if (thisNodeOrAnySubNodesHasError) {
                        node.parserContextFlags |= 64 /* ThisNodeOrAnySubNodesHasError */;
                    }
                    // Also mark that we've propogated the child information to this node.  This way we can
                    // always consult the bit directly on this node without needing to check its children
                    // again.
                    node.parserContextFlags |= 128 /* HasAggregatedChildData */;
                }
            }
            function getSourceFileOfNode(node) {
                while (node && node.kind !== 227 /* SourceFile */) {
                    node = node.parent;
                }
                return node;
            }
            ts.getSourceFileOfNode = getSourceFileOfNode;
            function getStartPositionOfLine(line, sourceFile) {
                ts.Debug.assert(line >= 0);
                return ts.getLineStarts(sourceFile)[line];
            }
            ts.getStartPositionOfLine = getStartPositionOfLine;
            // This is a useful function for debugging purposes.
            function nodePosToString(node) {
                var file = getSourceFileOfNode(node);
                var loc = ts.getLineAndCharacterOfPosition(file, node.pos);
                return file.fileName + "(" + (loc.line + 1) + "," + (loc.character + 1) + ")";
            }
            ts.nodePosToString = nodePosToString;
            function getStartPosOfNode(node) {
                return node.pos;
            }
            ts.getStartPosOfNode = getStartPosOfNode;
            // Returns true if this node is missing from the actual source code.  'missing' is different
            // from 'undefined/defined'.  When a node is undefined (which can happen for optional nodes
            // in the tree), it is definitel missing.  HOwever, a node may be defined, but still be 
            // missing.  This happens whenever the parser knows it needs to parse something, but can't
            // get anything in the source code that it expects at that location.  For example:
            //
            //          let a: ;
            //
            // Here, the Type in the Type-Annotation is not-optional (as there is a colon in the source 
            // code).  So the parser will attempt to parse out a type, and will create an actual node.
            // However, this node will be 'missing' in the sense that no actual source-code/tokens are
            // contained within it.
            function nodeIsMissing(node) {
                if (!node) {
                    return true;
                }
                return node.pos === node.end && node.kind !== 1 /* EndOfFileToken */;
            }
            ts.nodeIsMissing = nodeIsMissing;
            function nodeIsPresent(node) {
                return !nodeIsMissing(node);
            }
            ts.nodeIsPresent = nodeIsPresent;
            function getTokenPosOfNode(node, sourceFile) {
                // With nodes that have no width (i.e. 'Missing' nodes), we actually *don't*
                // want to skip trivia because this will launch us forward to the next token.
                if (nodeIsMissing(node)) {
                    return node.pos;
                }
                return ts.skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos);
            }
            ts.getTokenPosOfNode = getTokenPosOfNode;
            function getNonDecoratorTokenPosOfNode(node, sourceFile) {
                if (nodeIsMissing(node) || !node.decorators) {
                    return getTokenPosOfNode(node, sourceFile);
                }
                return ts.skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.decorators.end);
            }
            ts.getNonDecoratorTokenPosOfNode = getNonDecoratorTokenPosOfNode;
            function getSourceTextOfNodeFromSourceFile(sourceFile, node) {
                if (nodeIsMissing(node)) {
                    return "";
                }
                var text = sourceFile.text;
                return text.substring(ts.skipTrivia(text, node.pos), node.end);
            }
            ts.getSourceTextOfNodeFromSourceFile = getSourceTextOfNodeFromSourceFile;
            function getTextOfNodeFromSourceText(sourceText, node) {
                if (nodeIsMissing(node)) {
                    return "";
                }
                return sourceText.substring(ts.skipTrivia(sourceText, node.pos), node.end);
            }
            ts.getTextOfNodeFromSourceText = getTextOfNodeFromSourceText;
            function getTextOfNode(node) {
                return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node);
            }
            ts.getTextOfNode = getTextOfNode;
            // Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__'
            function escapeIdentifier(identifier) {
                return identifier.length >= 2 && identifier.charCodeAt(0) === 95 /* _ */ && identifier.charCodeAt(1) === 95 /* _ */ ? "_" + identifier : identifier;
            }
            ts.escapeIdentifier = escapeIdentifier;
            // Remove extra underscore from escaped identifier
            function unescapeIdentifier(identifier) {
                return identifier.length >= 3 && identifier.charCodeAt(0) === 95 /* _ */ && identifier.charCodeAt(1) === 95 /* _ */ && identifier.charCodeAt(2) === 95 /* _ */ ? identifier.substr(1) : identifier;
            }
            ts.unescapeIdentifier = unescapeIdentifier;
            // Make an identifier from an external module name by extracting the string after the last "/" and replacing
            // all non-alphanumeric characters with underscores
            function makeIdentifierFromModuleName(moduleName) {
                return ts.getBaseFileName(moduleName).replace(/\W/g, "_");
            }
            ts.makeIdentifierFromModuleName = makeIdentifierFromModuleName;
            function isBlockOrCatchScoped(declaration) {
                return (getCombinedNodeFlags(declaration) & 12288 /* BlockScoped */) !== 0 ||
                    isCatchClauseVariableDeclaration(declaration);
            }
            ts.isBlockOrCatchScoped = isBlockOrCatchScoped;
            // Gets the nearest enclosing block scope container that has the provided node 
            // as a descendant, that is not the provided node.
            function getEnclosingBlockScopeContainer(node) {
                var current = node.parent;
                while (current) {
                    if (isFunctionLike(current)) {
                        return current;
                    }
                    switch (current.kind) {
                        case 227 /* SourceFile */:
                        case 207 /* CaseBlock */:
                        case 223 /* CatchClause */:
                        case 205 /* ModuleDeclaration */:
                        case 186 /* ForStatement */:
                        case 187 /* ForInStatement */:
                        case 188 /* ForOfStatement */:
                            return current;
                        case 179 /* Block */:
                            // function block is not considered block-scope container
                            // see comment in binder.ts: bind(...), case for SyntaxKind.Block
                            if (!isFunctionLike(current.parent)) {
                                return current;
                            }
                    }
                    current = current.parent;
                }
            }
            ts.getEnclosingBlockScopeContainer = getEnclosingBlockScopeContainer;
            function isCatchClauseVariableDeclaration(declaration) {
                return declaration &&
                    declaration.kind === 198 /* VariableDeclaration */ &&
                    declaration.parent &&
                    declaration.parent.kind === 223 /* CatchClause */;
            }
            ts.isCatchClauseVariableDeclaration = isCatchClauseVariableDeclaration;
            // Return display name of an identifier
            // Computed property names will just be emitted as "[<expr>]", where <expr> is the source
            // text of the expression in the computed property.
            function declarationNameToString(name) {
                return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
            }
            ts.declarationNameToString = declarationNameToString;
            function createDiagnosticForNode(node, message, arg0, arg1, arg2) {
                var sourceFile = getSourceFileOfNode(node);
                var span = getErrorSpanForNode(sourceFile, node);
                return ts.createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2);
            }
            ts.createDiagnosticForNode = createDiagnosticForNode;
            function createDiagnosticForNodeFromMessageChain(node, messageChain) {
                var sourceFile = getSourceFileOfNode(node);
                var span = getErrorSpanForNode(sourceFile, node);
                return {
                    file: sourceFile,
                    start: span.start,
                    length: span.length,
                    code: messageChain.code,
                    category: messageChain.category,
                    messageText: messageChain.next ? messageChain : messageChain.messageText
                };
            }
            ts.createDiagnosticForNodeFromMessageChain = createDiagnosticForNodeFromMessageChain;
            function getSpanOfTokenAtPosition(sourceFile, pos) {
                var scanner = ts.createScanner(sourceFile.languageVersion, true, sourceFile.text, undefined, pos);
                scanner.scan();
                var start = scanner.getTokenPos();
                return ts.createTextSpanFromBounds(start, scanner.getTextPos());
            }
            ts.getSpanOfTokenAtPosition = getSpanOfTokenAtPosition;
            function getErrorSpanForNode(sourceFile, node) {
                var errorNode = node;
                switch (node.kind) {
                    case 227 /* SourceFile */:
                        var pos_1 = ts.skipTrivia(sourceFile.text, 0, false);
                        if (pos_1 === sourceFile.text.length) {
                            // file is empty - return span for the beginning of the file
                            return ts.createTextSpan(0, 0);
                        }
                        return getSpanOfTokenAtPosition(sourceFile, pos_1);
                    // This list is a work in progress. Add missing node kinds to improve their error
                    // spans.
                    case 198 /* VariableDeclaration */:
                    case 152 /* BindingElement */:
                    case 201 /* ClassDeclaration */:
                    case 174 /* ClassExpression */:
                    case 202 /* InterfaceDeclaration */:
                    case 205 /* ModuleDeclaration */:
                    case 204 /* EnumDeclaration */:
                    case 226 /* EnumMember */:
                    case 200 /* FunctionDeclaration */:
                    case 162 /* FunctionExpression */:
                        errorNode = node.name;
                        break;
                }
                if (errorNode === undefined) {
                    // If we don't have a better node, then just set the error on the first token of 
                    // construct.
                    return getSpanOfTokenAtPosition(sourceFile, node.pos);
                }
                var pos = nodeIsMissing(errorNode)
                    ? errorNode.pos
                    : ts.skipTrivia(sourceFile.text, errorNode.pos);
                return ts.createTextSpanFromBounds(pos, errorNode.end);
            }
            ts.getErrorSpanForNode = getErrorSpanForNode;
            function isExternalModule(file) {
                return file.externalModuleIndicator !== undefined;
            }
            ts.isExternalModule = isExternalModule;
            function isDeclarationFile(file) {
                return (file.flags & 2048 /* DeclarationFile */) !== 0;
            }
            ts.isDeclarationFile = isDeclarationFile;
            function isConstEnumDeclaration(node) {
                return node.kind === 204 /* EnumDeclaration */ && isConst(node);
            }
            ts.isConstEnumDeclaration = isConstEnumDeclaration;
            function walkUpBindingElementsAndPatterns(node) {
                while (node && (node.kind === 152 /* BindingElement */ || isBindingPattern(node))) {
                    node = node.parent;
                }
                return node;
            }
            // Returns the node flags for this node and all relevant parent nodes.  This is done so that 
            // nodes like variable declarations and binding elements can returned a view of their flags
            // that includes the modifiers from their container.  i.e. flags like export/declare aren't
            // stored on the variable declaration directly, but on the containing variable statement 
            // (if it has one).  Similarly, flags for let/const are store on the variable declaration
            // list.  By calling this function, all those flags are combined so that the client can treat
            // the node as if it actually had those flags.
            function getCombinedNodeFlags(node) {
                node = walkUpBindingElementsAndPatterns(node);
                var flags = node.flags;
                if (node.kind === 198 /* VariableDeclaration */) {
                    node = node.parent;
                }
                if (node && node.kind === 199 /* VariableDeclarationList */) {
                    flags |= node.flags;
                    node = node.parent;
                }
                if (node && node.kind === 180 /* VariableStatement */) {
                    flags |= node.flags;
                }
                return flags;
            }
            ts.getCombinedNodeFlags = getCombinedNodeFlags;
            function isConst(node) {
                return !!(getCombinedNodeFlags(node) & 8192 /* Const */);
            }
            ts.isConst = isConst;
            function isLet(node) {
                return !!(getCombinedNodeFlags(node) & 4096 /* Let */);
            }
            ts.isLet = isLet;
            function isPrologueDirective(node) {
                return node.kind === 182 /* ExpressionStatement */ && node.expression.kind === 8 /* StringLiteral */;
            }
            ts.isPrologueDirective = isPrologueDirective;
            function getLeadingCommentRangesOfNode(node, sourceFileOfNode) {
                // If parameter/type parameter, the prev token trailing comments are part of this node too
                if (node.kind === 129 /* Parameter */ || node.kind === 128 /* TypeParameter */) {
                    // e.g.   (/** blah */ a, /** blah */ b);
                    // e.g.:     (
                    //            /** blah */ a,
                    //            /** blah */ b);
                    return ts.concatenate(ts.getTrailingCommentRanges(sourceFileOfNode.text, node.pos), ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos));
                }
                else {
                    return ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos);
                }
            }
            ts.getLeadingCommentRangesOfNode = getLeadingCommentRangesOfNode;
            function getJsDocComments(node, sourceFileOfNode) {
                return ts.filter(getLeadingCommentRangesOfNode(node, sourceFileOfNode), isJsDocComment);
                function isJsDocComment(comment) {
                    // True if the comment starts with '/**' but not if it is '/**/'
                    return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === 42 /* asterisk */ &&
                        sourceFileOfNode.text.charCodeAt(comment.pos + 2) === 42 /* asterisk */ &&
                        sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== 47 /* slash */;
                }
            }
            ts.getJsDocComments = getJsDocComments;
            ts.fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*<reference\s+path\s*=\s*)('|")(.+?)\2.*?\/>/;
            // Warning: This has the same semantics as the forEach family of functions,
            //          in that traversal terminates in the event that 'visitor' supplies a truthy value.
            function forEachReturnStatement(body, visitor) {
                return traverse(body);
                function traverse(node) {
                    switch (node.kind) {
                        case 191 /* ReturnStatement */:
                            return visitor(node);
                        case 207 /* CaseBlock */:
                        case 179 /* Block */:
                        case 183 /* IfStatement */:
                        case 184 /* DoStatement */:
                        case 185 /* WhileStatement */:
                        case 186 /* ForStatement */:
                        case 187 /* ForInStatement */:
                        case 188 /* ForOfStatement */:
                        case 192 /* WithStatement */:
                        case 193 /* SwitchStatement */:
                        case 220 /* CaseClause */:
                        case 221 /* DefaultClause */:
                        case 194 /* LabeledStatement */:
                        case 196 /* TryStatement */:
                        case 223 /* CatchClause */:
                            return ts.forEachChild(node, traverse);
                    }
                }
            }
            ts.forEachReturnStatement = forEachReturnStatement;
            function isVariableLike(node) {
                if (node) {
                    switch (node.kind) {
                        case 152 /* BindingElement */:
                        case 226 /* EnumMember */:
                        case 129 /* Parameter */:
                        case 224 /* PropertyAssignment */:
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                        case 225 /* ShorthandPropertyAssignment */:
                        case 198 /* VariableDeclaration */:
                            return true;
                    }
                }
                return false;
            }
            ts.isVariableLike = isVariableLike;
            function isAccessor(node) {
                if (node) {
                    switch (node.kind) {
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                            return true;
                    }
                }
                return false;
            }
            ts.isAccessor = isAccessor;
            function isFunctionLike(node) {
                if (node) {
                    switch (node.kind) {
                        case 135 /* Constructor */:
                        case 162 /* FunctionExpression */:
                        case 200 /* FunctionDeclaration */:
                        case 163 /* ArrowFunction */:
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                        case 138 /* CallSignature */:
                        case 139 /* ConstructSignature */:
                        case 140 /* IndexSignature */:
                        case 142 /* FunctionType */:
                        case 143 /* ConstructorType */:
                        case 162 /* FunctionExpression */:
                        case 163 /* ArrowFunction */:
                        case 200 /* FunctionDeclaration */:
                            return true;
                    }
                }
                return false;
            }
            ts.isFunctionLike = isFunctionLike;
            function isFunctionBlock(node) {
                return node && node.kind === 179 /* Block */ && isFunctionLike(node.parent);
            }
            ts.isFunctionBlock = isFunctionBlock;
            function isObjectLiteralMethod(node) {
                return node && node.kind === 134 /* MethodDeclaration */ && node.parent.kind === 154 /* ObjectLiteralExpression */;
            }
            ts.isObjectLiteralMethod = isObjectLiteralMethod;
            function getContainingFunction(node) {
                while (true) {
                    node = node.parent;
                    if (!node || isFunctionLike(node)) {
                        return node;
                    }
                }
            }
            ts.getContainingFunction = getContainingFunction;
            function getThisContainer(node, includeArrowFunctions) {
                while (true) {
                    node = node.parent;
                    if (!node) {
                        return undefined;
                    }
                    switch (node.kind) {
                        case 127 /* ComputedPropertyName */:
                            // If the grandparent node is an object literal (as opposed to a class),
                            // then the computed property is not a 'this' container.
                            // A computed property name in a class needs to be a this container
                            // so that we can error on it.
                            if (node.parent.parent.kind === 201 /* ClassDeclaration */) {
                                return node;
                            }
                            // If this is a computed property, then the parent should not
                            // make it a this container. The parent might be a property
                            // in an object literal, like a method or accessor. But in order for
                            // such a parent to be a this container, the reference must be in
                            // the *body* of the container.
                            node = node.parent;
                            break;
                        case 130 /* Decorator */:
                            // Decorators are always applied outside of the body of a class or method. 
                            if (node.parent.kind === 129 /* Parameter */ && isClassElement(node.parent.parent)) {
                                // If the decorator's parent is a Parameter, we resolve the this container from
                                // the grandparent class declaration.
                                node = node.parent.parent;
                            }
                            else if (isClassElement(node.parent)) {
                                // If the decorator's parent is a class element, we resolve the 'this' container
                                // from the parent class declaration.
                                node = node.parent;
                            }
                            break;
                        case 163 /* ArrowFunction */:
                            if (!includeArrowFunctions) {
                                continue;
                            }
                        // Fall through
                        case 200 /* FunctionDeclaration */:
                        case 162 /* FunctionExpression */:
                        case 205 /* ModuleDeclaration */:
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                        case 135 /* Constructor */:
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                        case 204 /* EnumDeclaration */:
                        case 227 /* SourceFile */:
                            return node;
                    }
                }
            }
            ts.getThisContainer = getThisContainer;
            function getSuperContainer(node, includeFunctions) {
                while (true) {
                    node = node.parent;
                    if (!node)
                        return node;
                    switch (node.kind) {
                        case 127 /* ComputedPropertyName */:
                            // If the grandparent node is an object literal (as opposed to a class),
                            // then the computed property is not a 'super' container.
                            // A computed property name in a class needs to be a super container
                            // so that we can error on it.
                            if (node.parent.parent.kind === 201 /* ClassDeclaration */) {
                                return node;
                            }
                            // If this is a computed property, then the parent should not
                            // make it a super container. The parent might be a property
                            // in an object literal, like a method or accessor. But in order for
                            // such a parent to be a super container, the reference must be in
                            // the *body* of the container.
                            node = node.parent;
                            break;
                        case 130 /* Decorator */:
                            // Decorators are always applied outside of the body of a class or method. 
                            if (node.parent.kind === 129 /* Parameter */ && isClassElement(node.parent.parent)) {
                                // If the decorator's parent is a Parameter, we resolve the this container from
                                // the grandparent class declaration.
                                node = node.parent.parent;
                            }
                            else if (isClassElement(node.parent)) {
                                // If the decorator's parent is a class element, we resolve the 'this' container
                                // from the parent class declaration.
                                node = node.parent;
                            }
                            break;
                        case 200 /* FunctionDeclaration */:
                        case 162 /* FunctionExpression */:
                        case 163 /* ArrowFunction */:
                            if (!includeFunctions) {
                                continue;
                            }
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                        case 135 /* Constructor */:
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                            return node;
                    }
                }
            }
            ts.getSuperContainer = getSuperContainer;
            function getInvokedExpression(node) {
                if (node.kind === 159 /* TaggedTemplateExpression */) {
                    return node.tag;
                }
                // Will either be a CallExpression or NewExpression.
                return node.expression;
            }
            ts.getInvokedExpression = getInvokedExpression;
            function nodeCanBeDecorated(node) {
                switch (node.kind) {
                    case 201 /* ClassDeclaration */:
                        // classes are valid targets
                        return true;
                    case 132 /* PropertyDeclaration */:
                        // property declarations are valid if their parent is a class declaration.
                        return node.parent.kind === 201 /* ClassDeclaration */;
                    case 129 /* Parameter */:
                        // if the parameter's parent has a body and its grandparent is a class declaration, this is a valid target;
                        return node.parent.body && node.parent.parent.kind === 201 /* ClassDeclaration */;
                    case 136 /* GetAccessor */:
                    case 137 /* SetAccessor */:
                    case 134 /* MethodDeclaration */:
                        // if this method has a body and its parent is a class declaration, this is a valid target.
                        return node.body && node.parent.kind === 201 /* ClassDeclaration */;
                }
                return false;
            }
            ts.nodeCanBeDecorated = nodeCanBeDecorated;
            function nodeIsDecorated(node) {
                switch (node.kind) {
                    case 201 /* ClassDeclaration */:
                        if (node.decorators) {
                            return true;
                        }
                        return false;
                    case 132 /* PropertyDeclaration */:
                    case 129 /* Parameter */:
                        if (node.decorators) {
                            return true;
                        }
                        return false;
                    case 136 /* GetAccessor */:
                        if (node.body && node.decorators) {
                            return true;
                        }
                        return false;
                    case 134 /* MethodDeclaration */:
                    case 137 /* SetAccessor */:
                        if (node.body && node.decorators) {
                            return true;
                        }
                        return false;
                }
                return false;
            }
            ts.nodeIsDecorated = nodeIsDecorated;
            function childIsDecorated(node) {
                switch (node.kind) {
                    case 201 /* ClassDeclaration */:
                        return ts.forEach(node.members, nodeOrChildIsDecorated);
                    case 134 /* MethodDeclaration */:
                    case 137 /* SetAccessor */:
                        return ts.forEach(node.parameters, nodeIsDecorated);
                }
                return false;
            }
            ts.childIsDecorated = childIsDecorated;
            function nodeOrChildIsDecorated(node) {
                return nodeIsDecorated(node) || childIsDecorated(node);
            }
            ts.nodeOrChildIsDecorated = nodeOrChildIsDecorated;
            function isExpression(node) {
                switch (node.kind) {
                    case 93 /* ThisKeyword */:
                    case 91 /* SuperKeyword */:
                    case 89 /* NullKeyword */:
                    case 95 /* TrueKeyword */:
                    case 80 /* FalseKeyword */:
                    case 9 /* RegularExpressionLiteral */:
                    case 153 /* ArrayLiteralExpression */:
                    case 154 /* ObjectLiteralExpression */:
                    case 155 /* PropertyAccessExpression */:
                    case 156 /* ElementAccessExpression */:
                    case 157 /* CallExpression */:
                    case 158 /* NewExpression */:
                    case 159 /* TaggedTemplateExpression */:
                    case 160 /* TypeAssertionExpression */:
                    case 161 /* ParenthesizedExpression */:
                    case 162 /* FunctionExpression */:
                    case 174 /* ClassExpression */:
                    case 163 /* ArrowFunction */:
                    case 166 /* VoidExpression */:
                    case 164 /* DeleteExpression */:
                    case 165 /* TypeOfExpression */:
                    case 167 /* PrefixUnaryExpression */:
                    case 168 /* PostfixUnaryExpression */:
                    case 169 /* BinaryExpression */:
                    case 170 /* ConditionalExpression */:
                    case 173 /* SpreadElementExpression */:
                    case 171 /* TemplateExpression */:
                    case 10 /* NoSubstitutionTemplateLiteral */:
                    case 175 /* OmittedExpression */:
                        return true;
                    case 126 /* QualifiedName */:
                        while (node.parent.kind === 126 /* QualifiedName */) {
                            node = node.parent;
                        }
                        return node.parent.kind === 144 /* TypeQuery */;
                    case 65 /* Identifier */:
                        if (node.parent.kind === 144 /* TypeQuery */) {
                            return true;
                        }
                    // fall through
                    case 7 /* NumericLiteral */:
                    case 8 /* StringLiteral */:
                        var parent_1 = node.parent;
                        switch (parent_1.kind) {
                            case 198 /* VariableDeclaration */:
                            case 129 /* Parameter */:
                            case 132 /* PropertyDeclaration */:
                            case 131 /* PropertySignature */:
                            case 226 /* EnumMember */:
                            case 224 /* PropertyAssignment */:
                            case 152 /* BindingElement */:
                                return parent_1.initializer === node;
                            case 182 /* ExpressionStatement */:
                            case 183 /* IfStatement */:
                            case 184 /* DoStatement */:
                            case 185 /* WhileStatement */:
                            case 191 /* ReturnStatement */:
                            case 192 /* WithStatement */:
                            case 193 /* SwitchStatement */:
                            case 220 /* CaseClause */:
                            case 195 /* ThrowStatement */:
                            case 193 /* SwitchStatement */:
                                return parent_1.expression === node;
                            case 186 /* ForStatement */:
                                var forStatement = parent_1;
                                return (forStatement.initializer === node && forStatement.initializer.kind !== 199 /* VariableDeclarationList */) ||
                                    forStatement.condition === node ||
                                    forStatement.incrementor === node;
                            case 187 /* ForInStatement */:
                            case 188 /* ForOfStatement */:
                                var forInStatement = parent_1;
                                return (forInStatement.initializer === node && forInStatement.initializer.kind !== 199 /* VariableDeclarationList */) ||
                                    forInStatement.expression === node;
                            case 160 /* TypeAssertionExpression */:
                                return node === parent_1.expression;
                            case 176 /* TemplateSpan */:
                                return node === parent_1.expression;
                            case 127 /* ComputedPropertyName */:
                                return node === parent_1.expression;
                            case 130 /* Decorator */:
                                return true;
                            default:
                                if (isExpression(parent_1)) {
                                    return true;
                                }
                        }
                }
                return false;
            }
            ts.isExpression = isExpression;
            function isInstantiatedModule(node, preserveConstEnums) {
                var moduleState = ts.getModuleInstanceState(node);
                return moduleState === 1 /* Instantiated */ ||
                    (preserveConstEnums && moduleState === 2 /* ConstEnumOnly */);
            }
            ts.isInstantiatedModule = isInstantiatedModule;
            function isExternalModuleImportEqualsDeclaration(node) {
                return node.kind === 208 /* ImportEqualsDeclaration */ && node.moduleReference.kind === 219 /* ExternalModuleReference */;
            }
            ts.isExternalModuleImportEqualsDeclaration = isExternalModuleImportEqualsDeclaration;
            function getExternalModuleImportEqualsDeclarationExpression(node) {
                ts.Debug.assert(isExternalModuleImportEqualsDeclaration(node));
                return node.moduleReference.expression;
            }
            ts.getExternalModuleImportEqualsDeclarationExpression = getExternalModuleImportEqualsDeclarationExpression;
            function isInternalModuleImportEqualsDeclaration(node) {
                return node.kind === 208 /* ImportEqualsDeclaration */ && node.moduleReference.kind !== 219 /* ExternalModuleReference */;
            }
            ts.isInternalModuleImportEqualsDeclaration = isInternalModuleImportEqualsDeclaration;
            function getExternalModuleName(node) {
                if (node.kind === 209 /* ImportDeclaration */) {
                    return node.moduleSpecifier;
                }
                if (node.kind === 208 /* ImportEqualsDeclaration */) {
                    var reference = node.moduleReference;
                    if (reference.kind === 219 /* ExternalModuleReference */) {
                        return reference.expression;
                    }
                }
                if (node.kind === 215 /* ExportDeclaration */) {
                    return node.moduleSpecifier;
                }
            }
            ts.getExternalModuleName = getExternalModuleName;
            function hasDotDotDotToken(node) {
                return node && node.kind === 129 /* Parameter */ && node.dotDotDotToken !== undefined;
            }
            ts.hasDotDotDotToken = hasDotDotDotToken;
            function hasQuestionToken(node) {
                if (node) {
                    switch (node.kind) {
                        case 129 /* Parameter */:
                            return node.questionToken !== undefined;
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                            return node.questionToken !== undefined;
                        case 225 /* ShorthandPropertyAssignment */:
                        case 224 /* PropertyAssignment */:
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                            return node.questionToken !== undefined;
                    }
                }
                return false;
            }
            ts.hasQuestionToken = hasQuestionToken;
            function hasRestParameters(s) {
                return s.parameters.length > 0 && s.parameters[s.parameters.length - 1].dotDotDotToken !== undefined;
            }
            ts.hasRestParameters = hasRestParameters;
            function isLiteralKind(kind) {
                return 7 /* FirstLiteralToken */ <= kind && kind <= 10 /* LastLiteralToken */;
            }
            ts.isLiteralKind = isLiteralKind;
            function isTextualLiteralKind(kind) {
                return kind === 8 /* StringLiteral */ || kind === 10 /* NoSubstitutionTemplateLiteral */;
            }
            ts.isTextualLiteralKind = isTextualLiteralKind;
            function isTemplateLiteralKind(kind) {
                return 10 /* FirstTemplateToken */ <= kind && kind <= 13 /* LastTemplateToken */;
            }
            ts.isTemplateLiteralKind = isTemplateLiteralKind;
            function isBindingPattern(node) {
                return !!node && (node.kind === 151 /* ArrayBindingPattern */ || node.kind === 150 /* ObjectBindingPattern */);
            }
            ts.isBindingPattern = isBindingPattern;
            function isInAmbientContext(node) {
                while (node) {
                    if (node.flags & (2 /* Ambient */ | 2048 /* DeclarationFile */)) {
                        return true;
                    }
                    node = node.parent;
                }
                return false;
            }
            ts.isInAmbientContext = isInAmbientContext;
            function isDeclaration(node) {
                switch (node.kind) {
                    case 163 /* ArrowFunction */:
                    case 152 /* BindingElement */:
                    case 201 /* ClassDeclaration */:
                    case 135 /* Constructor */:
                    case 204 /* EnumDeclaration */:
                    case 226 /* EnumMember */:
                    case 217 /* ExportSpecifier */:
                    case 200 /* FunctionDeclaration */:
                    case 162 /* FunctionExpression */:
                    case 136 /* GetAccessor */:
                    case 210 /* ImportClause */:
                    case 208 /* ImportEqualsDeclaration */:
                    case 213 /* ImportSpecifier */:
                    case 202 /* InterfaceDeclaration */:
                    case 134 /* MethodDeclaration */:
                    case 133 /* MethodSignature */:
                    case 205 /* ModuleDeclaration */:
                    case 211 /* NamespaceImport */:
                    case 129 /* Parameter */:
                    case 224 /* PropertyAssignment */:
                    case 132 /* PropertyDeclaration */:
                    case 131 /* PropertySignature */:
                    case 137 /* SetAccessor */:
                    case 225 /* ShorthandPropertyAssignment */:
                    case 203 /* TypeAliasDeclaration */:
                    case 128 /* TypeParameter */:
                    case 198 /* VariableDeclaration */:
                        return true;
                }
                return false;
            }
            ts.isDeclaration = isDeclaration;
            function isStatement(n) {
                switch (n.kind) {
                    case 190 /* BreakStatement */:
                    case 189 /* ContinueStatement */:
                    case 197 /* DebuggerStatement */:
                    case 184 /* DoStatement */:
                    case 182 /* ExpressionStatement */:
                    case 181 /* EmptyStatement */:
                    case 187 /* ForInStatement */:
                    case 188 /* ForOfStatement */:
                    case 186 /* ForStatement */:
                    case 183 /* IfStatement */:
                    case 194 /* LabeledStatement */:
                    case 191 /* ReturnStatement */:
                    case 193 /* SwitchStatement */:
                    case 94 /* ThrowKeyword */:
                    case 196 /* TryStatement */:
                    case 180 /* VariableStatement */:
                    case 185 /* WhileStatement */:
                    case 192 /* WithStatement */:
                    case 214 /* ExportAssignment */:
                        return true;
                    default:
                        return false;
                }
            }
            ts.isStatement = isStatement;
            function isClassElement(n) {
                switch (n.kind) {
                    case 135 /* Constructor */:
                    case 132 /* PropertyDeclaration */:
                    case 134 /* MethodDeclaration */:
                    case 136 /* GetAccessor */:
                    case 137 /* SetAccessor */:
                    case 133 /* MethodSignature */:
                    case 140 /* IndexSignature */:
                        return true;
                    default:
                        return false;
                }
            }
            ts.isClassElement = isClassElement;
            // True if the given identifier, string literal, or number literal is the name of a declaration node
            function isDeclarationName(name) {
                if (name.kind !== 65 /* Identifier */ && name.kind !== 8 /* StringLiteral */ && name.kind !== 7 /* NumericLiteral */) {
                    return false;
                }
                var parent = name.parent;
                if (parent.kind === 213 /* ImportSpecifier */ || parent.kind === 217 /* ExportSpecifier */) {
                    if (parent.propertyName) {
                        return true;
                    }
                }
                if (isDeclaration(parent)) {
                    return parent.name === name;
                }
                return false;
            }
            ts.isDeclarationName = isDeclarationName;
            // An alias symbol is created by one of the following declarations:
            // import <symbol> = ...
            // import <symbol> from ...
            // import * as <symbol> from ...
            // import { x as <symbol> } from ...
            // export { x as <symbol> } from ...
            // export = ...
            // export default ...
            function isAliasSymbolDeclaration(node) {
                return node.kind === 208 /* ImportEqualsDeclaration */ ||
                    node.kind === 210 /* ImportClause */ && !!node.name ||
                    node.kind === 211 /* NamespaceImport */ ||
                    node.kind === 213 /* ImportSpecifier */ ||
                    node.kind === 217 /* ExportSpecifier */ ||
                    node.kind === 214 /* ExportAssignment */ && node.expression.kind === 65 /* Identifier */;
            }
            ts.isAliasSymbolDeclaration = isAliasSymbolDeclaration;
            function getClassExtendsHeritageClauseElement(node) {
                var heritageClause = getHeritageClause(node.heritageClauses, 79 /* ExtendsKeyword */);
                return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined;
            }
            ts.getClassExtendsHeritageClauseElement = getClassExtendsHeritageClauseElement;
            function getClassImplementsHeritageClauseElements(node) {
                var heritageClause = getHeritageClause(node.heritageClauses, 102 /* ImplementsKeyword */);
                return heritageClause ? heritageClause.types : undefined;
            }
            ts.getClassImplementsHeritageClauseElements = getClassImplementsHeritageClauseElements;
            function getInterfaceBaseTypeNodes(node) {
                var heritageClause = getHeritageClause(node.heritageClauses, 79 /* ExtendsKeyword */);
                return heritageClause ? heritageClause.types : undefined;
            }
            ts.getInterfaceBaseTypeNodes = getInterfaceBaseTypeNodes;
            function getHeritageClause(clauses, kind) {
                if (clauses) {
                    for (var _i = 0; _i < clauses.length; _i++) {
                        var clause = clauses[_i];
                        if (clause.token === kind) {
                            return clause;
                        }
                    }
                }
                return undefined;
            }
            ts.getHeritageClause = getHeritageClause;
            function tryResolveScriptReference(host, sourceFile, reference) {
                if (!host.getCompilerOptions().noResolve) {
                    var referenceFileName = ts.isRootedDiskPath(reference.fileName) ? reference.fileName : ts.combinePaths(ts.getDirectoryPath(sourceFile.fileName), reference.fileName);
                    referenceFileName = ts.getNormalizedAbsolutePath(referenceFileName, host.getCurrentDirectory());
                    return host.getSourceFile(referenceFileName);
                }
            }
            ts.tryResolveScriptReference = tryResolveScriptReference;
            function getAncestor(node, kind) {
                while (node) {
                    if (node.kind === kind) {
                        return node;
                    }
                    node = node.parent;
                }
                return undefined;
            }
            ts.getAncestor = getAncestor;
            function getFileReferenceFromReferencePath(comment, commentRange) {
                var simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
                var isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim;
                if (simpleReferenceRegEx.exec(comment)) {
                    if (isNoDefaultLibRegEx.exec(comment)) {
                        return {
                            isNoDefaultLib: true
                        };
                    }
                    else {
                        var matchResult = ts.fullTripleSlashReferencePathRegEx.exec(comment);
                        if (matchResult) {
                            var start = commentRange.pos;
                            var end = commentRange.end;
                            return {
                                fileReference: {
                                    pos: start,
                                    end: end,
                                    fileName: matchResult[3]
                                },
                                isNoDefaultLib: false
                            };
                        }
                        else {
                            return {
                                diagnosticMessage: ts.Diagnostics.Invalid_reference_directive_syntax,
                                isNoDefaultLib: false
                            };
                        }
                    }
                }
                return undefined;
            }
            ts.getFileReferenceFromReferencePath = getFileReferenceFromReferencePath;
            function isKeyword(token) {
                return 66 /* FirstKeyword */ <= token && token <= 125 /* LastKeyword */;
            }
            ts.isKeyword = isKeyword;
            function isTrivia(token) {
                return 2 /* FirstTriviaToken */ <= token && token <= 6 /* LastTriviaToken */;
            }
            ts.isTrivia = isTrivia;
            /**
             * A declaration has a dynamic name if both of the following are true:
             *   1. The declaration has a computed property name
             *   2. The computed name is *not* expressed as Symbol.<name>, where name
             *      is a property of the Symbol constructor that denotes a built in
             *      Symbol.
             */
            function hasDynamicName(declaration) {
                return declaration.name &&
                    declaration.name.kind === 127 /* ComputedPropertyName */ &&
                    !isWellKnownSymbolSyntactically(declaration.name.expression);
            }
            ts.hasDynamicName = hasDynamicName;
            /**
             * Checks if the expression is of the form:
             *    Symbol.name
             * where Symbol is literally the word "Symbol", and name is any identifierName
             */
            function isWellKnownSymbolSyntactically(node) {
                return node.kind === 155 /* PropertyAccessExpression */ && isESSymbolIdentifier(node.expression);
            }
            ts.isWellKnownSymbolSyntactically = isWellKnownSymbolSyntactically;
            function getPropertyNameForPropertyNameNode(name) {
                if (name.kind === 65 /* Identifier */ || name.kind === 8 /* StringLiteral */ || name.kind === 7 /* NumericLiteral */) {
                    return name.text;
                }
                if (name.kind === 127 /* ComputedPropertyName */) {
                    var nameExpression = name.expression;
                    if (isWellKnownSymbolSyntactically(nameExpression)) {
                        var rightHandSideName = nameExpression.name.text;
                        return getPropertyNameForKnownSymbolName(rightHandSideName);
                    }
                }
                return undefined;
            }
            ts.getPropertyNameForPropertyNameNode = getPropertyNameForPropertyNameNode;
            function getPropertyNameForKnownSymbolName(symbolName) {
                return "__@" + symbolName;
            }
            ts.getPropertyNameForKnownSymbolName = getPropertyNameForKnownSymbolName;
            /**
             * Includes the word "Symbol" with unicode escapes
             */
            function isESSymbolIdentifier(node) {
                return node.kind === 65 /* Identifier */ && node.text === "Symbol";
            }
            ts.isESSymbolIdentifier = isESSymbolIdentifier;
            function isModifier(token) {
                switch (token) {
                    case 108 /* PublicKeyword */:
                    case 106 /* PrivateKeyword */:
                    case 107 /* ProtectedKeyword */:
                    case 109 /* StaticKeyword */:
                    case 78 /* ExportKeyword */:
                    case 115 /* DeclareKeyword */:
                    case 70 /* ConstKeyword */:
                    case 73 /* DefaultKeyword */:
                        return true;
                }
                return false;
            }
            ts.isModifier = isModifier;
            function nodeStartsNewLexicalEnvironment(n) {
                return isFunctionLike(n) || n.kind === 205 /* ModuleDeclaration */ || n.kind === 227 /* SourceFile */;
            }
            ts.nodeStartsNewLexicalEnvironment = nodeStartsNewLexicalEnvironment;
            function nodeIsSynthesized(node) {
                return node.pos === -1;
            }
            ts.nodeIsSynthesized = nodeIsSynthesized;
            function createSynthesizedNode(kind, startsOnNewLine) {
                var node = ts.createNode(kind);
                node.pos = -1;
                node.end = -1;
                node.startsOnNewLine = startsOnNewLine;
                return node;
            }
            ts.createSynthesizedNode = createSynthesizedNode;
            function createSynthesizedNodeArray() {
                var array = [];
                array.pos = -1;
                array.end = -1;
                return array;
            }
            ts.createSynthesizedNodeArray = createSynthesizedNodeArray;
            function createDiagnosticCollection() {
                var nonFileDiagnostics = [];
                var fileDiagnostics = {};
                var diagnosticsModified = false;
                var modificationCount = 0;
                return {
                    add: add,
                    getGlobalDiagnostics: getGlobalDiagnostics,
                    getDiagnostics: getDiagnostics,
                    getModificationCount: getModificationCount
                };
                function getModificationCount() {
                    return modificationCount;
                }
                function add(diagnostic) {
                    var diagnostics;
                    if (diagnostic.file) {
                        diagnostics = fileDiagnostics[diagnostic.file.fileName];
                        if (!diagnostics) {
                            diagnostics = [];
                            fileDiagnostics[diagnostic.file.fileName] = diagnostics;
                        }
                    }
                    else {
                        diagnostics = nonFileDiagnostics;
                    }
                    diagnostics.push(diagnostic);
                    diagnosticsModified = true;
                    modificationCount++;
                }
                function getGlobalDiagnostics() {
                    sortAndDeduplicate();
                    return nonFileDiagnostics;
                }
                function getDiagnostics(fileName) {
                    sortAndDeduplicate();
                    if (fileName) {
                        return fileDiagnostics[fileName] || [];
                    }
                    var allDiagnostics = [];
                    function pushDiagnostic(d) {
                        allDiagnostics.push(d);
                    }
                    ts.forEach(nonFileDiagnostics, pushDiagnostic);
                    for (var key in fileDiagnostics) {
                        if (ts.hasProperty(fileDiagnostics, key)) {
                            ts.forEach(fileDiagnostics[key], pushDiagnostic);
                        }
                    }
                    return ts.sortAndDeduplicateDiagnostics(allDiagnostics);
                }
                function sortAndDeduplicate() {
                    if (!diagnosticsModified) {
                        return;
                    }
                    diagnosticsModified = false;
                    nonFileDiagnostics = ts.sortAndDeduplicateDiagnostics(nonFileDiagnostics);
                    for (var key in fileDiagnostics) {
                        if (ts.hasProperty(fileDiagnostics, key)) {
                            fileDiagnostics[key] = ts.sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
                        }
                    }
                }
            }
            ts.createDiagnosticCollection = createDiagnosticCollection;
            // This consists of the first 19 unprintable ASCII characters, canonical escapes, lineSeparator,
            // paragraphSeparator, and nextLine. The latter three are just desirable to suppress new lines in
            // the language service. These characters should be escaped when printing, and if any characters are added,
            // the map below must be updated. Note that this regexp *does not* include the 'delete' character.
            // There is no reason for this other than that JSON.stringify does not handle it either.
            var escapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
            var escapedCharsMap = {
                "\0": "\\0",
                "\t": "\\t",
                "\v": "\\v",
                "\f": "\\f",
                "\b": "\\b",
                "\r": "\\r",
                "\n": "\\n",
                "\\": "\\\\",
                "\"": "\\\"",
                "\u2028": "\\u2028",
                "\u2029": "\\u2029",
                "\u0085": "\\u0085" // nextLine
            };
            /**
             * Based heavily on the abstract 'Quote'/'QuoteJSONString' operation from ECMA-262 (24.3.2.2),
             * but augmented for a few select characters (e.g. lineSeparator, paragraphSeparator, nextLine)
             * Note that this doesn't actually wrap the input in double quotes.
             */
            function escapeString(s) {
                s = escapedCharsRegExp.test(s) ? s.replace(escapedCharsRegExp, getReplacement) : s;
                return s;
                function getReplacement(c) {
                    return escapedCharsMap[c] || get16BitUnicodeEscapeSequence(c.charCodeAt(0));
                }
            }
            ts.escapeString = escapeString;
            function get16BitUnicodeEscapeSequence(charCode) {
                var hexCharCode = charCode.toString(16).toUpperCase();
                var paddedHexCode = ("0000" + hexCharCode).slice(-4);
                return "\\u" + paddedHexCode;
            }
            var nonAsciiCharacters = /[^\u0000-\u007F]/g;
            function escapeNonAsciiCharacters(s) {
                // Replace non-ASCII characters with '\uNNNN' escapes if any exist.
                // Otherwise just return the original string.
                return nonAsciiCharacters.test(s) ?
                    s.replace(nonAsciiCharacters, function (c) { return get16BitUnicodeEscapeSequence(c.charCodeAt(0)); }) :
                    s;
            }
            ts.escapeNonAsciiCharacters = escapeNonAsciiCharacters;
            var indentStrings = ["", "    "];
            function getIndentString(level) {
                if (indentStrings[level] === undefined) {
                    indentStrings[level] = getIndentString(level - 1) + indentStrings[1];
                }
                return indentStrings[level];
            }
            ts.getIndentString = getIndentString;
            function getIndentSize() {
                return indentStrings[1].length;
            }
            ts.getIndentSize = getIndentSize;
            function createTextWriter(newLine) {
                var output = "";
                var indent = 0;
                var lineStart = true;
                var lineCount = 0;
                var linePos = 0;
                function write(s) {
                    if (s && s.length) {
                        if (lineStart) {
                            output += getIndentString(indent);
                            lineStart = false;
                        }
                        output += s;
                    }
                }
                function rawWrite(s) {
                    if (s !== undefined) {
                        if (lineStart) {
                            lineStart = false;
                        }
                        output += s;
                    }
                }
                function writeLiteral(s) {
                    if (s && s.length) {
                        write(s);
                        var lineStartsOfS = ts.computeLineStarts(s);
                        if (lineStartsOfS.length > 1) {
                            lineCount = lineCount + lineStartsOfS.length - 1;
                            linePos = output.length - s.length + lineStartsOfS[lineStartsOfS.length - 1];
                        }
                    }
                }
                function writeLine() {
                    if (!lineStart) {
                        output += newLine;
                        lineCount++;
                        linePos = output.length;
                        lineStart = true;
                    }
                }
                function writeTextOfNode(sourceFile, node) {
                    write(getSourceTextOfNodeFromSourceFile(sourceFile, node));
                }
                return {
                    write: write,
                    rawWrite: rawWrite,
                    writeTextOfNode: writeTextOfNode,
                    writeLiteral: writeLiteral,
                    writeLine: writeLine,
                    increaseIndent: function () { return indent++; },
                    decreaseIndent: function () { return indent--; },
                    getIndent: function () { return indent; },
                    getTextPos: function () { return output.length; },
                    getLine: function () { return lineCount + 1; },
                    getColumn: function () { return lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1; },
                    getText: function () { return output; }
                };
            }
            ts.createTextWriter = createTextWriter;
            function getOwnEmitOutputFilePath(sourceFile, host, extension) {
                var compilerOptions = host.getCompilerOptions();
                var emitOutputFilePathWithoutExtension;
                if (compilerOptions.outDir) {
                    emitOutputFilePathWithoutExtension = ts.removeFileExtension(getSourceFilePathInNewDir(sourceFile, host, compilerOptions.outDir));
                }
                else {
                    emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.fileName);
                }
                return emitOutputFilePathWithoutExtension + extension;
            }
            ts.getOwnEmitOutputFilePath = getOwnEmitOutputFilePath;
            function getSourceFilePathInNewDir(sourceFile, host, newDirPath) {
                var sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, host.getCurrentDirectory());
                sourceFilePath = sourceFilePath.replace(host.getCommonSourceDirectory(), "");
                return ts.combinePaths(newDirPath, sourceFilePath);
            }
            ts.getSourceFilePathInNewDir = getSourceFilePathInNewDir;
            function writeFile(host, diagnostics, fileName, data, writeByteOrderMark) {
                host.writeFile(fileName, data, writeByteOrderMark, function (hostErrorMessage) {
                    diagnostics.push(ts.createCompilerDiagnostic(ts.Diagnostics.Could_not_write_file_0_Colon_1, fileName, hostErrorMessage));
                });
            }
            ts.writeFile = writeFile;
            function getLineOfLocalPosition(currentSourceFile, pos) {
                return ts.getLineAndCharacterOfPosition(currentSourceFile, pos).line;
            }
            ts.getLineOfLocalPosition = getLineOfLocalPosition;
            function getFirstConstructorWithBody(node) {
                return ts.forEach(node.members, function (member) {
                    if (member.kind === 135 /* Constructor */ && nodeIsPresent(member.body)) {
                        return member;
                    }
                });
            }
            ts.getFirstConstructorWithBody = getFirstConstructorWithBody;
            function shouldEmitToOwnFile(sourceFile, compilerOptions) {
                if (!isDeclarationFile(sourceFile)) {
                    if ((isExternalModule(sourceFile) || !compilerOptions.out) && !ts.fileExtensionIs(sourceFile.fileName, ".js")) {
                        return true;
                    }
                    return false;
                }
                return false;
            }
            ts.shouldEmitToOwnFile = shouldEmitToOwnFile;
            function getAllAccessorDeclarations(declarations, accessor) {
                var firstAccessor;
                var secondAccessor;
                var getAccessor;
                var setAccessor;
                if (hasDynamicName(accessor)) {
                    firstAccessor = accessor;
                    if (accessor.kind === 136 /* GetAccessor */) {
                        getAccessor = accessor;
                    }
                    else if (accessor.kind === 137 /* SetAccessor */) {
                        setAccessor = accessor;
                    }
                    else {
                        ts.Debug.fail("Accessor has wrong kind");
                    }
                }
                else {
                    ts.forEach(declarations, function (member) {
                        if ((member.kind === 136 /* GetAccessor */ || member.kind === 137 /* SetAccessor */)
                            && (member.flags & 128 /* Static */) === (accessor.flags & 128 /* Static */)) {
                            var memberName = getPropertyNameForPropertyNameNode(member.name);
                            var accessorName = getPropertyNameForPropertyNameNode(accessor.name);
                            if (memberName === accessorName) {
                                if (!firstAccessor) {
                                    firstAccessor = member;
                                }
                                else if (!secondAccessor) {
                                    secondAccessor = member;
                                }
                                if (member.kind === 136 /* GetAccessor */ && !getAccessor) {
                                    getAccessor = member;
                                }
                                if (member.kind === 137 /* SetAccessor */ && !setAccessor) {
                                    setAccessor = member;
                                }
                            }
                        }
                    });
                }
                return {
                    firstAccessor: firstAccessor,
                    secondAccessor: secondAccessor,
                    getAccessor: getAccessor,
                    setAccessor: setAccessor
                };
            }
            ts.getAllAccessorDeclarations = getAllAccessorDeclarations;
            function emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments) {
                // If the leading comments start on different line than the start of node, write new line
                if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos &&
                    getLineOfLocalPosition(currentSourceFile, node.pos) !== getLineOfLocalPosition(currentSourceFile, leadingComments[0].pos)) {
                    writer.writeLine();
                }
            }
            ts.emitNewLineBeforeLeadingComments = emitNewLineBeforeLeadingComments;
            function emitComments(currentSourceFile, writer, comments, trailingSeparator, newLine, writeComment) {
                var emitLeadingSpace = !trailingSeparator;
                ts.forEach(comments, function (comment) {
                    if (emitLeadingSpace) {
                        writer.write(" ");
                        emitLeadingSpace = false;
                    }
                    writeComment(currentSourceFile, writer, comment, newLine);
                    if (comment.hasTrailingNewLine) {
                        writer.writeLine();
                    }
                    else if (trailingSeparator) {
                        writer.write(" ");
                    }
                    else {
                        // Emit leading space to separate comment during next comment emit
                        emitLeadingSpace = true;
                    }
                });
            }
            ts.emitComments = emitComments;
            function writeCommentRange(currentSourceFile, writer, comment, newLine) {
                if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 42 /* asterisk */) {
                    var firstCommentLineAndCharacter = ts.getLineAndCharacterOfPosition(currentSourceFile, comment.pos);
                    var lineCount = ts.getLineStarts(currentSourceFile).length;
                    var firstCommentLineIndent;
                    for (var pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) {
                        var nextLineStart = (currentLine + 1) === lineCount
                            ? currentSourceFile.text.length + 1
                            : getStartPositionOfLine(currentLine + 1, currentSourceFile);
                        if (pos !== comment.pos) {
                            // If we are not emitting first line, we need to write the spaces to adjust the alignment
                            if (firstCommentLineIndent === undefined) {
                                firstCommentLineIndent = calculateIndent(getStartPositionOfLine(firstCommentLineAndCharacter.line, currentSourceFile), comment.pos);
                            }
                            // These are number of spaces writer is going to write at current indent
                            var currentWriterIndentSpacing = writer.getIndent() * getIndentSize();
                            // Number of spaces we want to be writing
                            // eg: Assume writer indent
                            // module m {
                            //         /* starts at character 9 this is line 1
                            //    * starts at character pos 4 line                        --1  = 8 - 8 + 3
                            //   More left indented comment */                            --2  = 8 - 8 + 2
                            //     class c { }
                            // }
                            // module m {
                            //     /* this is line 1 -- Assume current writer indent 8
                            //      * line                                                --3 = 8 - 4 + 5
                            //            More right indented comment */                  --4 = 8 - 4 + 11
                            //     class c { }
                            // }
                            var spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(pos, nextLineStart);
                            if (spacesToEmit > 0) {
                                var numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize();
                                var indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize());
                                // Write indent size string ( in eg 1: = "", 2: "" , 3: string with 8 spaces 4: string with 12 spaces
                                writer.rawWrite(indentSizeSpaceString);
                                // Emit the single spaces (in eg: 1: 3 spaces, 2: 2 spaces, 3: 1 space, 4: 3 spaces)
                                while (numberOfSingleSpacesToEmit) {
                                    writer.rawWrite(" ");
                                    numberOfSingleSpacesToEmit--;
                                }
                            }
                            else {
                                // No spaces to emit write empty string
                                writer.rawWrite("");
                            }
                        }
                        // Write the comment line text
                        writeTrimmedCurrentLine(pos, nextLineStart);
                        pos = nextLineStart;
                    }
                }
                else {
                    // Single line comment of style //....
                    writer.write(currentSourceFile.text.substring(comment.pos, comment.end));
                }
                function writeTrimmedCurrentLine(pos, nextLineStart) {
                    var end = Math.min(comment.end, nextLineStart - 1);
                    var currentLineText = currentSourceFile.text.substring(pos, end).replace(/^\s+|\s+$/g, '');
                    if (currentLineText) {
                        // trimmed forward and ending spaces text
                        writer.write(currentLineText);
                        if (end !== comment.end) {
                            writer.writeLine();
                        }
                    }
                    else {
                        // Empty string - make sure we write empty line
                        writer.writeLiteral(newLine);
                    }
                }
                function calculateIndent(pos, end) {
                    var currentLineIndent = 0;
                    for (; pos < end && ts.isWhiteSpace(currentSourceFile.text.charCodeAt(pos)); pos++) {
                        if (currentSourceFile.text.charCodeAt(pos) === 9 /* tab */) {
                            // Tabs = TabSize = indent size and go to next tabStop
                            currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize());
                        }
                        else {
                            // Single space
                            currentLineIndent++;
                        }
                    }
                    return currentLineIndent;
                }
            }
            ts.writeCommentRange = writeCommentRange;
            function modifierToFlag(token) {
                switch (token) {
                    case 109 /* StaticKeyword */: return 128 /* Static */;
                    case 108 /* PublicKeyword */: return 16 /* Public */;
                    case 107 /* ProtectedKeyword */: return 64 /* Protected */;
                    case 106 /* PrivateKeyword */: return 32 /* Private */;
                    case 78 /* ExportKeyword */: return 1 /* Export */;
                    case 115 /* DeclareKeyword */: return 2 /* Ambient */;
                    case 70 /* ConstKeyword */: return 8192 /* Const */;
                    case 73 /* DefaultKeyword */: return 256 /* Default */;
                }
                return 0;
            }
            ts.modifierToFlag = modifierToFlag;
            function isLeftHandSideExpression(expr) {
                if (expr) {
                    switch (expr.kind) {
                        case 155 /* PropertyAccessExpression */:
                        case 156 /* ElementAccessExpression */:
                        case 158 /* NewExpression */:
                        case 157 /* CallExpression */:
                        case 159 /* TaggedTemplateExpression */:
                        case 153 /* ArrayLiteralExpression */:
                        case 161 /* ParenthesizedExpression */:
                        case 154 /* ObjectLiteralExpression */:
                        case 174 /* ClassExpression */:
                        case 162 /* FunctionExpression */:
                        case 65 /* Identifier */:
                        case 9 /* RegularExpressionLiteral */:
                        case 7 /* NumericLiteral */:
                        case 8 /* StringLiteral */:
                        case 10 /* NoSubstitutionTemplateLiteral */:
                        case 171 /* TemplateExpression */:
                        case 80 /* FalseKeyword */:
                        case 89 /* NullKeyword */:
                        case 93 /* ThisKeyword */:
                        case 95 /* TrueKeyword */:
                        case 91 /* SuperKeyword */:
                            return true;
                    }
                }
                return false;
            }
            ts.isLeftHandSideExpression = isLeftHandSideExpression;
            function isAssignmentOperator(token) {
                return token >= 53 /* FirstAssignment */ && token <= 64 /* LastAssignment */;
            }
            ts.isAssignmentOperator = isAssignmentOperator;
            // Returns false if this heritage clause element's expression contains something unsupported
            // (i.e. not a name or dotted name).
            function isSupportedHeritageClauseElement(node) {
                return isSupportedHeritageClauseElementExpression(node.expression);
            }
            ts.isSupportedHeritageClauseElement = isSupportedHeritageClauseElement;
            function isSupportedHeritageClauseElementExpression(node) {
                if (node.kind === 65 /* Identifier */) {
                    return true;
                }
                else if (node.kind === 155 /* PropertyAccessExpression */) {
                    return isSupportedHeritageClauseElementExpression(node.expression);
                }
                else {
                    return false;
                }
            }
            function isRightSideOfQualifiedNameOrPropertyAccess(node) {
                return (node.parent.kind === 126 /* QualifiedName */ && node.parent.right === node) ||
                    (node.parent.kind === 155 /* PropertyAccessExpression */ && node.parent.name === node);
            }
            ts.isRightSideOfQualifiedNameOrPropertyAccess = isRightSideOfQualifiedNameOrPropertyAccess;
            function getLocalSymbolForExportDefault(symbol) {
                return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & 256 /* Default */) ? symbol.valueDeclaration.localSymbol : undefined;
            }
            ts.getLocalSymbolForExportDefault = getLocalSymbolForExportDefault;
        })(ts || (ts = {}));
        var ts;
        (function (ts) {
            function getDefaultLibFileName(options) {
                return options.target === 2 /* ES6 */ ? "lib.es6.d.ts" : "lib.d.ts";
            }
            ts.getDefaultLibFileName = getDefaultLibFileName;
            function textSpanEnd(span) {
                return span.start + span.length;
            }
            ts.textSpanEnd = textSpanEnd;
            function textSpanIsEmpty(span) {
                return span.length === 0;
            }
            ts.textSpanIsEmpty = textSpanIsEmpty;
            function textSpanContainsPosition(span, position) {
                return position >= span.start && position < textSpanEnd(span);
            }
            ts.textSpanContainsPosition = textSpanContainsPosition;
            // Returns true if 'span' contains 'other'.
            function textSpanContainsTextSpan(span, other) {
                return other.start >= span.start && textSpanEnd(other) <= textSpanEnd(span);
            }
            ts.textSpanContainsTextSpan = textSpanContainsTextSpan;
            function textSpanOverlapsWith(span, other) {
                var overlapStart = Math.max(span.start, other.start);
                var overlapEnd = Math.min(textSpanEnd(span), textSpanEnd(other));
                return overlapStart < overlapEnd;
            }
            ts.textSpanOverlapsWith = textSpanOverlapsWith;
            function textSpanOverlap(span1, span2) {
                var overlapStart = Math.max(span1.start, span2.start);
                var overlapEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
                if (overlapStart < overlapEnd) {
                    return createTextSpanFromBounds(overlapStart, overlapEnd);
                }
                return undefined;
            }
            ts.textSpanOverlap = textSpanOverlap;
            function textSpanIntersectsWithTextSpan(span, other) {
                return other.start <= textSpanEnd(span) && textSpanEnd(other) >= span.start;
            }
            ts.textSpanIntersectsWithTextSpan = textSpanIntersectsWithTextSpan;
            function textSpanIntersectsWith(span, start, length) {
                var end = start + length;
                return start <= textSpanEnd(span) && end >= span.start;
            }
            ts.textSpanIntersectsWith = textSpanIntersectsWith;
            function textSpanIntersectsWithPosition(span, position) {
                return position <= textSpanEnd(span) && position >= span.start;
            }
            ts.textSpanIntersectsWithPosition = textSpanIntersectsWithPosition;
            function textSpanIntersection(span1, span2) {
                var intersectStart = Math.max(span1.start, span2.start);
                var intersectEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
                if (intersectStart <= intersectEnd) {
                    return createTextSpanFromBounds(intersectStart, intersectEnd);
                }
                return undefined;
            }
            ts.textSpanIntersection = textSpanIntersection;
            function createTextSpan(start, length) {
                if (start < 0) {
                    throw new Error("start < 0");
                }
                if (length < 0) {
                    throw new Error("length < 0");
                }
                return { start: start, length: length };
            }
            ts.createTextSpan = createTextSpan;
            function createTextSpanFromBounds(start, end) {
                return createTextSpan(start, end - start);
            }
            ts.createTextSpanFromBounds = createTextSpanFromBounds;
            function textChangeRangeNewSpan(range) {
                return createTextSpan(range.span.start, range.newLength);
            }
            ts.textChangeRangeNewSpan = textChangeRangeNewSpan;
            function textChangeRangeIsUnchanged(range) {
                return textSpanIsEmpty(range.span) && range.newLength === 0;
            }
            ts.textChangeRangeIsUnchanged = textChangeRangeIsUnchanged;
            function createTextChangeRange(span, newLength) {
                if (newLength < 0) {
                    throw new Error("newLength < 0");
                }
                return { span: span, newLength: newLength };
            }
            ts.createTextChangeRange = createTextChangeRange;
            ts.unchangedTextChangeRange = createTextChangeRange(createTextSpan(0, 0), 0);
            /**
             * Called to merge all the changes that occurred across several versions of a script snapshot
             * into a single change.  i.e. if a user keeps making successive edits to a script we will
             * have a text change from V1 to V2, V2 to V3, ..., Vn.
             *
             * This function will then merge those changes into a single change range valid between V1 and
             * Vn.
             */
            function collapseTextChangeRangesAcrossMultipleVersions(changes) {
                if (changes.length === 0) {
                    return ts.unchangedTextChangeRange;
                }
                if (changes.length === 1) {
                    return changes[0];
                }
                // We change from talking about { { oldStart, oldLength }, newLength } to { oldStart, oldEnd, newEnd }
                // as it makes things much easier to reason about.
                var change0 = changes[0];
                var oldStartN = change0.span.start;
                var oldEndN = textSpanEnd(change0.span);
                var newEndN = oldStartN + change0.newLength;
                for (var i = 1; i < changes.length; i++) {
                    var nextChange = changes[i];
                    // Consider the following case:
                    // i.e. two edits.  The first represents the text change range { { 10, 50 }, 30 }.  i.e. The span starting
                    // at 10, with length 50 is reduced to length 30.  The second represents the text change range { { 30, 30 }, 40 }.
                    // i.e. the span starting at 30 with length 30 is increased to length 40.
                    //
                    //      0         10        20        30        40        50        60        70        80        90        100
                    //      -------------------------------------------------------------------------------------------------------
                    //                |                                                 /                                          
                    //                |                                            /----                                           
                    //  T1            |                                       /----                                                
                    //                |                                  /----                                                     
                    //                |                             /----                                                          
                    //      -------------------------------------------------------------------------------------------------------
                    //                                     |                            \                                          
                    //                                     |                               \                                       
                    //   T2                                |                                 \                                     
                    //                                     |                                   \                                   
                    //                                     |                                      \                                
                    //      -------------------------------------------------------------------------------------------------------
                    //
                    // Merging these turns out to not be too difficult.  First, determining the new start of the change is trivial
                    // it's just the min of the old and new starts.  i.e.:
                    //
                    //      0         10        20        30        40        50        60        70        80        90        100
                    //      ------------------------------------------------------------*------------------------------------------
                    //                |                                                 /                                          
                    //                |                                            /----                                           
                    //  T1            |                                       /----                                                
                    //                |                                  /----                                                     
                    //                |                             /----                                                          
                    //      ----------------------------------------$-------------------$------------------------------------------
                    //                .                    |                            \                                          
                    //                .                    |                               \                                       
                    //   T2           .                    |                                 \                                     
                    //                .                    |                                   \                                   
                    //                .                    |                                      \                                
                    //      ----------------------------------------------------------------------*--------------------------------
                    //
                    // (Note the dots represent the newly inferrred start.
                    // Determining the new and old end is also pretty simple.  Basically it boils down to paying attention to the
                    // absolute positions at the asterixes, and the relative change between the dollar signs. Basically, we see
                    // which if the two $'s precedes the other, and we move that one forward until they line up.  in this case that
                    // means:
                    //
                    //      0         10        20        30        40        50        60        70        80        90        100
                    //      --------------------------------------------------------------------------------*----------------------
                    //                |                                                                     /                      
                    //                |                                                                /----                       
                    //  T1            |                                                           /----                            
                    //                |                                                      /----                                 
                    //                |                                                 /----                                      
                    //      ------------------------------------------------------------$------------------------------------------
                    //                .                    |                            \                                          
                    //                .                    |                               \                                       
                    //   T2           .                    |                                 \                                     
                    //                .                    |                                   \                                   
                    //                .                    |                                      \                                
                    //      ----------------------------------------------------------------------*--------------------------------
                    //
                    // In other words (in this case), we're recognizing that the second edit happened after where the first edit
                    // ended with a delta of 20 characters (60 - 40).  Thus, if we go back in time to where the first edit started
                    // that's the same as if we started at char 80 instead of 60.  
                    //
                    // As it so happens, the same logic applies if the second edit precedes the first edit.  In that case rahter
                    // than pusing the first edit forward to match the second, we'll push the second edit forward to match the
                    // first.
                    //
                    // In this case that means we have { oldStart: 10, oldEnd: 80, newEnd: 70 } or, in TextChangeRange
                    // semantics: { { start: 10, length: 70 }, newLength: 60 }
                    //
                    // The math then works out as follows.
                    // If we have { oldStart1, oldEnd1, newEnd1 } and { oldStart2, oldEnd2, newEnd2 } then we can compute the 
                    // final result like so:
                    //
                    // {
                    //      oldStart3: Min(oldStart1, oldStart2),
                    //      oldEnd3  : Max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)),
                    //      newEnd3  : Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2))
                    // }
                    var oldStart1 = oldStartN;
                    var oldEnd1 = oldEndN;
                    var newEnd1 = newEndN;
                    var oldStart2 = nextChange.span.start;
                    var oldEnd2 = textSpanEnd(nextChange.span);
                    var newEnd2 = oldStart2 + nextChange.newLength;
                    oldStartN = Math.min(oldStart1, oldStart2);
                    oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1));
                    newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2));
                }
                return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), newEndN - oldStartN);
            }
            ts.collapseTextChangeRangesAcrossMultipleVersions = collapseTextChangeRangesAcrossMultipleVersions;
        })(ts || (ts = {}));
        /// <reference path="scanner.ts"/>
        /// <reference path="utilities.ts"/>
        var ts;
        (function (ts) {
            var nodeConstructors = new Array(229 /* Count */);
            /* @internal */ ts.parseTime = 0;
            function getNodeConstructor(kind) {
                return nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind));
            }
            ts.getNodeConstructor = getNodeConstructor;
            function createNode(kind) {
                return new (getNodeConstructor(kind))();
            }
            ts.createNode = createNode;
            function visitNode(cbNode, node) {
                if (node) {
                    return cbNode(node);
                }
            }
            function visitNodeArray(cbNodes, nodes) {
                if (nodes) {
                    return cbNodes(nodes);
                }
            }
            function visitEachNode(cbNode, nodes) {
                if (nodes) {
                    for (var _i = 0; _i < nodes.length; _i++) {
                        var node = nodes[_i];
                        var result = cbNode(node);
                        if (result) {
                            return result;
                        }
                    }
                }
            }
            // Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
            // stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
            // embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
            // a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
            function forEachChild(node, cbNode, cbNodeArray) {
                if (!node) {
                    return;
                }
                // The visitXXX functions could be written as local functions that close over the cbNode and cbNodeArray
                // callback parameters, but that causes a closure allocation for each invocation with noticeable effects
                // on performance.
                var visitNodes = cbNodeArray ? visitNodeArray : visitEachNode;
                var cbNodes = cbNodeArray || cbNode;
                switch (node.kind) {
                    case 126 /* QualifiedName */:
                        return visitNode(cbNode, node.left) ||
                            visitNode(cbNode, node.right);
                    case 128 /* TypeParameter */:
                        return visitNode(cbNode, node.name) ||
                            visitNode(cbNode, node.constraint) ||
                            visitNode(cbNode, node.expression);
                    case 129 /* Parameter */:
                    case 132 /* PropertyDeclaration */:
                    case 131 /* PropertySignature */:
                    case 224 /* PropertyAssignment */:
                    case 225 /* ShorthandPropertyAssignment */:
                    case 198 /* VariableDeclaration */:
                    case 152 /* BindingElement */:
                        return visitNodes(cbNodes, node.decorators) ||
                            visitNodes(cbNodes, node.modifiers) ||
                            visitNode(cbNode, node.propertyName) ||
                            visitNode(cbNode, node.dotDotDotToken) ||
                            visitNode(cbNode, node.name) ||
                            visitNode(cbNode, node.questionToken) ||
                            visitNode(cbNode, node.type) ||
                            visitNode(cbNode, node.initializer);
                    case 142 /* FunctionType */:
                    case 143 /* ConstructorType */:
                    case 138 /* CallSignature */:
                    case 139 /* ConstructSignature */:
                    case 140 /* IndexSignature */:
                        return visitNodes(cbNodes, node.decorators) ||
                            visitNodes(cbNodes, node.modifiers) ||
                            visitNodes(cbNodes, node.typeParameters) ||
                            visitNodes(cbNodes, node.parameters) ||
                            visitNode(cbNode, node.type);
                    case 134 /* MethodDeclaration */:
                    case 133 /* MethodSignature */:
                    case 135 /* Constructor */:
                    case 136 /* GetAccessor */:
                    case 137 /* SetAccessor */:
                    case 162 /* FunctionExpression */:
                    case 200 /* FunctionDeclaration */:
                    case 163 /* ArrowFunction */:
                        return visitNodes(cbNodes, node.decorators) ||
                            visitNodes(cbNodes, node.modifiers) ||
                            visitNode(cbNode, node.asteriskToken) ||
                            visitNode(cbNode, node.name) ||
                            visitNode(cbNode, node.questionToken) ||
                            visitNodes(cbNodes, node.typeParameters) ||
                            visitNodes(cbNodes, node.parameters) ||
                            visitNode(cbNode, node.type) ||
                            visitNode(cbNode, node.equalsGreaterThanToken) ||
                            visitNode(cbNode, node.body);
                    case 141 /* TypeReference */:
                        return visitNode(cbNode, node.typeName) ||
                            visitNodes(cbNodes, node.typeArguments);
                    case 144 /* TypeQuery */:
                        return visitNode(cbNode, node.exprName);
                    case 145 /* TypeLiteral */:
                        return visitNodes(cbNodes, node.members);
                    case 146 /* ArrayType */:
                        return visitNode(cbNode, node.elementType);
                    case 147 /* TupleType */:
                        return visitNodes(cbNodes, node.elementTypes);
                    case 148 /* UnionType */:
                        return visitNodes(cbNodes, node.types);
                    case 149 /* ParenthesizedType */:
                        return visitNode(cbNode, node.type);
                    case 150 /* ObjectBindingPattern */:
                    case 151 /* ArrayBindingPattern */:
                        return visitNodes(cbNodes, node.elements);
                    case 153 /* ArrayLiteralExpression */:
                        return visitNodes(cbNodes, node.elements);
                    case 154 /* ObjectLiteralExpression */:
                        return visitNodes(cbNodes, node.properties);
                    case 155 /* PropertyAccessExpression */:
                        return visitNode(cbNode, node.expression) ||
                            visitNode(cbNode, node.dotToken) ||
                            visitNode(cbNode, node.name);
                    case 156 /* ElementAccessExpression */:
                        return visitNode(cbNode, node.expression) ||
                            visitNode(cbNode, node.argumentExpression);
                    case 157 /* CallExpression */:
                    case 158 /* NewExpression */:
                        return visitNode(cbNode, node.expression) ||
                            visitNodes(cbNodes, node.typeArguments) ||
                            visitNodes(cbNodes, node.arguments);
                    case 159 /* TaggedTemplateExpression */:
                        return visitNode(cbNode, node.tag) ||
                            visitNode(cbNode, node.template);
                    case 160 /* TypeAssertionExpression */:
                        return visitNode(cbNode, node.type) ||
                            visitNode(cbNode, node.expression);
                    case 161 /* ParenthesizedExpression */:
                        return visitNode(cbNode, node.expression);
                    case 164 /* DeleteExpression */:
                        return visitNode(cbNode, node.expression);
                    case 165 /* TypeOfExpression */:
                        return visitNode(cbNode, node.expression);
                    case 166 /* VoidExpression */:
                        return visitNode(cbNode, node.expression);
                    case 167 /* PrefixUnaryExpression */:
                        return visitNode(cbNode, node.operand);
                    case 172 /* YieldExpression */:
                        return visitNode(cbNode, node.asteriskToken) ||
                            visitNode(cbNode, node.expression);
                    case 168 /* PostfixUnaryExpression */:
                        return visitNode(cbNode, node.operand);
                    case 169 /* BinaryExpression */:
                        return visitNode(cbNode, node.left) ||
                            visitNode(cbNode, node.operatorToken) ||
                            visitNode(cbNode, node.right);
                    case 170 /* ConditionalExpression */:
                        return visitNode(cbNode, node.condition) ||
                            visitNode(cbNode, node.questionToken) ||
                            visitNode(cbNode, node.whenTrue) ||
                            visitNode(cbNode, node.colonToken) ||
                            visitNode(cbNode, node.whenFalse);
                    case 173 /* SpreadElementExpression */:
                        return visitNode(cbNode, node.expression);
                    case 179 /* Block */:
                    case 206 /* ModuleBlock */:
                        return visitNodes(cbNodes, node.statements);
                    case 227 /* SourceFile */:
                        return visitNodes(cbNodes, node.statements) ||
                            visitNode(cbNode, node.endOfFileToken);
                    case 180 /* VariableStatement */:
                        return visitNodes(cbNodes, node.decorators) ||
                            visitNodes(cbNodes, node.modifiers) ||
                            visitNode(cbNode, node.declarationList);
                    case 199 /* VariableDeclarationList */:
                        return visitNodes(cbNodes, node.declarations);
                    case 182 /* ExpressionStatement */:
                        return visitNode(cbNode, node.expression);
                    case 183 /* IfStatement */:
                        return visitNode(cbNode, node.expression) ||
                            visitNode(cbNode, node.thenStatement) ||
                            visitNode(cbNode, node.elseStatement);
                    case 184 /* DoStatement */:
                        return visitNode(cbNode, node.statement) ||
                            visitNode(cbNode, node.expression);
                    case 185 /* WhileStatement */:
                        return visitNode(cbNode, node.expression) ||
                            visitNode(cbNode, node.statement);
                    case 186 /* ForStatement */:
                        return visitNode(cbNode, node.initializer) ||
                            visitNode(cbNode, node.condition) ||
                            visitNode(cbNode, node.incrementor) ||
                            visitNode(cbNode, node.statement);
                    case 187 /* ForInStatement */:
                        return visitNode(cbNode, node.initializer) ||
                            visitNode(cbNode, node.expression) ||
                            visitNode(cbNode, node.statement);
                    case 188 /* ForOfStatement */:
                        return visitNode(cbNode, node.initializer) ||
                            visitNode(cbNode, node.expression) ||
                            visitNode(cbNode, node.statement);
                    case 189 /* ContinueStatement */:
                    case 190 /* BreakStatement */:
                        return visitNode(cbNode, node.label);
                    case 191 /* ReturnStatement */:
                        return visitNode(cbNode, node.expression);
                    case 192 /* WithStatement */:
                        return visitNode(cbNode, node.expression) ||
                            visitNode(cbNode, node.statement);
                    case 193 /* SwitchStatement */:
                        return visitNode(cbNode, node.expression) ||
                            visitNode(cbNode, node.caseBlock);
                    case 207 /* CaseBlock */:
                        return visitNodes(cbNodes, node.clauses);
                    case 220 /* CaseClause */:
                        return visitNode(cbNode, node.expression) ||
                            visitNodes(cbNodes, node.statements);
                    case 221 /* DefaultClause */:
                        return visitNodes(cbNodes, node.statements);
                    case 194 /* LabeledStatement */:
                        return visitNode(cbNode, node.label) ||
                            visitNode(cbNode, node.statement);
                    case 195 /* ThrowStatement */:
                        return visitNode(cbNode, node.expression);
                    case 196 /* TryStatement */:
                        return visitNode(cbNode, node.tryBlock) ||
                            visitNode(cbNode, node.catchClause) ||
                            visitNode(cbNode, node.finallyBlock);
                    case 223 /* CatchClause */:
                        return visitNode(cbNode, node.variableDeclaration) ||
                            visitNode(cbNode, node.block);
                    case 130 /* Decorator */:
                        return visitNode(cbNode, node.expression);
                    case 201 /* ClassDeclaration */:
                    case 174 /* ClassExpression */:
                        return visitNodes(cbNodes, node.decorators) ||
                            visitNodes(cbNodes, node.modifiers) ||
                            visitNode(cbNode, node.name) ||
                            visitNodes(cbNodes, node.typeParameters) ||
                            visitNodes(cbNodes, node.heritageClauses) ||
                            visitNodes(cbNodes, node.members);
                    case 202 /* InterfaceDeclaration */:
                        return visitNodes(cbNodes, node.decorators) ||
                            visitNodes(cbNodes, node.modifiers) ||
                            visitNode(cbNode, node.name) ||
                            visitNodes(cbNodes, node.typeParameters) ||
                            visitNodes(cbNodes, node.heritageClauses) ||
                            visitNodes(cbNodes, node.members);
                    case 203 /* TypeAliasDeclaration */:
                        return visitNodes(cbNodes, node.decorators) ||
                            visitNodes(cbNodes, node.modifiers) ||
                            visitNode(cbNode, node.name) ||
                            visitNode(cbNode, node.type);
                    case 204 /* EnumDeclaration */:
                        return visitNodes(cbNodes, node.decorators) ||
                            visitNodes(cbNodes, node.modifiers) ||
                            visitNode(cbNode, node.name) ||
                            visitNodes(cbNodes, node.members);
                    case 226 /* EnumMember */:
                        return visitNode(cbNode, node.name) ||
                            visitNode(cbNode, node.initializer);
                    case 205 /* ModuleDeclaration */:
                        return visitNodes(cbNodes, node.decorators) ||
                            visitNodes(cbNodes, node.modifiers) ||
                            visitNode(cbNode, node.name) ||
                            visitNode(cbNode, node.body);
                    case 208 /* ImportEqualsDeclaration */:
                        return visitNodes(cbNodes, node.decorators) ||
                            visitNodes(cbNodes, node.modifiers) ||
                            visitNode(cbNode, node.name) ||
                            visitNode(cbNode, node.moduleReference);
                    case 209 /* ImportDeclaration */:
                        return visitNodes(cbNodes, node.decorators) ||
                            visitNodes(cbNodes, node.modifiers) ||
                            visitNode(cbNode, node.importClause) ||
                            visitNode(cbNode, node.moduleSpecifier);
                    case 210 /* ImportClause */:
                        return visitNode(cbNode, node.name) ||
                            visitNode(cbNode, node.namedBindings);
                    case 211 /* NamespaceImport */:
                        return visitNode(cbNode, node.name);
                    case 212 /* NamedImports */:
                    case 216 /* NamedExports */:
                        return visitNodes(cbNodes, node.elements);
                    case 215 /* ExportDeclaration */:
                        return visitNodes(cbNodes, node.decorators) ||
                            visitNodes(cbNodes, node.modifiers) ||
                            visitNode(cbNode, node.exportClause) ||
                            visitNode(cbNode, node.moduleSpecifier);
                    case 213 /* ImportSpecifier */:
                    case 217 /* ExportSpecifier */:
                        return visitNode(cbNode, node.propertyName) ||
                            visitNode(cbNode, node.name);
                    case 214 /* ExportAssignment */:
                        return visitNodes(cbNodes, node.decorators) ||
                            visitNodes(cbNodes, node.modifiers) ||
                            visitNode(cbNode, node.expression);
                    case 171 /* TemplateExpression */:
                        return visitNode(cbNode, node.head) || visitNodes(cbNodes, node.templateSpans);
                    case 176 /* TemplateSpan */:
                        return visitNode(cbNode, node.expression) || visitNode(cbNode, node.literal);
                    case 127 /* ComputedPropertyName */:
                        return visitNode(cbNode, node.expression);
                    case 222 /* HeritageClause */:
                        return visitNodes(cbNodes, node.types);
                    case 177 /* HeritageClauseElement */:
                        return visitNode(cbNode, node.expression) ||
                            visitNodes(cbNodes, node.typeArguments);
                    case 219 /* ExternalModuleReference */:
                        return visitNode(cbNode, node.expression);
                    case 218 /* MissingDeclaration */:
                        return visitNodes(cbNodes, node.decorators);
                }
            }
            ts.forEachChild = forEachChild;
            function createSourceFile(fileName, sourceText, languageVersion, setParentNodes) {
                if (setParentNodes === void 0) { setParentNodes = false; }
                var start = new Date().getTime();
                var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, undefined, setParentNodes);
                ts.parseTime += new Date().getTime() - start;
                return result;
            }
            ts.createSourceFile = createSourceFile;
            // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter
            // indicates what changed between the 'text' that this SourceFile has and the 'newText'.
            // The SourceFile will be created with the compiler attempting to reuse as many nodes from
            // this file as possible.
            //
            // Note: this function mutates nodes from this SourceFile. That means any existing nodes
            // from this SourceFile that are being held onto may change as a result (including
            // becoming detached from any SourceFile).  It is recommended that this SourceFile not
            // be used once 'update' is called on it.
            function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) {
                return IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
            }
            ts.updateSourceFile = updateSourceFile;
            // Implement the parser as a singleton module.  We do this for perf reasons because creating
            // parser instances can actually be expensive enough to impact us on projects with many source
            // files.
            var Parser;
            (function (Parser) {
                // Share a single scanner across all calls to parse a source file.  This helps speed things
                // up by avoiding the cost of creating/compiling scanners over and over again.
                var scanner = ts.createScanner(2 /* Latest */, true);
                var disallowInAndDecoratorContext = 2 /* DisallowIn */ | 16 /* Decorator */;
                var sourceFile;
                var syntaxCursor;
                var token;
                var sourceText;
                var nodeCount;
                var identifiers;
                var identifierCount;
                var parsingContext;
                // Flags that dictate what parsing context we're in.  For example:
                // Whether or not we are in strict parsing mode.  All that changes in strict parsing mode is
                // that some tokens that would be considered identifiers may be considered keywords.
                //
                // When adding more parser context flags, consider which is the more common case that the
                // flag will be in.  This should be the 'false' state for that flag.  The reason for this is
                // that we don't store data in our nodes unless the value is in the *non-default* state.  So,
                // for example, more often than code 'allows-in' (or doesn't 'disallow-in').  We opt for
                // 'disallow-in' set to 'false'.  Otherwise, if we had 'allowsIn' set to 'true', then almost
                // all nodes would need extra state on them to store this info.
                //
                // Note:  'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6
                // grammar specification.
                //
                // An important thing about these context concepts.  By default they are effectively inherited
                // while parsing through every grammar production.  i.e. if you don't change them, then when
                // you parse a sub-production, it will have the same context values as the parent production.
                // This is great most of the time.  After all, consider all the 'expression' grammar productions
                // and how nearly all of them pass along the 'in' and 'yield' context values:
                //
                // EqualityExpression[In, Yield] :
                //      RelationalExpression[?In, ?Yield]
                //      EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield]
                //      EqualityExpression[?In, ?Yield] != RelationalExpression[?In, ?Yield]
                //      EqualityExpression[?In, ?Yield] === RelationalExpression[?In, ?Yield]
                //      EqualityExpression[?In, ?Yield] !== RelationalExpression[?In, ?Yield]
                //
                // Where you have to be careful is then understanding what the points are in the grammar
                // where the values are *not* passed along.  For example:
                //
                // SingleNameBinding[Yield,GeneratorParameter]
                //      [+GeneratorParameter]BindingIdentifier[Yield] Initializer[In]opt
                //      [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
                //
                // Here this is saying that if the GeneratorParameter context flag is set, that we should
                // explicitly set the 'yield' context flag to false before calling into the BindingIdentifier
                // and we should explicitly unset the 'yield' context flag before calling into the Initializer.
                // production.  Conversely, if the GeneratorParameter context flag is not set, then we
                // should leave the 'yield' context flag alone.
                //
                // Getting this all correct is tricky and requires careful reading of the grammar to
                // understand when these values should be changed versus when they should be inherited.
                //
                // Note: it should not be necessary to save/restore these flags during speculative/lookahead
                // parsing.  These context flags are naturally stored and restored through normal recursive
                // descent parsing and unwinding.
                var contextFlags = 0;
                // Whether or not we've had a parse error since creating the last AST node.  If we have
                // encountered an error, it will be stored on the next AST node we create.  Parse errors
                // can be broken down into three categories:
                //
                // 1) An error that occurred during scanning.  For example, an unterminated literal, or a
                //    character that was completely not understood.
                //
                // 2) A token was expected, but was not present.  This type of error is commonly produced
                //    by the 'parseExpected' function.
                //
                // 3) A token was present that no parsing function was able to consume.  This type of error
                //    only occurs in the 'abortParsingListOrMoveToNextToken' function when the parser
                //    decides to skip the token.
                //
                // In all of these cases, we want to mark the next node as having had an error before it.
                // With this mark, we can know in incremental settings if this node can be reused, or if
                // we have to reparse it.  If we don't keep this information around, we may just reuse the
                // node.  in that event we would then not produce the same errors as we did before, causing
                // significant confusion problems.
                //
                // Note: it is necessary that this value be saved/restored during speculative/lookahead
                // parsing.  During lookahead parsing, we will often create a node.  That node will have
                // this value attached, and then this value will be set back to 'false'.  If we decide to
                // rewind, we must get back to the same value we had prior to the lookahead.
                //
                // Note: any errors at the end of the file that do not precede a regular node, should get
                // attached to the EOF token.
                var parseErrorBeforeNextFinishedNode = false;
                function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes) {
                    sourceText = _sourceText;
                    syntaxCursor = _syntaxCursor;
                    parsingContext = 0;
                    identifiers = {};
                    identifierCount = 0;
                    nodeCount = 0;
                    contextFlags = 0;
                    parseErrorBeforeNextFinishedNode = false;
                    createSourceFile(fileName, languageVersion);
                    // Initialize and prime the scanner before parsing the source elements.
                    scanner.setText(sourceText);
                    scanner.setOnError(scanError);
                    scanner.setScriptTarget(languageVersion);
                    token = nextToken();
                    processReferenceComments(sourceFile);
                    sourceFile.statements = parseList(0 /* SourceElements */, true, parseSourceElement);
                    ts.Debug.assert(token === 1 /* EndOfFileToken */);
                    sourceFile.endOfFileToken = parseTokenNode();
                    setExternalModuleIndicator(sourceFile);
                    sourceFile.nodeCount = nodeCount;
                    sourceFile.identifierCount = identifierCount;
                    sourceFile.identifiers = identifiers;
                    if (setParentNodes) {
                        fixupParentReferences(sourceFile);
                    }
                    syntaxCursor = undefined;
                    // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily.
                    scanner.setText("");
                    scanner.setOnError(undefined);
                    var result = sourceFile;
                    // Clear any data.  We don't want to accidently hold onto it for too long.
                    sourceFile = undefined;
                    identifiers = undefined;
                    syntaxCursor = undefined;
                    sourceText = undefined;
                    return result;
                }
                Parser.parseSourceFile = parseSourceFile;
                function fixupParentReferences(sourceFile) {
                    // normally parent references are set during binding. However, for clients that only need
                    // a syntax tree, and no semantic features, then the binding process is an unnecessary
                    // overhead.  This functions allows us to set all the parents, without all the expense of
                    // binding.
                    var parent = sourceFile;
                    forEachChild(sourceFile, visitNode);
                    return;
                    function visitNode(n) {
                        // walk down setting parents that differ from the parent we think it should be.  This
                        // allows us to quickly bail out of setting parents for subtrees during incremental
                        // parsing
                        if (n.parent !== parent) {
                            n.parent = parent;
                            var saveParent = parent;
                            parent = n;
                            forEachChild(n, visitNode);
                            parent = saveParent;
                        }
                    }
                }
                function createSourceFile(fileName, languageVersion) {
                    sourceFile = createNode(227 /* SourceFile */, 0);
                    sourceFile.pos = 0;
                    sourceFile.end = sourceText.length;
                    sourceFile.text = sourceText;
                    sourceFile.parseDiagnostics = [];
                    sourceFile.bindDiagnostics = [];
                    sourceFile.languageVersion = languageVersion;
                    sourceFile.fileName = ts.normalizePath(fileName);
                    sourceFile.flags = ts.fileExtensionIs(sourceFile.fileName, ".d.ts") ? 2048 /* DeclarationFile */ : 0;
                }
                function setContextFlag(val, flag) {
                    if (val) {
                        contextFlags |= flag;
                    }
                    else {
                        contextFlags &= ~flag;
                    }
                }
                function setStrictModeContext(val) {
                    setContextFlag(val, 1 /* StrictMode */);
                }
                function setDisallowInContext(val) {
                    setContextFlag(val, 2 /* DisallowIn */);
                }
                function setYieldContext(val) {
                    setContextFlag(val, 4 /* Yield */);
                }
                function setGeneratorParameterContext(val) {
                    setContextFlag(val, 8 /* GeneratorParameter */);
                }
                function setDecoratorContext(val) {
                    setContextFlag(val, 16 /* Decorator */);
                }
                function doOutsideOfContext(flags, func) {
                    var currentContextFlags = contextFlags & flags;
                    if (currentContextFlags) {
                        setContextFlag(false, currentContextFlags);
                        var result = func();
                        setContextFlag(true, currentContextFlags);
                        return result;
                    }
                    // no need to do anything special as we are not in any of the requested contexts
                    return func();
                }
                function allowInAnd(func) {
                    if (contextFlags & 2 /* DisallowIn */) {
                        setDisallowInContext(false);
                        var result = func();
                        setDisallowInContext(true);
                        return result;
                    }
                    // no need to do anything special if 'in' is already allowed.
                    return func();
                }
                function disallowInAnd(func) {
                    if (contextFlags & 2 /* DisallowIn */) {
                        // no need to do anything special if 'in' is already disallowed.
                        return func();
                    }
                    setDisallowInContext(true);
                    var result = func();
                    setDisallowInContext(false);
                    return result;
                }
                function doInYieldContext(func) {
                    if (contextFlags & 4 /* Yield */) {
                        // no need to do anything special if we're already in the [Yield] context.
                        return func();
                    }
                    setYieldContext(true);
                    var result = func();
                    setYieldContext(false);
                    return result;
                }
                function doOutsideOfYieldContext(func) {
                    if (contextFlags & 4 /* Yield */) {
                        setYieldContext(false);
                        var result = func();
                        setYieldContext(true);
                        return result;
                    }
                    // no need to do anything special if we're not in the [Yield] context.
                    return func();
                }
                function doInDecoratorContext(func) {
                    if (contextFlags & 16 /* Decorator */) {
                        // no need to do anything special if we're already in the [Decorator] context.
                        return func();
                    }
                    setDecoratorContext(true);
                    var result = func();
                    setDecoratorContext(false);
                    return result;
                }
                function inYieldContext() {
                    return (contextFlags & 4 /* Yield */) !== 0;
                }
                function inStrictModeContext() {
                    return (contextFlags & 1 /* StrictMode */) !== 0;
                }
                function inGeneratorParameterContext() {
                    return (contextFlags & 8 /* GeneratorParameter */) !== 0;
                }
                function inDisallowInContext() {
                    return (contextFlags & 2 /* DisallowIn */) !== 0;
                }
                function inDecoratorContext() {
                    return (contextFlags & 16 /* Decorator */) !== 0;
                }
                function parseErrorAtCurrentToken(message, arg0) {
                    var start = scanner.getTokenPos();
                    var length = scanner.getTextPos() - start;
                    parseErrorAtPosition(start, length, message, arg0);
                }
                function parseErrorAtPosition(start, length, message, arg0) {
                    // Don't report another error if it would just be at the same position as the last error.
                    var lastError = ts.lastOrUndefined(sourceFile.parseDiagnostics);
                    if (!lastError || start !== lastError.start) {
                        sourceFile.parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, start, length, message, arg0));
                    }
                    // Mark that we've encountered an error.  We'll set an appropriate bit on the next
                    // node we finish so that it can't be reused incrementally.
                    parseErrorBeforeNextFinishedNode = true;
                }
                function scanError(message, length) {
                    var pos = scanner.getTextPos();
                    parseErrorAtPosition(pos, length || 0, message);
                }
                function getNodePos() {
                    return scanner.getStartPos();
                }
                function getNodeEnd() {
                    return scanner.getStartPos();
                }
                function nextToken() {
                    return token = scanner.scan();
                }
                function getTokenPos(pos) {
                    return ts.skipTrivia(sourceText, pos);
                }
                function reScanGreaterToken() {
                    return token = scanner.reScanGreaterToken();
                }
                function reScanSlashToken() {
                    return token = scanner.reScanSlashToken();
                }
                function reScanTemplateToken() {
                    return token = scanner.reScanTemplateToken();
                }
                function speculationHelper(callback, isLookAhead) {
                    // Keep track of the state we'll need to rollback to if lookahead fails (or if the
                    // caller asked us to always reset our state).
                    var saveToken = token;
                    var saveParseDiagnosticsLength = sourceFile.parseDiagnostics.length;
                    var saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
                    // Note: it is not actually necessary to save/restore the context flags here.  That's
                    // because the saving/restorating of these flags happens naturally through the recursive
                    // descent nature of our parser.  However, we still store this here just so we can
                    // assert that that invariant holds.
                    var saveContextFlags = contextFlags;
                    // If we're only looking ahead, then tell the scanner to only lookahead as well.
                    // Otherwise, if we're actually speculatively parsing, then tell the scanner to do the
                    // same.
                    var result = isLookAhead
                        ? scanner.lookAhead(callback)
                        : scanner.tryScan(callback);
                    ts.Debug.assert(saveContextFlags === contextFlags);
                    // If our callback returned something 'falsy' or we're just looking ahead,
                    // then unconditionally restore us to where we were.
                    if (!result || isLookAhead) {
                        token = saveToken;
                        sourceFile.parseDiagnostics.length = saveParseDiagnosticsLength;
                        parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode;
                    }
                    return result;
                }
                // Invokes the provided callback then unconditionally restores the parser to the state it
                // was in immediately prior to invoking the callback.  The result of invoking the callback
                // is returned from this function.
                function lookAhead(callback) {
                    return speculationHelper(callback, true);
                }
                // Invokes the provided callback.  If the callback returns something falsy, then it restores
                // the parser to the state it was in immediately prior to invoking the callback.  If the
                // callback returns something truthy, then the parser state is not rolled back.  The result
                // of invoking the callback is returned from this function.
                function tryParse(callback) {
                    return speculationHelper(callback, false);
                }
                // Ignore strict mode flag because we will report an error in type checker instead.
                function isIdentifier() {
                    if (token === 65 /* Identifier */) {
                        return true;
                    }
                    // If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is
                    // considered a keyword and is not an identifier.
                    if (token === 110 /* YieldKeyword */ && inYieldContext()) {
                        return false;
                    }
                    return token > 101 /* LastReservedWord */;
                }
                function parseExpected(kind, diagnosticMessage) {
                    if (token === kind) {
                        nextToken();
                        return true;
                    }
                    // Report specific message if provided with one.  Otherwise, report generic fallback message.
                    if (diagnosticMessage) {
                        parseErrorAtCurrentToken(diagnosticMessage);
                    }
                    else {
                        parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(kind));
                    }
                    return false;
                }
                function parseOptional(t) {
                    if (token === t) {
                        nextToken();
                        return true;
                    }
                    return false;
                }
                function parseOptionalToken(t) {
                    if (token === t) {
                        return parseTokenNode();
                    }
                    return undefined;
                }
                function parseExpectedToken(t, reportAtCurrentPosition, diagnosticMessage, arg0) {
                    return parseOptionalToken(t) ||
                        createMissingNode(t, reportAtCurrentPosition, diagnosticMessage, arg0);
                }
                function parseTokenNode() {
                    var node = createNode(token);
                    nextToken();
                    return finishNode(node);
                }
                function canParseSemicolon() {
                    // If there's a real semicolon, then we can always parse it out.
                    if (token === 22 /* SemicolonToken */) {
                        return true;
                    }
                    // We can parse out an optional semicolon in ASI cases in the following cases.
                    return token === 15 /* CloseBraceToken */ || token === 1 /* EndOfFileToken */ || scanner.hasPrecedingLineBreak();
                }
                function parseSemicolon() {
                    if (canParseSemicolon()) {
                        if (token === 22 /* SemicolonToken */) {
                            // consume the semicolon if it was explicitly provided.
                            nextToken();
                        }
                        return true;
                    }
                    else {
                        return parseExpected(22 /* SemicolonToken */);
                    }
                }
                function createNode(kind, pos) {
                    nodeCount++;
                    var node = new (nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind)))();
                    if (!(pos >= 0)) {
                        pos = scanner.getStartPos();
                    }
                    node.pos = pos;
                    node.end = pos;
                    return node;
                }
                function finishNode(node) {
                    node.end = scanner.getStartPos();
                    if (contextFlags) {
                        node.parserContextFlags = contextFlags;
                    }
                    // Keep track on the node if we encountered an error while parsing it.  If we did, then
                    // we cannot reuse the node incrementally.  Once we've marked this node, clear out the
                    // flag so that we don't mark any subsequent nodes.
                    if (parseErrorBeforeNextFinishedNode) {
                        parseErrorBeforeNextFinishedNode = false;
                        node.parserContextFlags |= 32 /* ThisNodeHasError */;
                    }
                    return node;
                }
                function createMissingNode(kind, reportAtCurrentPosition, diagnosticMessage, arg0) {
                    if (reportAtCurrentPosition) {
                        parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0);
                    }
                    else {
                        parseErrorAtCurrentToken(diagnosticMessage, arg0);
                    }
                    var result = createNode(kind, scanner.getStartPos());
                    result.text = "";
                    return finishNode(result);
                }
                function internIdentifier(text) {
                    text = ts.escapeIdentifier(text);
                    return ts.hasProperty(identifiers, text) ? identifiers[text] : (identifiers[text] = text);
                }
                // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues
                // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for
                // each identifier in order to reduce memory consumption.
                function createIdentifier(isIdentifier, diagnosticMessage) {
                    identifierCount++;
                    if (isIdentifier) {
                        var node = createNode(65 /* Identifier */);
                        // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker
                        if (token !== 65 /* Identifier */) {
                            node.originalKeywordKind = token;
                        }
                        node.text = internIdentifier(scanner.getTokenValue());
                        nextToken();
                        return finishNode(node);
                    }
                    return createMissingNode(65 /* Identifier */, false, diagnosticMessage || ts.Diagnostics.Identifier_expected);
                }
                function parseIdentifier(diagnosticMessage) {
                    return createIdentifier(isIdentifier(), diagnosticMessage);
                }
                function parseIdentifierName() {
                    return createIdentifier(isIdentifierOrKeyword());
                }
                function isLiteralPropertyName() {
                    return isIdentifierOrKeyword() ||
                        token === 8 /* StringLiteral */ ||
                        token === 7 /* NumericLiteral */;
                }
                function parsePropertyName() {
                    if (token === 8 /* StringLiteral */ || token === 7 /* NumericLiteral */) {
                        return parseLiteralNode(true);
                    }
                    if (token === 18 /* OpenBracketToken */) {
                        return parseComputedPropertyName();
                    }
                    return parseIdentifierName();
                }
                function parseComputedPropertyName() {
                    // PropertyName[Yield,GeneratorParameter] :
                    //     LiteralPropertyName
                    //     [+GeneratorParameter] ComputedPropertyName
                    //     [~GeneratorParameter] ComputedPropertyName[?Yield]
                    //
                    // ComputedPropertyName[Yield] :
                    //     [ AssignmentExpression[In, ?Yield] ]
                    //
                    var node = createNode(127 /* ComputedPropertyName */);
                    parseExpected(18 /* OpenBracketToken */);
                    // We parse any expression (including a comma expression). But the grammar
                    // says that only an assignment expression is allowed, so the grammar checker
                    // will error if it sees a comma expression.
                    var yieldContext = inYieldContext();
                    if (inGeneratorParameterContext()) {
                        setYieldContext(false);
                    }
                    node.expression = allowInAnd(parseExpression);
                    if (inGeneratorParameterContext()) {
                        setYieldContext(yieldContext);
                    }
                    parseExpected(19 /* CloseBracketToken */);
                    return finishNode(node);
                }
                function parseContextualModifier(t) {
                    return token === t && tryParse(nextTokenCanFollowModifier);
                }
                function nextTokenCanFollowModifier() {
                    nextToken();
                    return canFollowModifier();
                }
                function parseAnyContextualModifier() {
                    return ts.isModifier(token) && tryParse(nextTokenCanFollowContextualModifier);
                }
                function nextTokenCanFollowContextualModifier() {
                    if (token === 70 /* ConstKeyword */) {
                        // 'const' is only a modifier if followed by 'enum'.
                        return nextToken() === 77 /* EnumKeyword */;
                    }
                    if (token === 78 /* ExportKeyword */) {
                        nextToken();
                        if (token === 73 /* DefaultKeyword */) {
                            return lookAhead(nextTokenIsClassOrFunction);
                        }
                        return token !== 35 /* AsteriskToken */ && token !== 14 /* OpenBraceToken */ && canFollowModifier();
                    }
                    if (token === 73 /* DefaultKeyword */) {
                        return nextTokenIsClassOrFunction();
                    }
                    nextToken();
                    return canFollowModifier();
                }
                function canFollowModifier() {
                    return token === 18 /* OpenBracketToken */
                        || token === 14 /* OpenBraceToken */
                        || token === 35 /* AsteriskToken */
                        || isLiteralPropertyName();
                }
                function nextTokenIsClassOrFunction() {
                    nextToken();
                    return token === 69 /* ClassKeyword */ || token === 83 /* FunctionKeyword */;
                }
                // True if positioned at the start of a list element
                function isListElement(parsingContext, inErrorRecovery) {
                    var node = currentNode(parsingContext);
                    if (node) {
                        return true;
                    }
                    switch (parsingContext) {
                        case 0 /* SourceElements */:
                        case 1 /* ModuleElements */:
                            return isSourceElement(inErrorRecovery);
                        case 2 /* BlockStatements */:
                        case 4 /* SwitchClauseStatements */:
                            return isStartOfStatement(inErrorRecovery);
                        case 3 /* SwitchClauses */:
                            return token === 67 /* CaseKeyword */ || token === 73 /* DefaultKeyword */;
                        case 5 /* TypeMembers */:
                            return isStartOfTypeMember();
                        case 6 /* ClassMembers */:
                            // We allow semicolons as class elements (as specified by ES6) as long as we're
                            // not in error recovery.  If we're in error recovery, we don't want an errant
                            // semicolon to be treated as a class member (since they're almost always used
                            // for statements.
                            return lookAhead(isClassMemberStart) || (token === 22 /* SemicolonToken */ && !inErrorRecovery);
                        case 7 /* EnumMembers */:
                            // Include open bracket computed properties. This technically also lets in indexers,
                            // which would be a candidate for improved error reporting.
                            return token === 18 /* OpenBracketToken */ || isLiteralPropertyName();
                        case 13 /* ObjectLiteralMembers */:
                            return token === 18 /* OpenBracketToken */ || token === 35 /* AsteriskToken */ || isLiteralPropertyName();
                        case 10 /* ObjectBindingElements */:
                            return isLiteralPropertyName();
                        case 8 /* HeritageClauseElement */:
                            // If we see { } then only consume it as an expression if it is followed by , or {
                            // That way we won't consume the body of a class in its heritage clause.
                            if (token === 14 /* OpenBraceToken */) {
                                return lookAhead(isValidHeritageClauseObjectLiteral);
                            }
                            if (!inErrorRecovery) {
                                return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword();
                            }
                            else {
                                // If we're in error recovery we tighten up what we're willing to match.
                                // That way we don't treat something like "this" as a valid heritage clause
                                // element during recovery.
                                return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword();
                            }
                        case 9 /* VariableDeclarations */:
                            return isIdentifierOrPattern();
                        case 11 /* ArrayBindingElements */:
                            return token === 23 /* CommaToken */ || token === 21 /* DotDotDotToken */ || isIdentifierOrPattern();
                        case 16 /* TypeParameters */:
                            return isIdentifier();
                        case 12 /* ArgumentExpressions */:
                        case 14 /* ArrayLiteralMembers */:
                            return token === 23 /* CommaToken */ || token === 21 /* DotDotDotToken */ || isStartOfExpression();
                        case 15 /* Parameters */:
                            return isStartOfParameter();
                        case 17 /* TypeArguments */:
                        case 18 /* TupleElementTypes */:
                            return token === 23 /* CommaToken */ || isStartOfType();
                        case 19 /* HeritageClauses */:
                            return isHeritageClause();
                        case 20 /* ImportOrExportSpecifiers */:
                            return isIdentifierOrKeyword();
                    }
                    ts.Debug.fail("Non-exhaustive case in 'isListElement'.");
                }
                function isValidHeritageClauseObjectLiteral() {
                    ts.Debug.assert(token === 14 /* OpenBraceToken */);
                    if (nextToken() === 15 /* CloseBraceToken */) {
                        // if we see  "extends {}" then only treat the {} as what we're extending (and not
                        // the class body) if we have:
                        //
                        //      extends {} { 
                        //      extends {},
                        //      extends {} extends
                        //      extends {} implements
                        var next = nextToken();
                        return next === 23 /* CommaToken */ || next === 14 /* OpenBraceToken */ || next === 79 /* ExtendsKeyword */ || next === 102 /* ImplementsKeyword */;
                    }
                    return true;
                }
                function nextTokenIsIdentifier() {
                    nextToken();
                    return isIdentifier();
                }
                function isHeritageClauseExtendsOrImplementsKeyword() {
                    if (token === 102 /* ImplementsKeyword */ ||
                        token === 79 /* ExtendsKeyword */) {
                        return lookAhead(nextTokenIsStartOfExpression);
                    }
                    return false;
                }
                function nextTokenIsStartOfExpression() {
                    nextToken();
                    return isStartOfExpression();
                }
                // True if positioned at a list terminator
                function isListTerminator(kind) {
                    if (token === 1 /* EndOfFileToken */) {
                        // Being at the end of the file ends all lists.
                        return true;
                    }
                    switch (kind) {
                        case 1 /* ModuleElements */:
                        case 2 /* BlockStatements */:
                        case 3 /* SwitchClauses */:
                        case 5 /* TypeMembers */:
                        case 6 /* ClassMembers */:
                        case 7 /* EnumMembers */:
                        case 13 /* ObjectLiteralMembers */:
                        case 10 /* ObjectBindingElements */:
                        case 20 /* ImportOrExportSpecifiers */:
                            return token === 15 /* CloseBraceToken */;
                        case 4 /* SwitchClauseStatements */:
                            return token === 15 /* CloseBraceToken */ || token === 67 /* CaseKeyword */ || token === 73 /* DefaultKeyword */;
                        case 8 /* HeritageClauseElement */:
                            return token === 14 /* OpenBraceToken */ || token === 79 /* ExtendsKeyword */ || token === 102 /* ImplementsKeyword */;
                        case 9 /* VariableDeclarations */:
                            return isVariableDeclaratorListTerminator();
                        case 16 /* TypeParameters */:
                            // Tokens other than '>' are here for better error recovery
                            return token === 25 /* GreaterThanToken */ || token === 16 /* OpenParenToken */ || token === 14 /* OpenBraceToken */ || token === 79 /* ExtendsKeyword */ || token === 102 /* ImplementsKeyword */;
                        case 12 /* ArgumentExpressions */:
                            // Tokens other than ')' are here for better error recovery
                            return token === 17 /* CloseParenToken */ || token === 22 /* SemicolonToken */;
                        case 14 /* ArrayLiteralMembers */:
                        case 18 /* TupleElementTypes */:
                        case 11 /* ArrayBindingElements */:
                            return token === 19 /* CloseBracketToken */;
                        case 15 /* Parameters */:
                            // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery
                            return token === 17 /* CloseParenToken */ || token === 19 /* CloseBracketToken */ /*|| token === SyntaxKind.OpenBraceToken*/;
                        case 17 /* TypeArguments */:
                            // Tokens other than '>' are here for better error recovery
                            return token === 25 /* GreaterThanToken */ || token === 16 /* OpenParenToken */;
                        case 19 /* HeritageClauses */:
                            return token === 14 /* OpenBraceToken */ || token === 15 /* CloseBraceToken */;
                    }
                }
                function isVariableDeclaratorListTerminator() {
                    // If we can consume a semicolon (either explicitly, or with ASI), then consider us done
                    // with parsing the list of  variable declarators.
                    if (canParseSemicolon()) {
                        return true;
                    }
                    // in the case where we're parsing the variable declarator of a 'for-in' statement, we
                    // are done if we see an 'in' keyword in front of us. Same with for-of
                    if (isInOrOfKeyword(token)) {
                        return true;
                    }
                    // ERROR RECOVERY TWEAK:
                    // For better error recovery, if we see an '=>' then we just stop immediately.  We've got an
                    // arrow function here and it's going to be very unlikely that we'll resynchronize and get
                    // another variable declaration.
                    if (token === 32 /* EqualsGreaterThanToken */) {
                        return true;
                    }
                    // Keep trying to parse out variable declarators.
                    return false;
                }
                // True if positioned at element or terminator of the current list or any enclosing list
                function isInSomeParsingContext() {
                    for (var kind = 0; kind < 21 /* Count */; kind++) {
                        if (parsingContext & (1 << kind)) {
                            if (isListElement(kind, true) || isListTerminator(kind)) {
                                return true;
                            }
                        }
                    }
                    return false;
                }
                // Parses a list of elements
                function parseList(kind, checkForStrictMode, parseElement) {
                    var saveParsingContext = parsingContext;
                    parsingContext |= 1 << kind;
                    var result = [];
                    result.pos = getNodePos();
                    var savedStrictModeContext = inStrictModeContext();
                    while (!isListTerminator(kind)) {
                        if (isListElement(kind, false)) {
                            var element = parseListElement(kind, parseElement);
                            result.push(element);
                            // test elements only if we are not already in strict mode
                            if (checkForStrictMode && !inStrictModeContext()) {
                                if (ts.isPrologueDirective(element)) {
                                    if (isUseStrictPrologueDirective(sourceFile, element)) {
                                        setStrictModeContext(true);
                                        checkForStrictMode = false;
                                    }
                                }
                                else {
                                    checkForStrictMode = false;
                                }
                            }
                            continue;
                        }
                        if (abortParsingListOrMoveToNextToken(kind)) {
                            break;
                        }
                    }
                    setStrictModeContext(savedStrictModeContext);
                    result.end = getNodeEnd();
                    parsingContext = saveParsingContext;
                    return result;
                }
                /// Should be called only on prologue directives (isPrologueDirective(node) should be true)
                function isUseStrictPrologueDirective(sourceFile, node) {
                    ts.Debug.assert(ts.isPrologueDirective(node));
                    var nodeText = ts.getSourceTextOfNodeFromSourceFile(sourceFile, node.expression);
                    // Note: the node text must be exactly "use strict" or 'use strict'.  It is not ok for the
                    // string to contain unicode escapes (as per ES5).
                    return nodeText === '"use strict"' || nodeText === "'use strict'";
                }
                function parseListElement(parsingContext, parseElement) {
                    var node = currentNode(parsingContext);
                    if (node) {
                        return consumeNode(node);
                    }
                    return parseElement();
                }
                function currentNode(parsingContext) {
                    // If there is an outstanding parse error that we've encountered, but not attached to
                    // some node, then we cannot get a node from the old source tree.  This is because we
                    // want to mark the next node we encounter as being unusable.
                    //
                    // Note: This may be too conservative.  Perhaps we could reuse the node and set the bit
                    // on it (or its leftmost child) as having the error.  For now though, being conservative
                    // is nice and likely won't ever affect perf.
                    if (parseErrorBeforeNextFinishedNode) {
                        return undefined;
                    }
                    if (!syntaxCursor) {
                        // if we don't have a cursor, we could never return a node from the old tree.
                        return undefined;
                    }
                    var node = syntaxCursor.currentNode(scanner.getStartPos());
                    // Can't reuse a missing node.
                    if (ts.nodeIsMissing(node)) {
                        return undefined;
                    }
                    // Can't reuse a node that intersected the change range.
                    if (node.intersectsChange) {
                        return undefined;
                    }
                    // Can't reuse a node that contains a parse error.  This is necessary so that we
                    // produce the same set of errors again.
                    if (ts.containsParseError(node)) {
                        return undefined;
                    }
                    // We can only reuse a node if it was parsed under the same strict mode that we're
                    // currently in.  i.e. if we originally parsed a node in non-strict mode, but then
                    // the user added 'using strict' at the top of the file, then we can't use that node
                    // again as the presense of strict mode may cause us to parse the tokens in the file
                    // differetly.
                    //
                    // Note: we *can* reuse tokens when the strict mode changes.  That's because tokens
                    // are unaffected by strict mode.  It's just the parser will decide what to do with it
                    // differently depending on what mode it is in.
                    //
                    // This also applies to all our other context flags as well.
                    var nodeContextFlags = node.parserContextFlags & 63 /* ParserGeneratedFlags */;
                    if (nodeContextFlags !== contextFlags) {
                        return undefined;
                    }
                    // Ok, we have a node that looks like it could be reused.  Now verify that it is valid
                    // in the currest list parsing context that we're currently at.
                    if (!canReuseNode(node, parsingContext)) {
                        return undefined;
                    }
                    return node;
                }
                function consumeNode(node) {
                    // Move the scanner so it is after the node we just consumed.
                    scanner.setTextPos(node.end);
                    nextToken();
                    return node;
                }
                function canReuseNode(node, parsingContext) {
                    switch (parsingContext) {
                        case 1 /* ModuleElements */:
                            return isReusableModuleElement(node);
                        case 6 /* ClassMembers */:
                            return isReusableClassMember(node);
                        case 3 /* SwitchClauses */:
                            return isReusableSwitchClause(node);
                        case 2 /* BlockStatements */:
                        case 4 /* SwitchClauseStatements */:
                            return isReusableStatement(node);
                        case 7 /* EnumMembers */:
                            return isReusableEnumMember(node);
                        case 5 /* TypeMembers */:
                            return isReusableTypeMember(node);
                        case 9 /* VariableDeclarations */:
                            return isReusableVariableDeclaration(node);
                        case 15 /* Parameters */:
                            return isReusableParameter(node);
                        // Any other lists we do not care about reusing nodes in.  But feel free to add if
                        // you can do so safely.  Danger areas involve nodes that may involve speculative
                        // parsing.  If speculative parsing is involved with the node, then the range the
                        // parser reached while looking ahead might be in the edited range (see the example
                        // in canReuseVariableDeclaratorNode for a good case of this).
                        case 19 /* HeritageClauses */:
                        // This would probably be safe to reuse.  There is no speculative parsing with
                        // heritage clauses.
                        case 16 /* TypeParameters */:
                        // This would probably be safe to reuse.  There is no speculative parsing with
                        // type parameters.  Note that that's because type *parameters* only occur in
                        // unambiguous *type* contexts.  While type *arguments* occur in very ambiguous
                        // *expression* contexts.
                        case 18 /* TupleElementTypes */:
                        // This would probably be safe to reuse.  There is no speculative parsing with
                        // tuple types.
                        // Technically, type argument list types are probably safe to reuse.  While
                        // speculative parsing is involved with them (since type argument lists are only
                        // produced from speculative parsing a < as a type argument list), we only have
                        // the types because speculative parsing succeeded.  Thus, the lookahead never
                        // went past the end of the list and rewound.
                        case 17 /* TypeArguments */:
                        // Note: these are almost certainly not safe to ever reuse.  Expressions commonly
                        // need a large amount of lookahead, and we should not reuse them as they may
                        // have actually intersected the edit.
                        case 12 /* ArgumentExpressions */:
                        // This is not safe to reuse for the same reason as the 'AssignmentExpression'
                        // cases.  i.e. a property assignment may end with an expression, and thus might
                        // have lookahead far beyond it's old node.
                        case 13 /* ObjectLiteralMembers */:
                        // This is probably not safe to reuse.  There can be speculative parsing with
                        // type names in a heritage clause.  There can be generic names in the type
                        // name list, and there can be left hand side expressions (which can have type
                        // arguments.)
                        case 8 /* HeritageClauseElement */:
                    }
                    return false;
                }
                function isReusableModuleElement(node) {
                    if (node) {
                        switch (node.kind) {
                            case 209 /* ImportDeclaration */:
                            case 208 /* ImportEqualsDeclaration */:
                            case 215 /* ExportDeclaration */:
                            case 214 /* ExportAssignment */:
                            case 201 /* ClassDeclaration */:
                            case 202 /* InterfaceDeclaration */:
                            case 205 /* ModuleDeclaration */:
                            case 204 /* EnumDeclaration */:
                                return true;
                        }
                        return isReusableStatement(node);
                    }
                    return false;
                }
                function isReusableClassMember(node) {
                    if (node) {
                        switch (node.kind) {
                            case 135 /* Constructor */:
                            case 140 /* IndexSignature */:
                            case 134 /* MethodDeclaration */:
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                            case 132 /* PropertyDeclaration */:
                            case 178 /* SemicolonClassElement */:
                                return true;
                        }
                    }
                    return false;
                }
                function isReusableSwitchClause(node) {
                    if (node) {
                        switch (node.kind) {
                            case 220 /* CaseClause */:
                            case 221 /* DefaultClause */:
                                return true;
                        }
                    }
                    return false;
                }
                function isReusableStatement(node) {
                    if (node) {
                        switch (node.kind) {
                            case 200 /* FunctionDeclaration */:
                            case 180 /* VariableStatement */:
                            case 179 /* Block */:
                            case 183 /* IfStatement */:
                            case 182 /* ExpressionStatement */:
                            case 195 /* ThrowStatement */:
                            case 191 /* ReturnStatement */:
                            case 193 /* SwitchStatement */:
                            case 190 /* BreakStatement */:
                            case 189 /* ContinueStatement */:
                            case 187 /* ForInStatement */:
                            case 188 /* ForOfStatement */:
                            case 186 /* ForStatement */:
                            case 185 /* WhileStatement */:
                            case 192 /* WithStatement */:
                            case 181 /* EmptyStatement */:
                            case 196 /* TryStatement */:
                            case 194 /* LabeledStatement */:
                            case 184 /* DoStatement */:
                            case 197 /* DebuggerStatement */:
                                return true;
                        }
                    }
                    return false;
                }
                function isReusableEnumMember(node) {
                    return node.kind === 226 /* EnumMember */;
                }
                function isReusableTypeMember(node) {
                    if (node) {
                        switch (node.kind) {
                            case 139 /* ConstructSignature */:
                            case 133 /* MethodSignature */:
                            case 140 /* IndexSignature */:
                            case 131 /* PropertySignature */:
                            case 138 /* CallSignature */:
                                return true;
                        }
                    }
                    return false;
                }
                function isReusableVariableDeclaration(node) {
                    if (node.kind !== 198 /* VariableDeclaration */) {
                        return false;
                    }
                    // Very subtle incremental parsing bug.  Consider the following code:
                    //
                    //      let v = new List < A, B
                    //
                    // This is actually legal code.  It's a list of variable declarators "v = new List<A"
                    // on one side and "B" on the other. If you then change that to:
                    //
                    //      let v = new List < A, B >()
                    //
                    // then we have a problem.  "v = new List<A" doesn't intersect the change range, so we
                    // start reparsing at "B" and we completely fail to handle this properly.
                    //
                    // In order to prevent this, we do not allow a variable declarator to be reused if it
                    // has an initializer.
                    var variableDeclarator = node;
                    return variableDeclarator.initializer === undefined;
                }
                function isReusableParameter(node) {
                    if (node.kind !== 129 /* Parameter */) {
                        return false;
                    }
                    // See the comment in isReusableVariableDeclaration for why we do this.
                    var parameter = node;
                    return parameter.initializer === undefined;
                }
                // Returns true if we should abort parsing.
                function abortParsingListOrMoveToNextToken(kind) {
                    parseErrorAtCurrentToken(parsingContextErrors(kind));
                    if (isInSomeParsingContext()) {
                        return true;
                    }
                    nextToken();
                    return false;
                }
                function parsingContextErrors(context) {
                    switch (context) {
                        case 0 /* SourceElements */: return ts.Diagnostics.Declaration_or_statement_expected;
                        case 1 /* ModuleElements */: return ts.Diagnostics.Declaration_or_statement_expected;
                        case 2 /* BlockStatements */: return ts.Diagnostics.Statement_expected;
                        case 3 /* SwitchClauses */: return ts.Diagnostics.case_or_default_expected;
                        case 4 /* SwitchClauseStatements */: return ts.Diagnostics.Statement_expected;
                        case 5 /* TypeMembers */: return ts.Diagnostics.Property_or_signature_expected;
                        case 6 /* ClassMembers */: return ts.Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected;
                        case 7 /* EnumMembers */: return ts.Diagnostics.Enum_member_expected;
                        case 8 /* HeritageClauseElement */: return ts.Diagnostics.Expression_expected;
                        case 9 /* VariableDeclarations */: return ts.Diagnostics.Variable_declaration_expected;
                        case 10 /* ObjectBindingElements */: return ts.Diagnostics.Property_destructuring_pattern_expected;
                        case 11 /* ArrayBindingElements */: return ts.Diagnostics.Array_element_destructuring_pattern_expected;
                        case 12 /* ArgumentExpressions */: return ts.Diagnostics.Argument_expression_expected;
                        case 13 /* ObjectLiteralMembers */: return ts.Diagnostics.Property_assignment_expected;
                        case 14 /* ArrayLiteralMembers */: return ts.Diagnostics.Expression_or_comma_expected;
                        case 15 /* Parameters */: return ts.Diagnostics.Parameter_declaration_expected;
                        case 16 /* TypeParameters */: return ts.Diagnostics.Type_parameter_declaration_expected;
                        case 17 /* TypeArguments */: return ts.Diagnostics.Type_argument_expected;
                        case 18 /* TupleElementTypes */: return ts.Diagnostics.Type_expected;
                        case 19 /* HeritageClauses */: return ts.Diagnostics.Unexpected_token_expected;
                        case 20 /* ImportOrExportSpecifiers */: return ts.Diagnostics.Identifier_expected;
                    }
                }
                ;
                // Parses a comma-delimited list of elements
                function parseDelimitedList(kind, parseElement, considerSemicolonAsDelimeter) {
                    var saveParsingContext = parsingContext;
                    parsingContext |= 1 << kind;
                    var result = [];
                    result.pos = getNodePos();
                    var commaStart = -1; // Meaning the previous token was not a comma
                    while (true) {
                        if (isListElement(kind, false)) {
                            result.push(parseListElement(kind, parseElement));
                            commaStart = scanner.getTokenPos();
                            if (parseOptional(23 /* CommaToken */)) {
                                continue;
                            }
                            commaStart = -1; // Back to the state where the last token was not a comma
                            if (isListTerminator(kind)) {
                                break;
                            }
                            // We didn't get a comma, and the list wasn't terminated, explicitly parse
                            // out a comma so we give a good error message.
                            parseExpected(23 /* CommaToken */);
                            // If the token was a semicolon, and the caller allows that, then skip it and
                            // continue.  This ensures we get back on track and don't result in tons of
                            // parse errors.  For example, this can happen when people do things like use
                            // a semicolon to delimit object literal members.   Note: we'll have already
                            // reported an error when we called parseExpected above.
                            if (considerSemicolonAsDelimeter && token === 22 /* SemicolonToken */ && !scanner.hasPrecedingLineBreak()) {
                                nextToken();
                            }
                            continue;
                        }
                        if (isListTerminator(kind)) {
                            break;
                        }
                        if (abortParsingListOrMoveToNextToken(kind)) {
                            break;
                        }
                    }
                    // Recording the trailing comma is deliberately done after the previous
                    // loop, and not just if we see a list terminator. This is because the list
                    // may have ended incorrectly, but it is still important to know if there
                    // was a trailing comma.
                    // Check if the last token was a comma.
                    if (commaStart >= 0) {
                        // Always preserve a trailing comma by marking it on the NodeArray
                        result.hasTrailingComma = true;
                    }
                    result.end = getNodeEnd();
                    parsingContext = saveParsingContext;
                    return result;
                }
                function createMissingList() {
                    var pos = getNodePos();
                    var result = [];
                    result.pos = pos;
                    result.end = pos;
                    return result;
                }
                function parseBracketedList(kind, parseElement, open, close) {
                    if (parseExpected(open)) {
                        var result = parseDelimitedList(kind, parseElement);
                        parseExpected(close);
                        return result;
                    }
                    return createMissingList();
                }
                // The allowReservedWords parameter controls whether reserved words are permitted after the first dot
                function parseEntityName(allowReservedWords, diagnosticMessage) {
                    var entity = parseIdentifier(diagnosticMessage);
                    while (parseOptional(20 /* DotToken */)) {
                        var node = createNode(126 /* QualifiedName */, entity.pos);
                        node.left = entity;
                        node.right = parseRightSideOfDot(allowReservedWords);
                        entity = finishNode(node);
                    }
                    return entity;
                }
                function parseRightSideOfDot(allowIdentifierNames) {
                    // Technically a keyword is valid here as all keywords are identifier names.
                    // However, often we'll encounter this in error situations when the keyword
                    // is actually starting another valid construct.
                    //
                    // So, we check for the following specific case:
                    //
                    //      name.
                    //      keyword identifierNameOrKeyword
                    //
                    // Note: the newlines are important here.  For example, if that above code
                    // were rewritten into:
                    //
                    //      name.keyword
                    //      identifierNameOrKeyword
                    //
                    // Then we would consider it valid.  That's because ASI would take effect and
                    // the code would be implicitly: "name.keyword; identifierNameOrKeyword".
                    // In the first case though, ASI will not take effect because there is not a
                    // line terminator after the keyword.
                    if (scanner.hasPrecedingLineBreak() && scanner.isReservedWord()) {
                        var matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
                        if (matchesPattern) {
                            // Report that we need an identifier.  However, report it right after the dot,
                            // and not on the next token.  This is because the next token might actually
                            // be an identifier and the error woudl be quite confusing.
                            return createMissingNode(65 /* Identifier */, true, ts.Diagnostics.Identifier_expected);
                        }
                    }
                    return allowIdentifierNames ? parseIdentifierName() : parseIdentifier();
                }
                function parseTemplateExpression() {
                    var template = createNode(171 /* TemplateExpression */);
                    template.head = parseLiteralNode();
                    ts.Debug.assert(template.head.kind === 11 /* TemplateHead */, "Template head has wrong token kind");
                    var templateSpans = [];
                    templateSpans.pos = getNodePos();
                    do {
                        templateSpans.push(parseTemplateSpan());
                    } while (templateSpans[templateSpans.length - 1].literal.kind === 12 /* TemplateMiddle */);
                    templateSpans.end = getNodeEnd();
                    template.templateSpans = templateSpans;
                    return finishNode(template);
                }
                function parseTemplateSpan() {
                    var span = createNode(176 /* TemplateSpan */);
                    span.expression = allowInAnd(parseExpression);
                    var literal;
                    if (token === 15 /* CloseBraceToken */) {
                        reScanTemplateToken();
                        literal = parseLiteralNode();
                    }
                    else {
                        literal = parseExpectedToken(13 /* TemplateTail */, false, ts.Diagnostics._0_expected, ts.tokenToString(15 /* CloseBraceToken */));
                    }
                    span.literal = literal;
                    return finishNode(span);
                }
                function parseLiteralNode(internName) {
                    var node = createNode(token);
                    var text = scanner.getTokenValue();
                    node.text = internName ? internIdentifier(text) : text;
                    if (scanner.hasExtendedUnicodeEscape()) {
                        node.hasExtendedUnicodeEscape = true;
                    }
                    if (scanner.isUnterminated()) {
                        node.isUnterminated = true;
                    }
                    var tokenPos = scanner.getTokenPos();
                    nextToken();
                    finishNode(node);
                    // Octal literals are not allowed in strict mode or ES5
                    // Note that theoretically the following condition would hold true literals like 009,
                    // which is not octal.But because of how the scanner separates the tokens, we would
                    // never get a token like this. Instead, we would get 00 and 9 as two separate tokens.
                    // We also do not need to check for negatives because any prefix operator would be part of a
                    // parent unary expression.
                    if (node.kind === 7 /* NumericLiteral */
                        && sourceText.charCodeAt(tokenPos) === 48 /* _0 */
                        && ts.isOctalDigit(sourceText.charCodeAt(tokenPos + 1))) {
                        node.flags |= 16384 /* OctalLiteral */;
                    }
                    return node;
                }
                // TYPES
                function parseTypeReference() {
                    var node = createNode(141 /* TypeReference */);
                    node.typeName = parseEntityName(false, ts.Diagnostics.Type_expected);
                    if (!scanner.hasPrecedingLineBreak() && token === 24 /* LessThanToken */) {
                        node.typeArguments = parseBracketedList(17 /* TypeArguments */, parseType, 24 /* LessThanToken */, 25 /* GreaterThanToken */);
                    }
                    return finishNode(node);
                }
                function parseTypeQuery() {
                    var node = createNode(144 /* TypeQuery */);
                    parseExpected(97 /* TypeOfKeyword */);
                    node.exprName = parseEntityName(true);
                    return finishNode(node);
                }
                function parseTypeParameter() {
                    var node = createNode(128 /* TypeParameter */);
                    node.name = parseIdentifier();
                    if (parseOptional(79 /* ExtendsKeyword */)) {
                        // It's not uncommon for people to write improper constraints to a generic.  If the
                        // user writes a constraint that is an expression and not an actual type, then parse
                        // it out as an expression (so we can recover well), but report that a type is needed
                        // instead.
                        if (isStartOfType() || !isStartOfExpression()) {
                            node.constraint = parseType();
                        }
                        else {
                            // It was not a type, and it looked like an expression.  Parse out an expression
                            // here so we recover well.  Note: it is important that we call parseUnaryExpression
                            // and not parseExpression here.  If the user has:
                            //
                            //      <T extends "">
                            //
                            // We do *not* want to consume the  >  as we're consuming the expression for "".
                            node.expression = parseUnaryExpressionOrHigher();
                        }
                    }
                    return finishNode(node);
                }
                function parseTypeParameters() {
                    if (token === 24 /* LessThanToken */) {
                        return parseBracketedList(16 /* TypeParameters */, parseTypeParameter, 24 /* LessThanToken */, 25 /* GreaterThanToken */);
                    }
                }
                function parseParameterType() {
                    if (parseOptional(51 /* ColonToken */)) {
                        return token === 8 /* StringLiteral */
                            ? parseLiteralNode(true)
                            : parseType();
                    }
                    return undefined;
                }
                function isStartOfParameter() {
                    return token === 21 /* DotDotDotToken */ || isIdentifierOrPattern() || ts.isModifier(token) || token === 52 /* AtToken */;
                }
                function setModifiers(node, modifiers) {
                    if (modifiers) {
                        node.flags |= modifiers.flags;
                        node.modifiers = modifiers;
                    }
                }
                function parseParameter() {
                    var node = createNode(129 /* Parameter */);
                    node.decorators = parseDecorators();
                    setModifiers(node, parseModifiers());
                    node.dotDotDotToken = parseOptionalToken(21 /* DotDotDotToken */);
                    // SingleNameBinding[Yield,GeneratorParameter] : See 13.2.3
                    //      [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt
                    //      [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
                    node.name = inGeneratorParameterContext() ? doInYieldContext(parseIdentifierOrPattern) : parseIdentifierOrPattern();
                    if (ts.getFullWidth(node.name) === 0 && node.flags === 0 && ts.isModifier(token)) {
                        // in cases like
                        // 'use strict'
                        // function foo(static)
                        // isParameter('static') === true, because of isModifier('static')
                        // however 'static' is not a legal identifier in a strict mode.
                        // so result of this function will be ParameterDeclaration (flags = 0, name = missing, type = undefined, initializer = undefined)
                        // and current token will not change => parsing of the enclosing parameter list will last till the end of time (or OOM)
                        // to avoid this we'll advance cursor to the next token.
                        nextToken();
                    }
                    node.questionToken = parseOptionalToken(50 /* QuestionToken */);
                    node.type = parseParameterType();
                    node.initializer = inGeneratorParameterContext() ? doOutsideOfYieldContext(parseParameterInitializer) : parseParameterInitializer();
                    // Do not check for initializers in an ambient context for parameters. This is not
                    // a grammar error because the grammar allows arbitrary call signatures in
                    // an ambient context.
                    // It is actually not necessary for this to be an error at all. The reason is that
                    // function/constructor implementations are syntactically disallowed in ambient
                    // contexts. In addition, parameter initializers are semantically disallowed in
                    // overload signatures. So parameter initializers are transitively disallowed in
                    // ambient contexts.
                    return finishNode(node);
                }
                function parseParameterInitializer() {
                    return parseInitializer(true);
                }
                function fillSignature(returnToken, yieldAndGeneratorParameterContext, requireCompleteParameterList, signature) {
                    var returnTokenRequired = returnToken === 32 /* EqualsGreaterThanToken */;
                    signature.typeParameters = parseTypeParameters();
                    signature.parameters = parseParameterList(yieldAndGeneratorParameterContext, requireCompleteParameterList);
                    if (returnTokenRequired) {
                        parseExpected(returnToken);
                        signature.type = parseType();
                    }
                    else if (parseOptional(returnToken)) {
                        signature.type = parseType();
                    }
                }
                // Note: after careful analysis of the grammar, it does not appear to be possible to
                // have 'Yield' And 'GeneratorParameter' not in sync.  i.e. any production calling
                // this FormalParameters production either always sets both to true, or always sets
                // both to false.  As such we only have a single parameter to represent both.
                function parseParameterList(yieldAndGeneratorParameterContext, requireCompleteParameterList) {
                    // FormalParameters[Yield,GeneratorParameter] :
                    //      ...
                    //
                    // FormalParameter[Yield,GeneratorParameter] :
                    //      BindingElement[?Yield, ?GeneratorParameter]
                    //
                    // BindingElement[Yield, GeneratorParameter ] : See 13.2.3
                    //      SingleNameBinding[?Yield, ?GeneratorParameter]
                    //      [+GeneratorParameter]BindingPattern[?Yield, GeneratorParameter]Initializer[In]opt
                    //      [~GeneratorParameter]BindingPattern[?Yield]Initializer[In, ?Yield]opt
                    //
                    // SingleNameBinding[Yield, GeneratorParameter] : See 13.2.3
                    //      [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt
                    //      [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
                    if (parseExpected(16 /* OpenParenToken */)) {
                        var savedYieldContext = inYieldContext();
                        var savedGeneratorParameterContext = inGeneratorParameterContext();
                        setYieldContext(yieldAndGeneratorParameterContext);
                        setGeneratorParameterContext(yieldAndGeneratorParameterContext);
                        var result = parseDelimitedList(15 /* Parameters */, parseParameter);
                        setYieldContext(savedYieldContext);
                        setGeneratorParameterContext(savedGeneratorParameterContext);
                        if (!parseExpected(17 /* CloseParenToken */) && requireCompleteParameterList) {
                            // Caller insisted that we had to end with a )   We didn't.  So just return
                            // undefined here.
                            return undefined;
                        }
                        return result;
                    }
                    // We didn't even have an open paren.  If the caller requires a complete parameter list,
                    // we definitely can't provide that.  However, if they're ok with an incomplete one,
                    // then just return an empty set of parameters.
                    return requireCompleteParameterList ? undefined : createMissingList();
                }
                function parseTypeMemberSemicolon() {
                    // We allow type members to be separated by commas or (possibly ASI) semicolons.
                    // First check if it was a comma.  If so, we're done with the member.
                    if (parseOptional(23 /* CommaToken */)) {
                        return;
                    }
                    // Didn't have a comma.  We must have a (possible ASI) semicolon.
                    parseSemicolon();
                }
                function parseSignatureMember(kind) {
                    var node = createNode(kind);
                    if (kind === 139 /* ConstructSignature */) {
                        parseExpected(88 /* NewKeyword */);
                    }
                    fillSignature(51 /* ColonToken */, false, false, node);
                    parseTypeMemberSemicolon();
                    return finishNode(node);
                }
                function isIndexSignature() {
                    if (token !== 18 /* OpenBracketToken */) {
                        return false;
                    }
                    return lookAhead(isUnambiguouslyIndexSignature);
                }
                function isUnambiguouslyIndexSignature() {
                    // The only allowed sequence is:
                    //
                    //   [id:
                    //
                    // However, for error recovery, we also check the following cases:
                    //
                    //   [...
                    //   [id,
                    //   [id?,
                    //   [id?:
                    //   [id?]
                    //   [public id
                    //   [private id
                    //   [protected id
                    //   []
                    //
                    nextToken();
                    if (token === 21 /* DotDotDotToken */ || token === 19 /* CloseBracketToken */) {
                        return true;
                    }
                    if (ts.isModifier(token)) {
                        nextToken();
                        if (isIdentifier()) {
                            return true;
                        }
                    }
                    else if (!isIdentifier()) {
                        return false;
                    }
                    else {
                        // Skip the identifier
                        nextToken();
                    }
                    // A colon signifies a well formed indexer
                    // A comma should be a badly formed indexer because comma expressions are not allowed
                    // in computed properties.
                    if (token === 51 /* ColonToken */ || token === 23 /* CommaToken */) {
                        return true;
                    }
                    // Question mark could be an indexer with an optional property,
                    // or it could be a conditional expression in a computed property.
                    if (token !== 50 /* QuestionToken */) {
                        return false;
                    }
                    // If any of the following tokens are after the question mark, it cannot
                    // be a conditional expression, so treat it as an indexer.
                    nextToken();
                    return token === 51 /* ColonToken */ || token === 23 /* CommaToken */ || token === 19 /* CloseBracketToken */;
                }
                function parseIndexSignatureDeclaration(fullStart, decorators, modifiers) {
                    var node = createNode(140 /* IndexSignature */, fullStart);
                    node.decorators = decorators;
                    setModifiers(node, modifiers);
                    node.parameters = parseBracketedList(15 /* Parameters */, parseParameter, 18 /* OpenBracketToken */, 19 /* CloseBracketToken */);
                    node.type = parseTypeAnnotation();
                    parseTypeMemberSemicolon();
                    return finishNode(node);
                }
                function parsePropertyOrMethodSignature() {
                    var fullStart = scanner.getStartPos();
                    var name = parsePropertyName();
                    var questionToken = parseOptionalToken(50 /* QuestionToken */);
                    if (token === 16 /* OpenParenToken */ || token === 24 /* LessThanToken */) {
                        var method = createNode(133 /* MethodSignature */, fullStart);
                        method.name = name;
                        method.questionToken = questionToken;
                        // Method signatues don't exist in expression contexts.  So they have neither
                        // [Yield] nor [GeneratorParameter]
                        fillSignature(51 /* ColonToken */, false, false, method);
                        parseTypeMemberSemicolon();
                        return finishNode(method);
                    }
                    else {
                        var property = createNode(131 /* PropertySignature */, fullStart);
                        property.name = name;
                        property.questionToken = questionToken;
                        property.type = parseTypeAnnotation();
                        parseTypeMemberSemicolon();
                        return finishNode(property);
                    }
                }
                function isStartOfTypeMember() {
                    switch (token) {
                        case 16 /* OpenParenToken */:
                        case 24 /* LessThanToken */:
                        case 18 /* OpenBracketToken */:
                            return true;
                        default:
                            if (ts.isModifier(token)) {
                                var result = lookAhead(isStartOfIndexSignatureDeclaration);
                                if (result) {
                                    return result;
                                }
                            }
                            return isLiteralPropertyName() && lookAhead(isTypeMemberWithLiteralPropertyName);
                    }
                }
                function isStartOfIndexSignatureDeclaration() {
                    while (ts.isModifier(token)) {
                        nextToken();
                    }
                    return isIndexSignature();
                }
                function isTypeMemberWithLiteralPropertyName() {
                    nextToken();
                    return token === 16 /* OpenParenToken */ ||
                        token === 24 /* LessThanToken */ ||
                        token === 50 /* QuestionToken */ ||
                        token === 51 /* ColonToken */ ||
                        canParseSemicolon();
                }
                function parseTypeMember() {
                    switch (token) {
                        case 16 /* OpenParenToken */:
                        case 24 /* LessThanToken */:
                            return parseSignatureMember(138 /* CallSignature */);
                        case 18 /* OpenBracketToken */:
                            // Indexer or computed property
                            return isIndexSignature()
                                ? parseIndexSignatureDeclaration(scanner.getStartPos(), undefined, undefined)
                                : parsePropertyOrMethodSignature();
                        case 88 /* NewKeyword */:
                            if (lookAhead(isStartOfConstructSignature)) {
                                return parseSignatureMember(139 /* ConstructSignature */);
                            }
                        // fall through.
                        case 8 /* StringLiteral */:
                        case 7 /* NumericLiteral */:
                            return parsePropertyOrMethodSignature();
                        default:
                            // Index declaration as allowed as a type member.  But as per the grammar,
                            // they also allow modifiers. So we have to check for an index declaration
                            // that might be following modifiers. This ensures that things work properly
                            // when incrementally parsing as the parser will produce the Index declaration
                            // if it has the same text regardless of whether it is inside a class or an
                            // object type.
                            if (ts.isModifier(token)) {
                                var result = tryParse(parseIndexSignatureWithModifiers);
                                if (result) {
                                    return result;
                                }
                            }
                            if (isIdentifierOrKeyword()) {
                                return parsePropertyOrMethodSignature();
                            }
                    }
                }
                function parseIndexSignatureWithModifiers() {
                    var fullStart = scanner.getStartPos();
                    var decorators = parseDecorators();
                    var modifiers = parseModifiers();
                    return isIndexSignature()
                        ? parseIndexSignatureDeclaration(fullStart, decorators, modifiers)
                        : undefined;
                }
                function isStartOfConstructSignature() {
                    nextToken();
                    return token === 16 /* OpenParenToken */ || token === 24 /* LessThanToken */;
                }
                function parseTypeLiteral() {
                    var node = createNode(145 /* TypeLiteral */);
                    node.members = parseObjectTypeMembers();
                    return finishNode(node);
                }
                function parseObjectTypeMembers() {
                    var members;
                    if (parseExpected(14 /* OpenBraceToken */)) {
                        members = parseList(5 /* TypeMembers */, false, parseTypeMember);
                        parseExpected(15 /* CloseBraceToken */);
                    }
                    else {
                        members = createMissingList();
                    }
                    return members;
                }
                function parseTupleType() {
                    var node = createNode(147 /* TupleType */);
                    node.elementTypes = parseBracketedList(18 /* TupleElementTypes */, parseType, 18 /* OpenBracketToken */, 19 /* CloseBracketToken */);
                    return finishNode(node);
                }
                function parseParenthesizedType() {
                    var node = createNode(149 /* ParenthesizedType */);
                    parseExpected(16 /* OpenParenToken */);
                    node.type = parseType();
                    parseExpected(17 /* CloseParenToken */);
                    return finishNode(node);
                }
                function parseFunctionOrConstructorType(kind) {
                    var node = createNode(kind);
                    if (kind === 143 /* ConstructorType */) {
                        parseExpected(88 /* NewKeyword */);
                    }
                    fillSignature(32 /* EqualsGreaterThanToken */, false, false, node);
                    return finishNode(node);
                }
                function parseKeywordAndNoDot() {
                    var node = parseTokenNode();
                    return token === 20 /* DotToken */ ? undefined : node;
                }
                function parseNonArrayType() {
                    switch (token) {
                        case 112 /* AnyKeyword */:
                        case 121 /* StringKeyword */:
                        case 119 /* NumberKeyword */:
                        case 113 /* BooleanKeyword */:
                        case 122 /* SymbolKeyword */:
                            // If these are followed by a dot, then parse these out as a dotted type reference instead.
                            var node = tryParse(parseKeywordAndNoDot);
                            return node || parseTypeReference();
                        case 99 /* VoidKeyword */:
                            return parseTokenNode();
                        case 97 /* TypeOfKeyword */:
                            return parseTypeQuery();
                        case 14 /* OpenBraceToken */:
                            return parseTypeLiteral();
                        case 18 /* OpenBracketToken */:
                            return parseTupleType();
                        case 16 /* OpenParenToken */:
                            return parseParenthesizedType();
                        default:
                            return parseTypeReference();
                    }
                }
                function isStartOfType() {
                    switch (token) {
                        case 112 /* AnyKeyword */:
                        case 121 /* StringKeyword */:
                        case 119 /* NumberKeyword */:
                        case 113 /* BooleanKeyword */:
                        case 122 /* SymbolKeyword */:
                        case 99 /* VoidKeyword */:
                        case 97 /* TypeOfKeyword */:
                        case 14 /* OpenBraceToken */:
                        case 18 /* OpenBracketToken */:
                        case 24 /* LessThanToken */:
                        case 88 /* NewKeyword */:
                            return true;
                        case 16 /* OpenParenToken */:
                            // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier,
                            // or something that starts a type. We don't want to consider things like '(1)' a type.
                            return lookAhead(isStartOfParenthesizedOrFunctionType);
                        default:
                            return isIdentifier();
                    }
                }
                function isStartOfParenthesizedOrFunctionType() {
                    nextToken();
                    return token === 17 /* CloseParenToken */ || isStartOfParameter() || isStartOfType();
                }
                function parseArrayTypeOrHigher() {
                    var type = parseNonArrayType();
                    while (!scanner.hasPrecedingLineBreak() && parseOptional(18 /* OpenBracketToken */)) {
                        parseExpected(19 /* CloseBracketToken */);
                        var node = createNode(146 /* ArrayType */, type.pos);
                        node.elementType = type;
                        type = finishNode(node);
                    }
                    return type;
                }
                function parseUnionTypeOrHigher() {
                    var type = parseArrayTypeOrHigher();
                    if (token === 44 /* BarToken */) {
                        var types = [type];
                        types.pos = type.pos;
                        while (parseOptional(44 /* BarToken */)) {
                            types.push(parseArrayTypeOrHigher());
                        }
                        types.end = getNodeEnd();
                        var node = createNode(148 /* UnionType */, type.pos);
                        node.types = types;
                        type = finishNode(node);
                    }
                    return type;
                }
                function isStartOfFunctionType() {
                    if (token === 24 /* LessThanToken */) {
                        return true;
                    }
                    return token === 16 /* OpenParenToken */ && lookAhead(isUnambiguouslyStartOfFunctionType);
                }
                function isUnambiguouslyStartOfFunctionType() {
                    nextToken();
                    if (token === 17 /* CloseParenToken */ || token === 21 /* DotDotDotToken */) {
                        // ( )
                        // ( ...
                        return true;
                    }
                    if (isIdentifier() || ts.isModifier(token)) {
                        nextToken();
                        if (token === 51 /* ColonToken */ || token === 23 /* CommaToken */ ||
                            token === 50 /* QuestionToken */ || token === 53 /* EqualsToken */ ||
                            isIdentifier() || ts.isModifier(token)) {
                            // ( id :
                            // ( id ,
                            // ( id ?
                            // ( id =
                            // ( modifier id
                            return true;
                        }
                        if (token === 17 /* CloseParenToken */) {
                            nextToken();
                            if (token === 32 /* EqualsGreaterThanToken */) {
                                // ( id ) =>
                                return true;
                            }
                        }
                    }
                    return false;
                }
                function parseType() {
                    // The rules about 'yield' only apply to actual code/expression contexts.  They don't
                    // apply to 'type' contexts.  So we disable these parameters here before moving on.
                    var savedYieldContext = inYieldContext();
                    var savedGeneratorParameterContext = inGeneratorParameterContext();
                    setYieldContext(false);
                    setGeneratorParameterContext(false);
                    var result = parseTypeWorker();
                    setYieldContext(savedYieldContext);
                    setGeneratorParameterContext(savedGeneratorParameterContext);
                    return result;
                }
                function parseTypeWorker() {
                    if (isStartOfFunctionType()) {
                        return parseFunctionOrConstructorType(142 /* FunctionType */);
                    }
                    if (token === 88 /* NewKeyword */) {
                        return parseFunctionOrConstructorType(143 /* ConstructorType */);
                    }
                    return parseUnionTypeOrHigher();
                }
                function parseTypeAnnotation() {
                    return parseOptional(51 /* ColonToken */) ? parseType() : undefined;
                }
                // EXPRESSIONS
                function isStartOfLeftHandSideExpression() {
                    switch (token) {
                        case 93 /* ThisKeyword */:
                        case 91 /* SuperKeyword */:
                        case 89 /* NullKeyword */:
                        case 95 /* TrueKeyword */:
                        case 80 /* FalseKeyword */:
                        case 7 /* NumericLiteral */:
                        case 8 /* StringLiteral */:
                        case 10 /* NoSubstitutionTemplateLiteral */:
                        case 11 /* TemplateHead */:
                        case 16 /* OpenParenToken */:
                        case 18 /* OpenBracketToken */:
                        case 14 /* OpenBraceToken */:
                        case 83 /* FunctionKeyword */:
                        case 69 /* ClassKeyword */:
                        case 88 /* NewKeyword */:
                        case 36 /* SlashToken */:
                        case 57 /* SlashEqualsToken */:
                        case 65 /* Identifier */:
                            return true;
                        default:
                            return isIdentifier();
                    }
                }
                function isStartOfExpression() {
                    if (isStartOfLeftHandSideExpression()) {
                        return true;
                    }
                    switch (token) {
                        case 33 /* PlusToken */:
                        case 34 /* MinusToken */:
                        case 47 /* TildeToken */:
                        case 46 /* ExclamationToken */:
                        case 74 /* DeleteKeyword */:
                        case 97 /* TypeOfKeyword */:
                        case 99 /* VoidKeyword */:
                        case 38 /* PlusPlusToken */:
                        case 39 /* MinusMinusToken */:
                        case 24 /* LessThanToken */:
                        case 110 /* YieldKeyword */:
                            // Yield always starts an expression.  Either it is an identifier (in which case
                            // it is definitely an expression).  Or it's a keyword (either because we're in
                            // a generator, or in strict mode (or both)) and it started a yield expression.
                            return true;
                        default:
                            // Error tolerance.  If we see the start of some binary operator, we consider
                            // that the start of an expression.  That way we'll parse out a missing identifier,
                            // give a good message about an identifier being missing, and then consume the
                            // rest of the binary expression.
                            if (isBinaryOperator()) {
                                return true;
                            }
                            return isIdentifier();
                    }
                }
                function isStartOfExpressionStatement() {
                    // As per the grammar, none of '{' or 'function' or 'class' can start an expression statement.
                    return token !== 14 /* OpenBraceToken */ &&
                        token !== 83 /* FunctionKeyword */ &&
                        token !== 69 /* ClassKeyword */ &&
                        token !== 52 /* AtToken */ &&
                        isStartOfExpression();
                }
                function parseExpression() {
                    // Expression[in]:
                    //      AssignmentExpression[in]
                    //      Expression[in] , AssignmentExpression[in]
                    // clear the decorator context when parsing Expression, as it should be unambiguous when parsing a decorator
                    var saveDecoratorContext = inDecoratorContext();
                    if (saveDecoratorContext) {
                        setDecoratorContext(false);
                    }
                    var expr = parseAssignmentExpressionOrHigher();
                    var operatorToken;
                    while ((operatorToken = parseOptionalToken(23 /* CommaToken */))) {
                        expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher());
                    }
                    if (saveDecoratorContext) {
                        setDecoratorContext(true);
                    }
                    return expr;
                }
                function parseInitializer(inParameter) {
                    if (token !== 53 /* EqualsToken */) {
                        // It's not uncommon during typing for the user to miss writing the '=' token.  Check if
                        // there is no newline after the last token and if we're on an expression.  If so, parse
                        // this as an equals-value clause with a missing equals.
                        // NOTE: There are two places where we allow equals-value clauses.  The first is in a
                        // variable declarator.  The second is with a parameter.  For variable declarators
                        // it's more likely that a { would be a allowed (as an object literal).  While this
                        // is also allowed for parameters, the risk is that we consume the { as an object
                        // literal when it really will be for the block following the parameter.
                        if (scanner.hasPrecedingLineBreak() || (inParameter && token === 14 /* OpenBraceToken */) || !isStartOfExpression()) {
                            // preceding line break, open brace in a parameter (likely a function body) or current token is not an expression -
                            // do not try to parse initializer
                            return undefined;
                        }
                    }
                    // Initializer[In, Yield] :
                    //     = AssignmentExpression[?In, ?Yield]
                    parseExpected(53 /* EqualsToken */);
                    return parseAssignmentExpressionOrHigher();
                }
                function parseAssignmentExpressionOrHigher() {
                    //  AssignmentExpression[in,yield]:
                    //      1) ConditionalExpression[?in,?yield]
                    //      2) LeftHandSideExpression = AssignmentExpression[?in,?yield]
                    //      3) LeftHandSideExpression AssignmentOperator AssignmentExpression[?in,?yield]
                    //      4) ArrowFunctionExpression[?in,?yield]
                    //      5) [+Yield] YieldExpression[?In]
                    //
                    // Note: for ease of implementation we treat productions '2' and '3' as the same thing.
                    // (i.e. they're both BinaryExpressions with an assignment operator in it).
                    // First, do the simple check if we have a YieldExpression (production '5').
                    if (isYieldExpression()) {
                        return parseYieldExpression();
                    }
                    // Then, check if we have an arrow function (production '4') that starts with a parenthesized
                    // parameter list. If we do, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is
                    // not a  LeftHandSideExpression, nor does it start a ConditionalExpression.  So we are done
                    // with AssignmentExpression if we see one.
                    var arrowExpression = tryParseParenthesizedArrowFunctionExpression();
                    if (arrowExpression) {
                        return arrowExpression;
                    }
                    // Now try to see if we're in production '1', '2' or '3'.  A conditional expression can
                    // start with a LogicalOrExpression, while the assignment productions can only start with
                    // LeftHandSideExpressions.
                    //
                    // So, first, we try to just parse out a BinaryExpression.  If we get something that is a
                    // LeftHandSide or higher, then we can try to parse out the assignment expression part.
                    // Otherwise, we try to parse out the conditional expression bit.  We want to allow any
                    // binary expression here, so we pass in the 'lowest' precedence here so that it matches
                    // and consumes anything.
                    var expr = parseBinaryExpressionOrHigher(0);
                    // To avoid a look-ahead, we did not handle the case of an arrow function with a single un-parenthesized
                    // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single
                    // identifier and the current token is an arrow.
                    if (expr.kind === 65 /* Identifier */ && token === 32 /* EqualsGreaterThanToken */) {
                        return parseSimpleArrowFunctionExpression(expr);
                    }
                    // Now see if we might be in cases '2' or '3'.
                    // If the expression was a LHS expression, and we have an assignment operator, then
                    // we're in '2' or '3'. Consume the assignment and return.
                    //
                    // Note: we call reScanGreaterToken so that we get an appropriately merged token
                    // for cases like > > =  becoming >>=
                    if (ts.isLeftHandSideExpression(expr) && ts.isAssignmentOperator(reScanGreaterToken())) {
                        return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher());
                    }
                    // It wasn't an assignment or a lambda.  This is a conditional expression:
                    return parseConditionalExpressionRest(expr);
                }
                function isYieldExpression() {
                    if (token === 110 /* YieldKeyword */) {
                        // If we have a 'yield' keyword, and htis is a context where yield expressions are
                        // allowed, then definitely parse out a yield expression.
                        if (inYieldContext()) {
                            return true;
                        }
                        if (inStrictModeContext()) {
                            // If we're in strict mode, then 'yield' is a keyword, could only ever start
                            // a yield expression.
                            return true;
                        }
                        // We're in a context where 'yield expr' is not allowed.  However, if we can
                        // definitely tell that the user was trying to parse a 'yield expr' and not
                        // just a normal expr that start with a 'yield' identifier, then parse out
                        // a 'yield expr'.  We can then report an error later that they are only
                        // allowed in generator expressions.
                        //
                        // for example, if we see 'yield(foo)', then we'll have to treat that as an
                        // invocation expression of something called 'yield'.  However, if we have
                        // 'yield foo' then that is not legal as a normal expression, so we can
                        // definitely recognize this as a yield expression.
                        //
                        // for now we just check if the next token is an identifier.  More heuristics
                        // can be added here later as necessary.  We just need to make sure that we
                        // don't accidently consume something legal.
                        return lookAhead(nextTokenIsIdentifierOnSameLine);
                    }
                    return false;
                }
                function nextTokenIsIdentifierOnSameLine() {
                    nextToken();
                    return !scanner.hasPrecedingLineBreak() && isIdentifier();
                }
                function nextTokenIsIdentifierOrStartOfDestructuringOnTheSameLine() {
                    nextToken();
                    return !scanner.hasPrecedingLineBreak() &&
                        (isIdentifier() || token === 14 /* OpenBraceToken */ || token === 18 /* OpenBracketToken */);
                }
                function parseYieldExpression() {
                    var node = createNode(172 /* YieldExpression */);
                    // YieldExpression[In] :
                    //      yield
                    //      yield [no LineTerminator here] [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield]
                    //      yield [no LineTerminator here] * [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield]
                    nextToken();
                    if (!scanner.hasPrecedingLineBreak() &&
                        (token === 35 /* AsteriskToken */ || isStartOfExpression())) {
                        node.asteriskToken = parseOptionalToken(35 /* AsteriskToken */);
                        node.expression = parseAssignmentExpressionOrHigher();
                        return finishNode(node);
                    }
                    else {
                        // if the next token is not on the same line as yield.  or we don't have an '*' or
                        // the start of an expressin, then this is just a simple "yield" expression.
                        return finishNode(node);
                    }
                }
                function parseSimpleArrowFunctionExpression(identifier) {
                    ts.Debug.assert(token === 32 /* EqualsGreaterThanToken */, "parseSimpleArrowFunctionExpression should only have been called if we had a =>");
                    var node = createNode(163 /* ArrowFunction */, identifier.pos);
                    var parameter = createNode(129 /* Parameter */, identifier.pos);
                    parameter.name = identifier;
                    finishNode(parameter);
                    node.parameters = [parameter];
                    node.parameters.pos = parameter.pos;
                    node.parameters.end = parameter.end;
                    node.equalsGreaterThanToken = parseExpectedToken(32 /* EqualsGreaterThanToken */, false, ts.Diagnostics._0_expected, "=>");
                    node.body = parseArrowFunctionExpressionBody();
                    return finishNode(node);
                }
                function tryParseParenthesizedArrowFunctionExpression() {
                    var triState = isParenthesizedArrowFunctionExpression();
                    if (triState === 0 /* False */) {
                        // It's definitely not a parenthesized arrow function expression.
                        return undefined;
                    }
                    // If we definitely have an arrow function, then we can just parse one, not requiring a
                    // following => or { token. Otherwise, we *might* have an arrow function.  Try to parse
                    // it out, but don't allow any ambiguity, and return 'undefined' if this could be an
                    // expression instead.
                    var arrowFunction = triState === 1 /* True */
                        ? parseParenthesizedArrowFunctionExpressionHead(true)
                        : tryParse(parsePossibleParenthesizedArrowFunctionExpressionHead);
                    if (!arrowFunction) {
                        // Didn't appear to actually be a parenthesized arrow function.  Just bail out.
                        return undefined;
                    }
                    // If we have an arrow, then try to parse the body. Even if not, try to parse if we
                    // have an opening brace, just in case we're in an error state.
                    var lastToken = token;
                    arrowFunction.equalsGreaterThanToken = parseExpectedToken(32 /* EqualsGreaterThanToken */, false, ts.Diagnostics._0_expected, "=>");
                    arrowFunction.body = (lastToken === 32 /* EqualsGreaterThanToken */ || lastToken === 14 /* OpenBraceToken */)
                        ? parseArrowFunctionExpressionBody()
                        : parseIdentifier();
                    return finishNode(arrowFunction);
                }
                //  True        -> We definitely expect a parenthesized arrow function here.
                //  False       -> There *cannot* be a parenthesized arrow function here.
                //  Unknown     -> There *might* be a parenthesized arrow function here.
                //                 Speculatively look ahead to be sure, and rollback if not.
                function isParenthesizedArrowFunctionExpression() {
                    if (token === 16 /* OpenParenToken */ || token === 24 /* LessThanToken */) {
                        return lookAhead(isParenthesizedArrowFunctionExpressionWorker);
                    }
                    if (token === 32 /* EqualsGreaterThanToken */) {
                        // ERROR RECOVERY TWEAK:
                        // If we see a standalone => try to parse it as an arrow function expression as that's
                        // likely what the user intended to write.
                        return 1 /* True */;
                    }
                    // Definitely not a parenthesized arrow function.
                    return 0 /* False */;
                }
                function isParenthesizedArrowFunctionExpressionWorker() {
                    var first = token;
                    var second = nextToken();
                    if (first === 16 /* OpenParenToken */) {
                        if (second === 17 /* CloseParenToken */) {
                            // Simple cases: "() =>", "(): ", and  "() {".
                            // This is an arrow function with no parameters.
                            // The last one is not actually an arrow function,
                            // but this is probably what the user intended.
                            var third = nextToken();
                            switch (third) {
                                case 32 /* EqualsGreaterThanToken */:
                                case 51 /* ColonToken */:
                                case 14 /* OpenBraceToken */:
                                    return 1 /* True */;
                                default:
                                    return 0 /* False */;
                            }
                        }
                        // If encounter "([" or "({", this could be the start of a binding pattern.
                        // Examples:
                        //      ([ x ]) => { }
                        //      ({ x }) => { }
                        //      ([ x ])
                        //      ({ x })
                        if (second === 18 /* OpenBracketToken */ || second === 14 /* OpenBraceToken */) {
                            return 2 /* Unknown */;
                        }
                        // Simple case: "(..."
                        // This is an arrow function with a rest parameter.
                        if (second === 21 /* DotDotDotToken */) {
                            return 1 /* True */;
                        }
                        // If we had "(" followed by something that's not an identifier,
                        // then this definitely doesn't look like a lambda.
                        // Note: we could be a little more lenient and allow
                        // "(public" or "(private". These would not ever actually be allowed,
                        // but we could provide a good error message instead of bailing out.
                        if (!isIdentifier()) {
                            return 0 /* False */;
                        }
                        // If we have something like "(a:", then we must have a
                        // type-annotated parameter in an arrow function expression.
                        if (nextToken() === 51 /* ColonToken */) {
                            return 1 /* True */;
                        }
                        // This *could* be a parenthesized arrow function.
                        // Return Unknown to let the caller know.
                        return 2 /* Unknown */;
                    }
                    else {
                        ts.Debug.assert(first === 24 /* LessThanToken */);
                        // If we have "<" not followed by an identifier,
                        // then this definitely is not an arrow function.
                        if (!isIdentifier()) {
                            return 0 /* False */;
                        }
                        // This *could* be a parenthesized arrow function.
                        return 2 /* Unknown */;
                    }
                }
                function parsePossibleParenthesizedArrowFunctionExpressionHead() {
                    return parseParenthesizedArrowFunctionExpressionHead(false);
                }
                function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity) {
                    var node = createNode(163 /* ArrowFunction */);
                    // Arrow functions are never generators.
                    //
                    // If we're speculatively parsing a signature for a parenthesized arrow function, then
                    // we have to have a complete parameter list.  Otherwise we might see something like
                    // a => (b => c)
                    // And think that "(b =>" was actually a parenthesized arrow function with a missing
                    // close paren.
                    fillSignature(51 /* ColonToken */, false, !allowAmbiguity, node);
                    // If we couldn't get parameters, we definitely could not parse out an arrow function.
                    if (!node.parameters) {
                        return undefined;
                    }
                    // Parsing a signature isn't enough.
                    // Parenthesized arrow signatures often look like other valid expressions.
                    // For instance:
                    //  - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value.
                    //  - "(x,y)" is a comma expression parsed as a signature with two parameters.
                    //  - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation.
                    //
                    // So we need just a bit of lookahead to ensure that it can only be a signature.
                    if (!allowAmbiguity && token !== 32 /* EqualsGreaterThanToken */ && token !== 14 /* OpenBraceToken */) {
                        // Returning undefined here will cause our caller to rewind to where we started from.
                        return undefined;
                    }
                    return node;
                }
                function parseArrowFunctionExpressionBody() {
                    if (token === 14 /* OpenBraceToken */) {
                        return parseFunctionBlock(false, false);
                    }
                    if (isStartOfStatement(true) &&
                        !isStartOfExpressionStatement() &&
                        token !== 83 /* FunctionKeyword */ &&
                        token !== 69 /* ClassKeyword */) {
                        // Check if we got a plain statement (i.e. no expression-statements, no function/class expressions/declarations)
                        //
                        // Here we try to recover from a potential error situation in the case where the
                        // user meant to supply a block. For example, if the user wrote:
                        //
                        //  a =>
                        //      let v = 0;
                        //  }
                        //
                        // they may be missing an open brace.  Check to see if that's the case so we can
                        // try to recover better.  If we don't do this, then the next close curly we see may end
                        // up preemptively closing the containing construct.
                        //
                        // Note: even when 'ignoreMissingOpenBrace' is passed as true, parseBody will still error.
                        return parseFunctionBlock(false, true);
                    }
                    return parseAssignmentExpressionOrHigher();
                }
                function parseConditionalExpressionRest(leftOperand) {
                    // Note: we are passed in an expression which was produced from parseBinaryExpressionOrHigher.
                    var questionToken = parseOptionalToken(50 /* QuestionToken */);
                    if (!questionToken) {
                        return leftOperand;
                    }
                    // Note: we explicitly 'allowIn' in the whenTrue part of the condition expression, and
                    // we do not that for the 'whenFalse' part.
                    var node = createNode(170 /* ConditionalExpression */, leftOperand.pos);
                    node.condition = leftOperand;
                    node.questionToken = questionToken;
                    node.whenTrue = doOutsideOfContext(disallowInAndDecoratorContext, parseAssignmentExpressionOrHigher);
                    node.colonToken = parseExpectedToken(51 /* ColonToken */, false, ts.Diagnostics._0_expected, ts.tokenToString(51 /* ColonToken */));
                    node.whenFalse = parseAssignmentExpressionOrHigher();
                    return finishNode(node);
                }
                function parseBinaryExpressionOrHigher(precedence) {
                    var leftOperand = parseUnaryExpressionOrHigher();
                    return parseBinaryExpressionRest(precedence, leftOperand);
                }
                function isInOrOfKeyword(t) {
                    return t === 86 /* InKeyword */ || t === 125 /* OfKeyword */;
                }
                function parseBinaryExpressionRest(precedence, leftOperand) {
                    while (true) {
                        // We either have a binary operator here, or we're finished.  We call
                        // reScanGreaterToken so that we merge token sequences like > and = into >=
                        reScanGreaterToken();
                        var newPrecedence = getBinaryOperatorPrecedence();
                        // Check the precedence to see if we should "take" this operator
                        if (newPrecedence <= precedence) {
                            break;
                        }
                        if (token === 86 /* InKeyword */ && inDisallowInContext()) {
                            break;
                        }
                        leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence));
                    }
                    return leftOperand;
                }
                function isBinaryOperator() {
                    if (inDisallowInContext() && token === 86 /* InKeyword */) {
                        return false;
                    }
                    return getBinaryOperatorPrecedence() > 0;
                }
                function getBinaryOperatorPrecedence() {
                    switch (token) {
                        case 49 /* BarBarToken */:
                            return 1;
                        case 48 /* AmpersandAmpersandToken */:
                            return 2;
                        case 44 /* BarToken */:
                            return 3;
                        case 45 /* CaretToken */:
                            return 4;
                        case 43 /* AmpersandToken */:
                            return 5;
                        case 28 /* EqualsEqualsToken */:
                        case 29 /* ExclamationEqualsToken */:
                        case 30 /* EqualsEqualsEqualsToken */:
                        case 31 /* ExclamationEqualsEqualsToken */:
                            return 6;
                        case 24 /* LessThanToken */:
                        case 25 /* GreaterThanToken */:
                        case 26 /* LessThanEqualsToken */:
                        case 27 /* GreaterThanEqualsToken */:
                        case 87 /* InstanceOfKeyword */:
                        case 86 /* InKeyword */:
                            return 7;
                        case 40 /* LessThanLessThanToken */:
                        case 41 /* GreaterThanGreaterThanToken */:
                        case 42 /* GreaterThanGreaterThanGreaterThanToken */:
                            return 8;
                        case 33 /* PlusToken */:
                        case 34 /* MinusToken */:
                            return 9;
                        case 35 /* AsteriskToken */:
                        case 36 /* SlashToken */:
                        case 37 /* PercentToken */:
                            return 10;
                    }
                    // -1 is lower than all other precedences.  Returning it will cause binary expression
                    // parsing to stop.
                    return -1;
                }
                function makeBinaryExpression(left, operatorToken, right) {
                    var node = createNode(169 /* BinaryExpression */, left.pos);
                    node.left = left;
                    node.operatorToken = operatorToken;
                    node.right = right;
                    return finishNode(node);
                }
                function parsePrefixUnaryExpression() {
                    var node = createNode(167 /* PrefixUnaryExpression */);
                    node.operator = token;
                    nextToken();
                    node.operand = parseUnaryExpressionOrHigher();
                    return finishNode(node);
                }
                function parseDeleteExpression() {
                    var node = createNode(164 /* DeleteExpression */);
                    nextToken();
                    node.expression = parseUnaryExpressionOrHigher();
                    return finishNode(node);
                }
                function parseTypeOfExpression() {
                    var node = createNode(165 /* TypeOfExpression */);
                    nextToken();
                    node.expression = parseUnaryExpressionOrHigher();
                    return finishNode(node);
                }
                function parseVoidExpression() {
                    var node = createNode(166 /* VoidExpression */);
                    nextToken();
                    node.expression = parseUnaryExpressionOrHigher();
                    return finishNode(node);
                }
                function parseUnaryExpressionOrHigher() {
                    switch (token) {
                        case 33 /* PlusToken */:
                        case 34 /* MinusToken */:
                        case 47 /* TildeToken */:
                        case 46 /* ExclamationToken */:
                        case 38 /* PlusPlusToken */:
                        case 39 /* MinusMinusToken */:
                            return parsePrefixUnaryExpression();
                        case 74 /* DeleteKeyword */:
                            return parseDeleteExpression();
                        case 97 /* TypeOfKeyword */:
                            return parseTypeOfExpression();
                        case 99 /* VoidKeyword */:
                            return parseVoidExpression();
                        case 24 /* LessThanToken */:
                            return parseTypeAssertion();
                        default:
                            return parsePostfixExpressionOrHigher();
                    }
                }
                function parsePostfixExpressionOrHigher() {
                    var expression = parseLeftHandSideExpressionOrHigher();
                    ts.Debug.assert(ts.isLeftHandSideExpression(expression));
                    if ((token === 38 /* PlusPlusToken */ || token === 39 /* MinusMinusToken */) && !scanner.hasPrecedingLineBreak()) {
                        var node = createNode(168 /* PostfixUnaryExpression */, expression.pos);
                        node.operand = expression;
                        node.operator = token;
                        nextToken();
                        return finishNode(node);
                    }
                    return expression;
                }
                function parseLeftHandSideExpressionOrHigher() {
                    // Original Ecma:
                    // LeftHandSideExpression: See 11.2
                    //      NewExpression
                    //      CallExpression
                    //
                    // Our simplification:
                    //
                    // LeftHandSideExpression: See 11.2
                    //      MemberExpression
                    //      CallExpression
                    //
                    // See comment in parseMemberExpressionOrHigher on how we replaced NewExpression with
                    // MemberExpression to make our lives easier.
                    //
                    // to best understand the below code, it's important to see how CallExpression expands
                    // out into its own productions:
                    //
                    // CallExpression:
                    //      MemberExpression Arguments
                    //      CallExpression Arguments
                    //      CallExpression[Expression]
                    //      CallExpression.IdentifierName
                    //      super   (   ArgumentListopt   )
                    //      super.IdentifierName
                    //
                    // Because of the recursion in these calls, we need to bottom out first.  There are two
                    // bottom out states we can run into.  Either we see 'super' which must start either of
                    // the last two CallExpression productions.  Or we have a MemberExpression which either
                    // completes the LeftHandSideExpression, or starts the beginning of the first four
                    // CallExpression productions.
                    var expression = token === 91 /* SuperKeyword */
                        ? parseSuperExpression()
                        : parseMemberExpressionOrHigher();
                    // Now, we *may* be complete.  However, we might have consumed the start of a
                    // CallExpression.  As such, we need to consume the rest of it here to be complete.
                    return parseCallExpressionRest(expression);
                }
                function parseMemberExpressionOrHigher() {
                    // Note: to make our lives simpler, we decompose the the NewExpression productions and
                    // place ObjectCreationExpression and FunctionExpression into PrimaryExpression.
                    // like so:
                    //
                    //   PrimaryExpression : See 11.1
                    //      this
                    //      Identifier
                    //      Literal
                    //      ArrayLiteral
                    //      ObjectLiteral
                    //      (Expression)
                    //      FunctionExpression
                    //      new MemberExpression Arguments?
                    //
                    //   MemberExpression : See 11.2
                    //      PrimaryExpression
                    //      MemberExpression[Expression]
                    //      MemberExpression.IdentifierName
                    //
                    //   CallExpression : See 11.2
                    //      MemberExpression
                    //      CallExpression Arguments
                    //      CallExpression[Expression]
                    //      CallExpression.IdentifierName
                    //
                    // Technically this is ambiguous.  i.e. CallExpression defines:
                    //
                    //   CallExpression:
                    //      CallExpression Arguments
                    //
                    // If you see: "new Foo()"
                    //
                    // Then that could be treated as a single ObjectCreationExpression, or it could be
                    // treated as the invocation of "new Foo".  We disambiguate that in code (to match
                    // the original grammar) by making sure that if we see an ObjectCreationExpression
                    // we always consume arguments if they are there. So we treat "new Foo()" as an
                    // object creation only, and not at all as an invocation)  Another way to think
                    // about this is that for every "new" that we see, we will consume an argument list if
                    // it is there as part of the *associated* object creation node.  Any additional
                    // argument lists we see, will become invocation expressions.
                    //
                    // Because there are no other places in the grammar now that refer to FunctionExpression
                    // or ObjectCreationExpression, it is safe to push down into the PrimaryExpression
                    // production.
                    //
                    // Because CallExpression and MemberExpression are left recursive, we need to bottom out
                    // of the recursion immediately.  So we parse out a primary expression to start with.
                    var expression = parsePrimaryExpression();
                    return parseMemberExpressionRest(expression);
                }
                function parseSuperExpression() {
                    var expression = parseTokenNode();
                    if (token === 16 /* OpenParenToken */ || token === 20 /* DotToken */) {
                        return expression;
                    }
                    // If we have seen "super" it must be followed by '(' or '.'.
                    // If it wasn't then just try to parse out a '.' and report an error.
                    var node = createNode(155 /* PropertyAccessExpression */, expression.pos);
                    node.expression = expression;
                    node.dotToken = parseExpectedToken(20 /* DotToken */, false, ts.Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access);
                    node.name = parseRightSideOfDot(true);
                    return finishNode(node);
                }
                function parseTypeAssertion() {
                    var node = createNode(160 /* TypeAssertionExpression */);
                    parseExpected(24 /* LessThanToken */);
                    node.type = parseType();
                    parseExpected(25 /* GreaterThanToken */);
                    node.expression = parseUnaryExpressionOrHigher();
                    return finishNode(node);
                }
                function parseMemberExpressionRest(expression) {
                    while (true) {
                        var dotToken = parseOptionalToken(20 /* DotToken */);
                        if (dotToken) {
                            var propertyAccess = createNode(155 /* PropertyAccessExpression */, expression.pos);
                            propertyAccess.expression = expression;
                            propertyAccess.dotToken = dotToken;
                            propertyAccess.name = parseRightSideOfDot(true);
                            expression = finishNode(propertyAccess);
                            continue;
                        }
                        // when in the [Decorator] context, we do not parse ElementAccess as it could be part of a ComputedPropertyName                
                        if (!inDecoratorContext() && parseOptional(18 /* OpenBracketToken */)) {
                            var indexedAccess = createNode(156 /* ElementAccessExpression */, expression.pos);
                            indexedAccess.expression = expression;
                            // It's not uncommon for a user to write: "new Type[]".
                            // Check for that common pattern and report a better error message.
                            if (token !== 19 /* CloseBracketToken */) {
                                indexedAccess.argumentExpression = allowInAnd(parseExpression);
                                if (indexedAccess.argumentExpression.kind === 8 /* StringLiteral */ || indexedAccess.argumentExpression.kind === 7 /* NumericLiteral */) {
                                    var literal = indexedAccess.argumentExpression;
                                    literal.text = internIdentifier(literal.text);
                                }
                            }
                            parseExpected(19 /* CloseBracketToken */);
                            expression = finishNode(indexedAccess);
                            continue;
                        }
                        if (token === 10 /* NoSubstitutionTemplateLiteral */ || token === 11 /* TemplateHead */) {
                            var tagExpression = createNode(159 /* TaggedTemplateExpression */, expression.pos);
                            tagExpression.tag = expression;
                            tagExpression.template = token === 10 /* NoSubstitutionTemplateLiteral */
                                ? parseLiteralNode()
                                : parseTemplateExpression();
                            expression = finishNode(tagExpression);
                            continue;
                        }
                        return expression;
                    }
                }
                function parseCallExpressionRest(expression) {
                    while (true) {
                        expression = parseMemberExpressionRest(expression);
                        if (token === 24 /* LessThanToken */) {
                            // See if this is the start of a generic invocation.  If so, consume it and
                            // keep checking for postfix expressions.  Otherwise, it's just a '<' that's
                            // part of an arithmetic expression.  Break out so we consume it higher in the
                            // stack.
                            var typeArguments = tryParse(parseTypeArgumentsInExpression);
                            if (!typeArguments) {
                                return expression;
                            }
                            var callExpr = createNode(157 /* CallExpression */, expression.pos);
                            callExpr.expression = expression;
                            callExpr.typeArguments = typeArguments;
                            callExpr.arguments = parseArgumentList();
                            expression = finishNode(callExpr);
                            continue;
                        }
                        else if (token === 16 /* OpenParenToken */) {
                            var callExpr = createNode(157 /* CallExpression */, expression.pos);
                            callExpr.expression = expression;
                            callExpr.arguments = parseArgumentList();
                            expression = finishNode(callExpr);
                            continue;
                        }
                        return expression;
                    }
                }
                function parseArgumentList() {
                    parseExpected(16 /* OpenParenToken */);
                    var result = parseDelimitedList(12 /* ArgumentExpressions */, parseArgumentExpression);
                    parseExpected(17 /* CloseParenToken */);
                    return result;
                }
                function parseTypeArgumentsInExpression() {
                    if (!parseOptional(24 /* LessThanToken */)) {
                        return undefined;
                    }
                    var typeArguments = parseDelimitedList(17 /* TypeArguments */, parseType);
                    if (!parseExpected(25 /* GreaterThanToken */)) {
                        // If it doesn't have the closing >  then it's definitely not an type argument list.
                        return undefined;
                    }
                    // If we have a '<', then only parse this as a arugment list if the type arguments
                    // are complete and we have an open paren.  if we don't, rewind and return nothing.
                    return typeArguments && canFollowTypeArgumentsInExpression()
                        ? typeArguments
                        : undefined;
                }
                function canFollowTypeArgumentsInExpression() {
                    switch (token) {
                        case 16 /* OpenParenToken */: // foo<x>(
                        // this case are the only case where this token can legally follow a type argument
                        // list.  So we definitely want to treat this as a type arg list.
                        case 20 /* DotToken */: // foo<x>.
                        case 17 /* CloseParenToken */: // foo<x>)
                        case 19 /* CloseBracketToken */: // foo<x>]
                        case 51 /* ColonToken */: // foo<x>:
                        case 22 /* SemicolonToken */: // foo<x>;
                        case 50 /* QuestionToken */: // foo<x>?
                        case 28 /* EqualsEqualsToken */: // foo<x> ==
                        case 30 /* EqualsEqualsEqualsToken */: // foo<x> ===
                        case 29 /* ExclamationEqualsToken */: // foo<x> !=
                        case 31 /* ExclamationEqualsEqualsToken */: // foo<x> !==
                        case 48 /* AmpersandAmpersandToken */: // foo<x> &&
                        case 49 /* BarBarToken */: // foo<x> ||
                        case 45 /* CaretToken */: // foo<x> ^
                        case 43 /* AmpersandToken */: // foo<x> &
                        case 44 /* BarToken */: // foo<x> |
                        case 15 /* CloseBraceToken */: // foo<x> }
                        case 1 /* EndOfFileToken */:
                            // these cases can't legally follow a type arg list.  However, they're not legal
                            // expressions either.  The user is probably in the middle of a generic type. So
                            // treat it as such.
                            return true;
                        case 23 /* CommaToken */: // foo<x>,
                        case 14 /* OpenBraceToken */: // foo<x> {
                        // We don't want to treat these as type arguments.  Otherwise we'll parse this
                        // as an invocation expression.  Instead, we want to parse out the expression 
                        // in isolation from the type arguments.
                        default:
                            // Anything else treat as an expression.
                            return false;
                    }
                }
                function parsePrimaryExpression() {
                    switch (token) {
                        case 7 /* NumericLiteral */:
                        case 8 /* StringLiteral */:
                        case 10 /* NoSubstitutionTemplateLiteral */:
                            return parseLiteralNode();
                        case 93 /* ThisKeyword */:
                        case 91 /* SuperKeyword */:
                        case 89 /* NullKeyword */:
                        case 95 /* TrueKeyword */:
                        case 80 /* FalseKeyword */:
                            return parseTokenNode();
                        case 16 /* OpenParenToken */:
                            return parseParenthesizedExpression();
                        case 18 /* OpenBracketToken */:
                            return parseArrayLiteralExpression();
                        case 14 /* OpenBraceToken */:
                            return parseObjectLiteralExpression();
                        case 69 /* ClassKeyword */:
                            return parseClassExpression();
                        case 83 /* FunctionKeyword */:
                            return parseFunctionExpression();
                        case 88 /* NewKeyword */:
                            return parseNewExpression();
                        case 36 /* SlashToken */:
                        case 57 /* SlashEqualsToken */:
                            if (reScanSlashToken() === 9 /* RegularExpressionLiteral */) {
                                return parseLiteralNode();
                            }
                            break;
                        case 11 /* TemplateHead */:
                            return parseTemplateExpression();
                    }
                    return parseIdentifier(ts.Diagnostics.Expression_expected);
                }
                function parseParenthesizedExpression() {
                    var node = createNode(161 /* ParenthesizedExpression */);
                    parseExpected(16 /* OpenParenToken */);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(17 /* CloseParenToken */);
                    return finishNode(node);
                }
                function parseSpreadElement() {
                    var node = createNode(173 /* SpreadElementExpression */);
                    parseExpected(21 /* DotDotDotToken */);
                    node.expression = parseAssignmentExpressionOrHigher();
                    return finishNode(node);
                }
                function parseArgumentOrArrayLiteralElement() {
                    return token === 21 /* DotDotDotToken */ ? parseSpreadElement() :
                        token === 23 /* CommaToken */ ? createNode(175 /* OmittedExpression */) :
                            parseAssignmentExpressionOrHigher();
                }
                function parseArgumentExpression() {
                    return doOutsideOfContext(disallowInAndDecoratorContext, parseArgumentOrArrayLiteralElement);
                }
                function parseArrayLiteralExpression() {
                    var node = createNode(153 /* ArrayLiteralExpression */);
                    parseExpected(18 /* OpenBracketToken */);
                    if (scanner.hasPrecedingLineBreak())
                        node.flags |= 512 /* MultiLine */;
                    node.elements = parseDelimitedList(14 /* ArrayLiteralMembers */, parseArgumentOrArrayLiteralElement);
                    parseExpected(19 /* CloseBracketToken */);
                    return finishNode(node);
                }
                function tryParseAccessorDeclaration(fullStart, decorators, modifiers) {
                    if (parseContextualModifier(116 /* GetKeyword */)) {
                        return parseAccessorDeclaration(136 /* GetAccessor */, fullStart, decorators, modifiers);
                    }
                    else if (parseContextualModifier(120 /* SetKeyword */)) {
                        return parseAccessorDeclaration(137 /* SetAccessor */, fullStart, decorators, modifiers);
                    }
                    return undefined;
                }
                function parseObjectLiteralElement() {
                    var fullStart = scanner.getStartPos();
                    var decorators = parseDecorators();
                    var modifiers = parseModifiers();
                    var accessor = tryParseAccessorDeclaration(fullStart, decorators, modifiers);
                    if (accessor) {
                        return accessor;
                    }
                    var asteriskToken = parseOptionalToken(35 /* AsteriskToken */);
                    var tokenIsIdentifier = isIdentifier();
                    var nameToken = token;
                    var propertyName = parsePropertyName();
                    // Disallowing of optional property assignments happens in the grammar checker.
                    var questionToken = parseOptionalToken(50 /* QuestionToken */);
                    if (asteriskToken || token === 16 /* OpenParenToken */ || token === 24 /* LessThanToken */) {
                        return parseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, propertyName, questionToken);
                    }
                    // Parse to check if it is short-hand property assignment or normal property assignment
                    if ((token === 23 /* CommaToken */ || token === 15 /* CloseBraceToken */) && tokenIsIdentifier) {
                        var shorthandDeclaration = createNode(225 /* ShorthandPropertyAssignment */, fullStart);
                        shorthandDeclaration.name = propertyName;
                        shorthandDeclaration.questionToken = questionToken;
                        return finishNode(shorthandDeclaration);
                    }
                    else {
                        var propertyAssignment = createNode(224 /* PropertyAssignment */, fullStart);
                        propertyAssignment.name = propertyName;
                        propertyAssignment.questionToken = questionToken;
                        parseExpected(51 /* ColonToken */);
                        propertyAssignment.initializer = allowInAnd(parseAssignmentExpressionOrHigher);
                        return finishNode(propertyAssignment);
                    }
                }
                function parseObjectLiteralExpression() {
                    var node = createNode(154 /* ObjectLiteralExpression */);
                    parseExpected(14 /* OpenBraceToken */);
                    if (scanner.hasPrecedingLineBreak()) {
                        node.flags |= 512 /* MultiLine */;
                    }
                    node.properties = parseDelimitedList(13 /* ObjectLiteralMembers */, parseObjectLiteralElement, true);
                    parseExpected(15 /* CloseBraceToken */);
                    return finishNode(node);
                }
                function parseFunctionExpression() {
                    // GeneratorExpression :
                    //      function * BindingIdentifier[Yield]opt (FormalParameters[Yield, GeneratorParameter]) { GeneratorBody[Yield] }
                    // FunctionExpression:
                    //      function BindingIdentifieropt(FormalParameters) { FunctionBody }
                    var saveDecoratorContext = inDecoratorContext();
                    if (saveDecoratorContext) {
                        setDecoratorContext(false);
                    }
                    var node = createNode(162 /* FunctionExpression */);
                    parseExpected(83 /* FunctionKeyword */);
                    node.asteriskToken = parseOptionalToken(35 /* AsteriskToken */);
                    node.name = node.asteriskToken ? doInYieldContext(parseOptionalIdentifier) : parseOptionalIdentifier();
                    fillSignature(51 /* ColonToken */, !!node.asteriskToken, false, node);
                    node.body = parseFunctionBlock(!!node.asteriskToken, false);
                    if (saveDecoratorContext) {
                        setDecoratorContext(true);
                    }
                    return finishNode(node);
                }
                function parseOptionalIdentifier() {
                    return isIdentifier() ? parseIdentifier() : undefined;
                }
                function parseNewExpression() {
                    var node = createNode(158 /* NewExpression */);
                    parseExpected(88 /* NewKeyword */);
                    node.expression = parseMemberExpressionOrHigher();
                    node.typeArguments = tryParse(parseTypeArgumentsInExpression);
                    if (node.typeArguments || token === 16 /* OpenParenToken */) {
                        node.arguments = parseArgumentList();
                    }
                    return finishNode(node);
                }
                // STATEMENTS
                function parseBlock(ignoreMissingOpenBrace, checkForStrictMode, diagnosticMessage) {
                    var node = createNode(179 /* Block */);
                    if (parseExpected(14 /* OpenBraceToken */, diagnosticMessage) || ignoreMissingOpenBrace) {
                        node.statements = parseList(2 /* BlockStatements */, checkForStrictMode, parseStatement);
                        parseExpected(15 /* CloseBraceToken */);
                    }
                    else {
                        node.statements = createMissingList();
                    }
                    return finishNode(node);
                }
                function parseFunctionBlock(allowYield, ignoreMissingOpenBrace, diagnosticMessage) {
                    var savedYieldContext = inYieldContext();
                    setYieldContext(allowYield);
                    // We may be in a [Decorator] context when parsing a function expression or 
                    // arrow function. The body of the function is not in [Decorator] context.
                    var saveDecoratorContext = inDecoratorContext();
                    if (saveDecoratorContext) {
                        setDecoratorContext(false);
                    }
                    var block = parseBlock(ignoreMissingOpenBrace, true, diagnosticMessage);
                    if (saveDecoratorContext) {
                        setDecoratorContext(true);
                    }
                    setYieldContext(savedYieldContext);
                    return block;
                }
                function parseEmptyStatement() {
                    var node = createNode(181 /* EmptyStatement */);
                    parseExpected(22 /* SemicolonToken */);
                    return finishNode(node);
                }
                function parseIfStatement() {
                    var node = createNode(183 /* IfStatement */);
                    parseExpected(84 /* IfKeyword */);
                    parseExpected(16 /* OpenParenToken */);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(17 /* CloseParenToken */);
                    node.thenStatement = parseStatement();
                    node.elseStatement = parseOptional(76 /* ElseKeyword */) ? parseStatement() : undefined;
                    return finishNode(node);
                }
                function parseDoStatement() {
                    var node = createNode(184 /* DoStatement */);
                    parseExpected(75 /* DoKeyword */);
                    node.statement = parseStatement();
                    parseExpected(100 /* WhileKeyword */);
                    parseExpected(16 /* OpenParenToken */);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(17 /* CloseParenToken */);
                    // From: https://mail.mozilla.org/pipermail/es-discuss/2011-August/016188.html
                    // 157 min --- All allen at wirfs-brock.com CONF --- "do{;}while(false)false" prohibited in
                    // spec but allowed in consensus reality. Approved -- this is the de-facto standard whereby
                    //  do;while(0)x will have a semicolon inserted before x.
                    parseOptional(22 /* SemicolonToken */);
                    return finishNode(node);
                }
                function parseWhileStatement() {
                    var node = createNode(185 /* WhileStatement */);
                    parseExpected(100 /* WhileKeyword */);
                    parseExpected(16 /* OpenParenToken */);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(17 /* CloseParenToken */);
                    node.statement = parseStatement();
                    return finishNode(node);
                }
                function parseForOrForInOrForOfStatement() {
                    var pos = getNodePos();
                    parseExpected(82 /* ForKeyword */);
                    parseExpected(16 /* OpenParenToken */);
                    var initializer = undefined;
                    if (token !== 22 /* SemicolonToken */) {
                        if (token === 98 /* VarKeyword */ || token === 104 /* LetKeyword */ || token === 70 /* ConstKeyword */) {
                            initializer = parseVariableDeclarationList(true);
                        }
                        else {
                            initializer = disallowInAnd(parseExpression);
                        }
                    }
                    var forOrForInOrForOfStatement;
                    if (parseOptional(86 /* InKeyword */)) {
                        var forInStatement = createNode(187 /* ForInStatement */, pos);
                        forInStatement.initializer = initializer;
                        forInStatement.expression = allowInAnd(parseExpression);
                        parseExpected(17 /* CloseParenToken */);
                        forOrForInOrForOfStatement = forInStatement;
                    }
                    else if (parseOptional(125 /* OfKeyword */)) {
                        var forOfStatement = createNode(188 /* ForOfStatement */, pos);
                        forOfStatement.initializer = initializer;
                        forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher);
                        parseExpected(17 /* CloseParenToken */);
                        forOrForInOrForOfStatement = forOfStatement;
                    }
                    else {
                        var forStatement = createNode(186 /* ForStatement */, pos);
                        forStatement.initializer = initializer;
                        parseExpected(22 /* SemicolonToken */);
                        if (token !== 22 /* SemicolonToken */ && token !== 17 /* CloseParenToken */) {
                            forStatement.condition = allowInAnd(parseExpression);
                        }
                        parseExpected(22 /* SemicolonToken */);
                        if (token !== 17 /* CloseParenToken */) {
                            forStatement.incrementor = allowInAnd(parseExpression);
                        }
                        parseExpected(17 /* CloseParenToken */);
                        forOrForInOrForOfStatement = forStatement;
                    }
                    forOrForInOrForOfStatement.statement = parseStatement();
                    return finishNode(forOrForInOrForOfStatement);
                }
                function parseBreakOrContinueStatement(kind) {
                    var node = createNode(kind);
                    parseExpected(kind === 190 /* BreakStatement */ ? 66 /* BreakKeyword */ : 71 /* ContinueKeyword */);
                    if (!canParseSemicolon()) {
                        node.label = parseIdentifier();
                    }
                    parseSemicolon();
                    return finishNode(node);
                }
                function parseReturnStatement() {
                    var node = createNode(191 /* ReturnStatement */);
                    parseExpected(90 /* ReturnKeyword */);
                    if (!canParseSemicolon()) {
                        node.expression = allowInAnd(parseExpression);
                    }
                    parseSemicolon();
                    return finishNode(node);
                }
                function parseWithStatement() {
                    var node = createNode(192 /* WithStatement */);
                    parseExpected(101 /* WithKeyword */);
                    parseExpected(16 /* OpenParenToken */);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(17 /* CloseParenToken */);
                    node.statement = parseStatement();
                    return finishNode(node);
                }
                function parseCaseClause() {
                    var node = createNode(220 /* CaseClause */);
                    parseExpected(67 /* CaseKeyword */);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(51 /* ColonToken */);
                    node.statements = parseList(4 /* SwitchClauseStatements */, false, parseStatement);
                    return finishNode(node);
                }
                function parseDefaultClause() {
                    var node = createNode(221 /* DefaultClause */);
                    parseExpected(73 /* DefaultKeyword */);
                    parseExpected(51 /* ColonToken */);
                    node.statements = parseList(4 /* SwitchClauseStatements */, false, parseStatement);
                    return finishNode(node);
                }
                function parseCaseOrDefaultClause() {
                    return token === 67 /* CaseKeyword */ ? parseCaseClause() : parseDefaultClause();
                }
                function parseSwitchStatement() {
                    var node = createNode(193 /* SwitchStatement */);
                    parseExpected(92 /* SwitchKeyword */);
                    parseExpected(16 /* OpenParenToken */);
                    node.expression = allowInAnd(parseExpression);
                    parseExpected(17 /* CloseParenToken */);
                    var caseBlock = createNode(207 /* CaseBlock */, scanner.getStartPos());
                    parseExpected(14 /* OpenBraceToken */);
                    caseBlock.clauses = parseList(3 /* SwitchClauses */, false, parseCaseOrDefaultClause);
                    parseExpected(15 /* CloseBraceToken */);
                    node.caseBlock = finishNode(caseBlock);
                    return finishNode(node);
                }
                function parseThrowStatement() {
                    // ThrowStatement[Yield] :
                    //      throw [no LineTerminator here]Expression[In, ?Yield];
                    // Because of automatic semicolon insertion, we need to report error if this
                    // throw could be terminated with a semicolon.  Note: we can't call 'parseExpression'
                    // directly as that might consume an expression on the following line.
                    // We just return 'undefined' in that case.  The actual error will be reported in the
                    // grammar walker.
                    var node = createNode(195 /* ThrowStatement */);
                    parseExpected(94 /* ThrowKeyword */);
                    node.expression = scanner.hasPrecedingLineBreak() ? undefined : allowInAnd(parseExpression);
                    parseSemicolon();
                    return finishNode(node);
                }
                // TODO: Review for error recovery
                function parseTryStatement() {
                    var node = createNode(196 /* TryStatement */);
                    parseExpected(96 /* TryKeyword */);
                    node.tryBlock = parseBlock(false, false);
                    node.catchClause = token === 68 /* CatchKeyword */ ? parseCatchClause() : undefined;
                    // If we don't have a catch clause, then we must have a finally clause.  Try to parse
                    // one out no matter what.
                    if (!node.catchClause || token === 81 /* FinallyKeyword */) {
                        parseExpected(81 /* FinallyKeyword */);
                        node.finallyBlock = parseBlock(false, false);
                    }
                    return finishNode(node);
                }
                function parseCatchClause() {
                    var result = createNode(223 /* CatchClause */);
                    parseExpected(68 /* CatchKeyword */);
                    if (parseExpected(16 /* OpenParenToken */)) {
                        result.variableDeclaration = parseVariableDeclaration();
                    }
                    parseExpected(17 /* CloseParenToken */);
                    result.block = parseBlock(false, false);
                    return finishNode(result);
                }
                function parseDebuggerStatement() {
                    var node = createNode(197 /* DebuggerStatement */);
                    parseExpected(72 /* DebuggerKeyword */);
                    parseSemicolon();
                    return finishNode(node);
                }
                function parseExpressionOrLabeledStatement() {
                    // Avoiding having to do the lookahead for a labeled statement by just trying to parse
                    // out an expression, seeing if it is identifier and then seeing if it is followed by
                    // a colon.
                    var fullStart = scanner.getStartPos();
                    var expression = allowInAnd(parseExpression);
                    if (expression.kind === 65 /* Identifier */ && parseOptional(51 /* ColonToken */)) {
                        var labeledStatement = createNode(194 /* LabeledStatement */, fullStart);
                        labeledStatement.label = expression;
                        labeledStatement.statement = parseStatement();
                        return finishNode(labeledStatement);
                    }
                    else {
                        var expressionStatement = createNode(182 /* ExpressionStatement */, fullStart);
                        expressionStatement.expression = expression;
                        parseSemicolon();
                        return finishNode(expressionStatement);
                    }
                }
                function isStartOfStatement(inErrorRecovery) {
                    // Functions, variable statements and classes are allowed as a statement.  But as per
                    // the grammar, they also allow modifiers.  So we have to check for those statements 
                    // that might be following modifiers.This ensures that things work properly when
                    // incrementally parsing as the parser will produce the same FunctionDeclaraiton, 
                    // VariableStatement or ClassDeclaration, if it has the same text regardless of whether 
                    // it is inside a block or not.
                    if (ts.isModifier(token)) {
                        var result = lookAhead(parseVariableStatementOrFunctionDeclarationOrClassDeclarationWithDecoratorsOrModifiers);
                        if (result) {
                            return true;
                        }
                    }
                    switch (token) {
                        case 22 /* SemicolonToken */:
                            // If we're in error recovery, then we don't want to treat ';' as an empty statement.
                            // The problem is that ';' can show up in far too many contexts, and if we see one
                            // and assume it's a statement, then we may bail out inappropriately from whatever
                            // we're parsing.  For example, if we have a semicolon in the middle of a class, then
                            // we really don't want to assume the class is over and we're on a statement in the
                            // outer module.  We just want to consume and move on.
                            return !inErrorRecovery;
                        case 14 /* OpenBraceToken */:
                        case 98 /* VarKeyword */:
                        case 104 /* LetKeyword */:
                        case 83 /* FunctionKeyword */:
                        case 69 /* ClassKeyword */:
                        case 84 /* IfKeyword */:
                        case 75 /* DoKeyword */:
                        case 100 /* WhileKeyword */:
                        case 82 /* ForKeyword */:
                        case 71 /* ContinueKeyword */:
                        case 66 /* BreakKeyword */:
                        case 90 /* ReturnKeyword */:
                        case 101 /* WithKeyword */:
                        case 92 /* SwitchKeyword */:
                        case 94 /* ThrowKeyword */:
                        case 96 /* TryKeyword */:
                        case 72 /* DebuggerKeyword */:
                        // 'catch' and 'finally' do not actually indicate that the code is part of a statement,
                        // however, we say they are here so that we may gracefully parse them and error later.
                        case 68 /* CatchKeyword */:
                        case 81 /* FinallyKeyword */:
                            return true;
                        case 70 /* ConstKeyword */:
                            // const keyword can precede enum keyword when defining constant enums
                            // 'const enum' do not start statement.
                            // In ES 6 'enum' is a future reserved keyword, so it should not be used as identifier
                            var isConstEnum = lookAhead(nextTokenIsEnumKeyword);
                            return !isConstEnum;
                        case 103 /* InterfaceKeyword */:
                        case 117 /* ModuleKeyword */:
                        case 77 /* EnumKeyword */:
                        case 123 /* TypeKeyword */:
                            // When followed by an identifier, these do not start a statement but might
                            // instead be following declarations
                            if (isDeclarationStart()) {
                                return false;
                            }
                        case 108 /* PublicKeyword */:
                        case 106 /* PrivateKeyword */:
                        case 107 /* ProtectedKeyword */:
                        case 109 /* StaticKeyword */:
                            // When followed by an identifier or keyword, these do not start a statement but
                            // might instead be following type members
                            if (lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine)) {
                                return false;
                            }
                        default:
                            return isStartOfExpression();
                    }
                }
                function nextTokenIsEnumKeyword() {
                    nextToken();
                    return token === 77 /* EnumKeyword */;
                }
                function nextTokenIsIdentifierOrKeywordOnSameLine() {
                    nextToken();
                    return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak();
                }
                function parseStatement() {
                    switch (token) {
                        case 14 /* OpenBraceToken */:
                            return parseBlock(false, false);
                        case 98 /* VarKeyword */:
                        case 70 /* ConstKeyword */:
                            // const here should always be parsed as const declaration because of check in 'isStatement'
                            return parseVariableStatement(scanner.getStartPos(), undefined, undefined);
                        case 83 /* FunctionKeyword */:
                            return parseFunctionDeclaration(scanner.getStartPos(), undefined, undefined);
                        case 69 /* ClassKeyword */:
                            return parseClassDeclaration(scanner.getStartPos(), undefined, undefined);
                        case 22 /* SemicolonToken */:
                            return parseEmptyStatement();
                        case 84 /* IfKeyword */:
                            return parseIfStatement();
                        case 75 /* DoKeyword */:
                            return parseDoStatement();
                        case 100 /* WhileKeyword */:
                            return parseWhileStatement();
                        case 82 /* ForKeyword */:
                            return parseForOrForInOrForOfStatement();
                        case 71 /* ContinueKeyword */:
                            return parseBreakOrContinueStatement(189 /* ContinueStatement */);
                        case 66 /* BreakKeyword */:
                            return parseBreakOrContinueStatement(190 /* BreakStatement */);
                        case 90 /* ReturnKeyword */:
                            return parseReturnStatement();
                        case 101 /* WithKeyword */:
                            return parseWithStatement();
                        case 92 /* SwitchKeyword */:
                            return parseSwitchStatement();
                        case 94 /* ThrowKeyword */:
                            return parseThrowStatement();
                        case 96 /* TryKeyword */:
                        // Include the next two for error recovery.
                        case 68 /* CatchKeyword */:
                        case 81 /* FinallyKeyword */:
                            return parseTryStatement();
                        case 72 /* DebuggerKeyword */:
                            return parseDebuggerStatement();
                        case 104 /* LetKeyword */:
                            // If let follows identifier on the same line, it is declaration parse it as variable statement
                            if (isLetDeclaration()) {
                                return parseVariableStatement(scanner.getStartPos(), undefined, undefined);
                            }
                        // Else parse it like identifier - fall through
                        default:
                            // Functions and variable statements are allowed as a statement.  But as per
                            // the grammar, they also allow modifiers.  So we have to check for those
                            // statements that might be following modifiers.  This ensures that things
                            // work properly when incrementally parsing as the parser will produce the
                            // same FunctionDeclaraiton or VariableStatement if it has the same text
                            // regardless of whether it is inside a block or not.
                            // Even though variable statements and function declarations cannot have decorators, 
                            // we parse them here to provide better error recovery.
                            if (ts.isModifier(token) || token === 52 /* AtToken */) {
                                var result = tryParse(parseVariableStatementOrFunctionDeclarationOrClassDeclarationWithDecoratorsOrModifiers);
                                if (result) {
                                    return result;
                                }
                            }
                            return parseExpressionOrLabeledStatement();
                    }
                }
                function parseVariableStatementOrFunctionDeclarationOrClassDeclarationWithDecoratorsOrModifiers() {
                    var start = scanner.getStartPos();
                    var decorators = parseDecorators();
                    var modifiers = parseModifiers();
                    switch (token) {
                        case 70 /* ConstKeyword */:
                            var nextTokenIsEnum = lookAhead(nextTokenIsEnumKeyword);
                            if (nextTokenIsEnum) {
                                return undefined;
                            }
                            return parseVariableStatement(start, decorators, modifiers);
                        case 104 /* LetKeyword */:
                            if (!isLetDeclaration()) {
                                return undefined;
                            }
                            return parseVariableStatement(start, decorators, modifiers);
                        case 98 /* VarKeyword */:
                            return parseVariableStatement(start, decorators, modifiers);
                        case 83 /* FunctionKeyword */:
                            return parseFunctionDeclaration(start, decorators, modifiers);
                        case 69 /* ClassKeyword */:
                            return parseClassDeclaration(start, decorators, modifiers);
                    }
                    return undefined;
                }
                function parseFunctionBlockOrSemicolon(isGenerator, diagnosticMessage) {
                    if (token !== 14 /* OpenBraceToken */ && canParseSemicolon()) {
                        parseSemicolon();
                        return;
                    }
                    return parseFunctionBlock(isGenerator, false, diagnosticMessage);
                }
                // DECLARATIONS
                function parseArrayBindingElement() {
                    if (token === 23 /* CommaToken */) {
                        return createNode(175 /* OmittedExpression */);
                    }
                    var node = createNode(152 /* BindingElement */);
                    node.dotDotDotToken = parseOptionalToken(21 /* DotDotDotToken */);
                    node.name = parseIdentifierOrPattern();
                    node.initializer = parseInitializer(false);
                    return finishNode(node);
                }
                function parseObjectBindingElement() {
                    var node = createNode(152 /* BindingElement */);
                    // TODO(andersh): Handle computed properties
                    var tokenIsIdentifier = isIdentifier();
                    var propertyName = parsePropertyName();
                    if (tokenIsIdentifier && token !== 51 /* ColonToken */) {
                        node.name = propertyName;
                    }
                    else {
                        parseExpected(51 /* ColonToken */);
                        node.propertyName = propertyName;
                        node.name = parseIdentifierOrPattern();
                    }
                    node.initializer = parseInitializer(false);
                    return finishNode(node);
                }
                function parseObjectBindingPattern() {
                    var node = createNode(150 /* ObjectBindingPattern */);
                    parseExpected(14 /* OpenBraceToken */);
                    node.elements = parseDelimitedList(10 /* ObjectBindingElements */, parseObjectBindingElement);
                    parseExpected(15 /* CloseBraceToken */);
                    return finishNode(node);
                }
                function parseArrayBindingPattern() {
                    var node = createNode(151 /* ArrayBindingPattern */);
                    parseExpected(18 /* OpenBracketToken */);
                    node.elements = parseDelimitedList(11 /* ArrayBindingElements */, parseArrayBindingElement);
                    parseExpected(19 /* CloseBracketToken */);
                    return finishNode(node);
                }
                function isIdentifierOrPattern() {
                    return token === 14 /* OpenBraceToken */ || token === 18 /* OpenBracketToken */ || isIdentifier();
                }
                function parseIdentifierOrPattern() {
                    if (token === 18 /* OpenBracketToken */) {
                        return parseArrayBindingPattern();
                    }
                    if (token === 14 /* OpenBraceToken */) {
                        return parseObjectBindingPattern();
                    }
                    return parseIdentifier();
                }
                function parseVariableDeclaration() {
                    var node = createNode(198 /* VariableDeclaration */);
                    node.name = parseIdentifierOrPattern();
                    node.type = parseTypeAnnotation();
                    if (!isInOrOfKeyword(token)) {
                        node.initializer = parseInitializer(false);
                    }
                    return finishNode(node);
                }
                function parseVariableDeclarationList(inForStatementInitializer) {
                    var node = createNode(199 /* VariableDeclarationList */);
                    switch (token) {
                        case 98 /* VarKeyword */:
                            break;
                        case 104 /* LetKeyword */:
                            node.flags |= 4096 /* Let */;
                            break;
                        case 70 /* ConstKeyword */:
                            node.flags |= 8192 /* Const */;
                            break;
                        default:
                            ts.Debug.fail();
                    }
                    nextToken();
                    // The user may have written the following:
                    //
                    //    for (let of X) { }
                    //
                    // In this case, we want to parse an empty declaration list, and then parse 'of'
                    // as a keyword. The reason this is not automatic is that 'of' is a valid identifier.
                    // So we need to look ahead to determine if 'of' should be treated as a keyword in
                    // this context.
                    // The checker will then give an error that there is an empty declaration list.
                    if (token === 125 /* OfKeyword */ && lookAhead(canFollowContextualOfKeyword)) {
                        node.declarations = createMissingList();
                    }
                    else {
                        var savedDisallowIn = inDisallowInContext();
                        setDisallowInContext(inForStatementInitializer);
                        node.declarations = parseDelimitedList(9 /* VariableDeclarations */, parseVariableDeclaration);
                        setDisallowInContext(savedDisallowIn);
                    }
                    return finishNode(node);
                }
                function canFollowContextualOfKeyword() {
                    return nextTokenIsIdentifier() && nextToken() === 17 /* CloseParenToken */;
                }
                function parseVariableStatement(fullStart, decorators, modifiers) {
                    var node = createNode(180 /* VariableStatement */, fullStart);
                    node.decorators = decorators;
                    setModifiers(node, modifiers);
                    node.declarationList = parseVariableDeclarationList(false);
                    parseSemicolon();
                    return finishNode(node);
                }
                function parseFunctionDeclaration(fullStart, decorators, modifiers) {
                    var node = createNode(200 /* FunctionDeclaration */, fullStart);
                    node.decorators = decorators;
                    setModifiers(node, modifiers);
                    parseExpected(83 /* FunctionKeyword */);
                    node.asteriskToken = parseOptionalToken(35 /* AsteriskToken */);
                    node.name = node.flags & 256 /* Default */ ? parseOptionalIdentifier() : parseIdentifier();
                    fillSignature(51 /* ColonToken */, !!node.asteriskToken, false, node);
                    node.body = parseFunctionBlockOrSemicolon(!!node.asteriskToken, ts.Diagnostics.or_expected);
                    return finishNode(node);
                }
                function parseConstructorDeclaration(pos, decorators, modifiers) {
                    var node = createNode(135 /* Constructor */, pos);
                    node.decorators = decorators;
                    setModifiers(node, modifiers);
                    parseExpected(114 /* ConstructorKeyword */);
                    fillSignature(51 /* ColonToken */, false, false, node);
                    node.body = parseFunctionBlockOrSemicolon(false, ts.Diagnostics.or_expected);
                    return finishNode(node);
                }
                function parseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, name, questionToken, diagnosticMessage) {
                    var method = createNode(134 /* MethodDeclaration */, fullStart);
                    method.decorators = decorators;
                    setModifiers(method, modifiers);
                    method.asteriskToken = asteriskToken;
                    method.name = name;
                    method.questionToken = questionToken;
                    fillSignature(51 /* ColonToken */, !!asteriskToken, false, method);
                    method.body = parseFunctionBlockOrSemicolon(!!asteriskToken, diagnosticMessage);
                    return finishNode(method);
                }
                function parsePropertyDeclaration(fullStart, decorators, modifiers, name, questionToken) {
                    var property = createNode(132 /* PropertyDeclaration */, fullStart);
                    property.decorators = decorators;
                    setModifiers(property, modifiers);
                    property.name = name;
                    property.questionToken = questionToken;
                    property.type = parseTypeAnnotation();
                    property.initializer = allowInAnd(parseNonParameterInitializer);
                    parseSemicolon();
                    return finishNode(property);
                }
                function parsePropertyOrMethodDeclaration(fullStart, decorators, modifiers) {
                    var asteriskToken = parseOptionalToken(35 /* AsteriskToken */);
                    var name = parsePropertyName();
                    // Note: this is not legal as per the grammar.  But we allow it in the parser and
                    // report an error in the grammar checker.
                    var questionToken = parseOptionalToken(50 /* QuestionToken */);
                    if (asteriskToken || token === 16 /* OpenParenToken */ || token === 24 /* LessThanToken */) {
                        return parseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, name, questionToken, ts.Diagnostics.or_expected);
                    }
                    else {
                        return parsePropertyDeclaration(fullStart, decorators, modifiers, name, questionToken);
                    }
                }
                function parseNonParameterInitializer() {
                    return parseInitializer(false);
                }
                function parseAccessorDeclaration(kind, fullStart, decorators, modifiers) {
                    var node = createNode(kind, fullStart);
                    node.decorators = decorators;
                    setModifiers(node, modifiers);
                    node.name = parsePropertyName();
                    fillSignature(51 /* ColonToken */, false, false, node);
                    node.body = parseFunctionBlockOrSemicolon(false);
                    return finishNode(node);
                }
                function isClassMemberModifier(idToken) {
                    switch (idToken) {
                        case 108 /* PublicKeyword */:
                        case 106 /* PrivateKeyword */:
                        case 107 /* ProtectedKeyword */:
                        case 109 /* StaticKeyword */:
                            return true;
                        default:
                            return false;
                    }
                }
                function isClassMemberStart() {
                    var idToken;
                    if (token === 52 /* AtToken */) {
                        return true;
                    }
                    // Eat up all modifiers, but hold on to the last one in case it is actually an identifier.
                    while (ts.isModifier(token)) {
                        idToken = token;
                        // If the idToken is a class modifier (protected, private, public, and static), it is
                        // certain that we are starting to parse class member. This allows better error recovery
                        // Example:
                        //      public foo() ...     // true
                        //      public @dec blah ... // true; we will then report an error later
                        //      export public ...    // true; we will then report an error later
                        if (isClassMemberModifier(idToken)) {
                            return true;
                        }
                        nextToken();
                    }
                    if (token === 35 /* AsteriskToken */) {
                        return true;
                    }
                    // Try to get the first property-like token following all modifiers.
                    // This can either be an identifier or the 'get' or 'set' keywords.
                    if (isLiteralPropertyName()) {
                        idToken = token;
                        nextToken();
                    }
                    // Index signatures and computed properties are class members; we can parse.
                    if (token === 18 /* OpenBracketToken */) {
                        return true;
                    }
                    // If we were able to get any potential identifier...
                    if (idToken !== undefined) {
                        // If we have a non-keyword identifier, or if we have an accessor, then it's safe to parse.
                        if (!ts.isKeyword(idToken) || idToken === 120 /* SetKeyword */ || idToken === 116 /* GetKeyword */) {
                            return true;
                        }
                        // If it *is* a keyword, but not an accessor, check a little farther along
                        // to see if it should actually be parsed as a class member.
                        switch (token) {
                            case 16 /* OpenParenToken */: // Method declaration
                            case 24 /* LessThanToken */: // Generic Method declaration
                            case 51 /* ColonToken */: // Type Annotation for declaration
                            case 53 /* EqualsToken */: // Initializer for declaration
                            case 50 /* QuestionToken */:
                                return true;
                            default:
                                // Covers
                                //  - Semicolons     (declaration termination)
                                //  - Closing braces (end-of-class, must be declaration)
                                //  - End-of-files   (not valid, but permitted so that it gets caught later on)
                                //  - Line-breaks    (enabling *automatic semicolon insertion*)
                                return canParseSemicolon();
                        }
                    }
                    return false;
                }
                function parseDecorators() {
                    var decorators;
                    while (true) {
                        var decoratorStart = getNodePos();
                        if (!parseOptional(52 /* AtToken */)) {
                            break;
                        }
                        if (!decorators) {
                            decorators = [];
                            decorators.pos = scanner.getStartPos();
                        }
                        var decorator = createNode(130 /* Decorator */, decoratorStart);
                        decorator.expression = doInDecoratorContext(parseLeftHandSideExpressionOrHigher);
                        decorators.push(finishNode(decorator));
                    }
                    if (decorators) {
                        decorators.end = getNodeEnd();
                    }
                    return decorators;
                }
                function parseModifiers() {
                    var flags = 0;
                    var modifiers;
                    while (true) {
                        var modifierStart = scanner.getStartPos();
                        var modifierKind = token;
                        if (!parseAnyContextualModifier()) {
                            break;
                        }
                        if (!modifiers) {
                            modifiers = [];
                            modifiers.pos = modifierStart;
                        }
                        flags |= ts.modifierToFlag(modifierKind);
                        modifiers.push(finishNode(createNode(modifierKind, modifierStart)));
                    }
                    if (modifiers) {
                        modifiers.flags = flags;
                        modifiers.end = scanner.getStartPos();
                    }
                    return modifiers;
                }
                function parseClassElement() {
                    if (token === 22 /* SemicolonToken */) {
                        var result = createNode(178 /* SemicolonClassElement */);
                        nextToken();
                        return finishNode(result);
                    }
                    var fullStart = getNodePos();
                    var decorators = parseDecorators();
                    var modifiers = parseModifiers();
                    var accessor = tryParseAccessorDeclaration(fullStart, decorators, modifiers);
                    if (accessor) {
                        return accessor;
                    }
                    if (token === 114 /* ConstructorKeyword */) {
                        return parseConstructorDeclaration(fullStart, decorators, modifiers);
                    }
                    if (isIndexSignature()) {
                        return parseIndexSignatureDeclaration(fullStart, decorators, modifiers);
                    }
                    // It is very important that we check this *after* checking indexers because
                    // the [ token can start an index signature or a computed property name
                    if (isIdentifierOrKeyword() ||
                        token === 8 /* StringLiteral */ ||
                        token === 7 /* NumericLiteral */ ||
                        token === 35 /* AsteriskToken */ ||
                        token === 18 /* OpenBracketToken */) {
                        return parsePropertyOrMethodDeclaration(fullStart, decorators, modifiers);
                    }
                    if (decorators) {
                        // treat this as a property declaration with a missing name.
                        var name_3 = createMissingNode(65 /* Identifier */, true, ts.Diagnostics.Declaration_expected);
                        return parsePropertyDeclaration(fullStart, decorators, modifiers, name_3, undefined);
                    }
                    // 'isClassMemberStart' should have hinted not to attempt parsing.
                    ts.Debug.fail("Should not have attempted to parse class member declaration.");
                }
                function parseClassExpression() {
                    return parseClassDeclarationOrExpression(
                    /*fullStart:*/ scanner.getStartPos(), 
                    /*decorators:*/ undefined, 
                    /*modifiers:*/ undefined, 174 /* ClassExpression */);
                }
                function parseClassDeclaration(fullStart, decorators, modifiers) {
                    return parseClassDeclarationOrExpression(fullStart, decorators, modifiers, 201 /* ClassDeclaration */);
                }
                function parseClassDeclarationOrExpression(fullStart, decorators, modifiers, kind) {
                    // In ES6 specification, All parts of a ClassDeclaration or a ClassExpression are strict mode code
                    var savedStrictModeContext = inStrictModeContext();
                    setStrictModeContext(true);
                    var node = createNode(kind, fullStart);
                    node.decorators = decorators;
                    setModifiers(node, modifiers);
                    parseExpected(69 /* ClassKeyword */);
                    node.name = parseOptionalIdentifier();
                    node.typeParameters = parseTypeParameters();
                    node.heritageClauses = parseHeritageClauses(true);
                    if (parseExpected(14 /* OpenBraceToken */)) {
                        // ClassTail[Yield,GeneratorParameter] : See 14.5
                        //      [~GeneratorParameter]ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
                        //      [+GeneratorParameter] ClassHeritageopt { ClassBodyopt }
                        node.members = inGeneratorParameterContext()
                            ? doOutsideOfYieldContext(parseClassMembers)
                            : parseClassMembers();
                        parseExpected(15 /* CloseBraceToken */);
                    }
                    else {
                        node.members = createMissingList();
                    }
                    var finishedNode = finishNode(node);
                    setStrictModeContext(savedStrictModeContext);
                    return finishedNode;
                }
                function parseHeritageClauses(isClassHeritageClause) {
                    // ClassTail[Yield,GeneratorParameter] : See 14.5
                    //      [~GeneratorParameter]ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
                    //      [+GeneratorParameter] ClassHeritageopt { ClassBodyopt }
                    if (isHeritageClause()) {
                        return isClassHeritageClause && inGeneratorParameterContext()
                            ? doOutsideOfYieldContext(parseHeritageClausesWorker)
                            : parseHeritageClausesWorker();
                    }
                    return undefined;
                }
                function parseHeritageClausesWorker() {
                    return parseList(19 /* HeritageClauses */, false, parseHeritageClause);
                }
                function parseHeritageClause() {
                    if (token === 79 /* ExtendsKeyword */ || token === 102 /* ImplementsKeyword */) {
                        var node = createNode(222 /* HeritageClause */);
                        node.token = token;
                        nextToken();
                        node.types = parseDelimitedList(8 /* HeritageClauseElement */, parseHeritageClauseElement);
                        return finishNode(node);
                    }
                    return undefined;
                }
                function parseHeritageClauseElement() {
                    var node = createNode(177 /* HeritageClauseElement */);
                    node.expression = parseLeftHandSideExpressionOrHigher();
                    if (token === 24 /* LessThanToken */) {
                        node.typeArguments = parseBracketedList(17 /* TypeArguments */, parseType, 24 /* LessThanToken */, 25 /* GreaterThanToken */);
                    }
                    return finishNode(node);
                }
                function isHeritageClause() {
                    return token === 79 /* ExtendsKeyword */ || token === 102 /* ImplementsKeyword */;
                }
                function parseClassMembers() {
                    return parseList(6 /* ClassMembers */, false, parseClassElement);
                }
                function parseInterfaceDeclaration(fullStart, decorators, modifiers) {
                    var node = createNode(202 /* InterfaceDeclaration */, fullStart);
                    node.decorators = decorators;
                    setModifiers(node, modifiers);
                    parseExpected(103 /* InterfaceKeyword */);
                    node.name = parseIdentifier();
                    node.typeParameters = parseTypeParameters();
                    node.heritageClauses = parseHeritageClauses(false);
                    node.members = parseObjectTypeMembers();
                    return finishNode(node);
                }
                function parseTypeAliasDeclaration(fullStart, decorators, modifiers) {
                    var node = createNode(203 /* TypeAliasDeclaration */, fullStart);
                    node.decorators = decorators;
                    setModifiers(node, modifiers);
                    parseExpected(123 /* TypeKeyword */);
                    node.name = parseIdentifier();
                    parseExpected(53 /* EqualsToken */);
                    node.type = parseType();
                    parseSemicolon();
                    return finishNode(node);
                }
                // In an ambient declaration, the grammar only allows integer literals as initializers.
                // In a non-ambient declaration, the grammar allows uninitialized members only in a
                // ConstantEnumMemberSection, which starts at the beginning of an enum declaration
                // or any time an integer literal initializer is encountered.
                function parseEnumMember() {
                    var node = createNode(226 /* EnumMember */, scanner.getStartPos());
                    node.name = parsePropertyName();
                    node.initializer = allowInAnd(parseNonParameterInitializer);
                    return finishNode(node);
                }
                function parseEnumDeclaration(fullStart, decorators, modifiers) {
                    var node = createNode(204 /* EnumDeclaration */, fullStart);
                    node.decorators = decorators;
                    setModifiers(node, modifiers);
                    parseExpected(77 /* EnumKeyword */);
                    node.name = parseIdentifier();
                    if (parseExpected(14 /* OpenBraceToken */)) {
                        node.members = parseDelimitedList(7 /* EnumMembers */, parseEnumMember);
                        parseExpected(15 /* CloseBraceToken */);
                    }
                    else {
                        node.members = createMissingList();
                    }
                    return finishNode(node);
                }
                function parseModuleBlock() {
                    var node = createNode(206 /* ModuleBlock */, scanner.getStartPos());
                    if (parseExpected(14 /* OpenBraceToken */)) {
                        node.statements = parseList(1 /* ModuleElements */, false, parseModuleElement);
                        parseExpected(15 /* CloseBraceToken */);
                    }
                    else {
                        node.statements = createMissingList();
                    }
                    return finishNode(node);
                }
                function parseInternalModuleTail(fullStart, decorators, modifiers, flags) {
                    var node = createNode(205 /* ModuleDeclaration */, fullStart);
                    node.decorators = decorators;
                    setModifiers(node, modifiers);
                    node.flags |= flags;
                    node.name = parseIdentifier();
                    node.body = parseOptional(20 /* DotToken */)
                        ? parseInternalModuleTail(getNodePos(), undefined, undefined, 1 /* Export */)
                        : parseModuleBlock();
                    return finishNode(node);
                }
                function parseAmbientExternalModuleDeclaration(fullStart, decorators, modifiers) {
                    var node = createNode(205 /* ModuleDeclaration */, fullStart);
                    node.decorators = decorators;
                    setModifiers(node, modifiers);
                    node.name = parseLiteralNode(true);
                    node.body = parseModuleBlock();
                    return finishNode(node);
                }
                function parseModuleDeclaration(fullStart, decorators, modifiers) {
                    parseExpected(117 /* ModuleKeyword */);
                    return token === 8 /* StringLiteral */
                        ? parseAmbientExternalModuleDeclaration(fullStart, decorators, modifiers)
                        : parseInternalModuleTail(fullStart, decorators, modifiers, modifiers ? modifiers.flags : 0);
                }
                function isExternalModuleReference() {
                    return token === 118 /* RequireKeyword */ &&
                        lookAhead(nextTokenIsOpenParen);
                }
                function nextTokenIsOpenParen() {
                    return nextToken() === 16 /* OpenParenToken */;
                }
                function nextTokenIsCommaOrFromKeyword() {
                    nextToken();
                    return token === 23 /* CommaToken */ ||
                        token === 124 /* FromKeyword */;
                }
                function parseImportDeclarationOrImportEqualsDeclaration(fullStart, decorators, modifiers) {
                    parseExpected(85 /* ImportKeyword */);
                    var afterImportPos = scanner.getStartPos();
                    var identifier;
                    if (isIdentifier()) {
                        identifier = parseIdentifier();
                        if (token !== 23 /* CommaToken */ && token !== 124 /* FromKeyword */) {
                            // ImportEquals declaration of type:
                            // import x = require("mod"); or
                            // import x = M.x;
                            var importEqualsDeclaration = createNode(208 /* ImportEqualsDeclaration */, fullStart);
                            importEqualsDeclaration.decorators = decorators;
                            setModifiers(importEqualsDeclaration, modifiers);
                            importEqualsDeclaration.name = identifier;
                            parseExpected(53 /* EqualsToken */);
                            importEqualsDeclaration.moduleReference = parseModuleReference();
                            parseSemicolon();
                            return finishNode(importEqualsDeclaration);
                        }
                    }
                    // Import statement
                    var importDeclaration = createNode(209 /* ImportDeclaration */, fullStart);
                    importDeclaration.decorators = decorators;
                    setModifiers(importDeclaration, modifiers);
                    // ImportDeclaration:
                    //  import ImportClause from ModuleSpecifier ;
                    //  import ModuleSpecifier;
                    if (identifier ||
                        token === 35 /* AsteriskToken */ ||
                        token === 14 /* OpenBraceToken */) {
                        importDeclaration.importClause = parseImportClause(identifier, afterImportPos);
                        parseExpected(124 /* FromKeyword */);
                    }
                    importDeclaration.moduleSpecifier = parseModuleSpecifier();
                    parseSemicolon();
                    return finishNode(importDeclaration);
                }
                function parseImportClause(identifier, fullStart) {
                    //ImportClause:
                    //  ImportedDefaultBinding
                    //  NameSpaceImport
                    //  NamedImports
                    //  ImportedDefaultBinding, NameSpaceImport
                    //  ImportedDefaultBinding, NamedImports
                    var importClause = createNode(210 /* ImportClause */, fullStart);
                    if (identifier) {
                        // ImportedDefaultBinding:
                        //  ImportedBinding
                        importClause.name = identifier;
                    }
                    // If there was no default import or if there is comma token after default import
                    // parse namespace or named imports
                    if (!importClause.name ||
                        parseOptional(23 /* CommaToken */)) {
                        importClause.namedBindings = token === 35 /* AsteriskToken */ ? parseNamespaceImport() : parseNamedImportsOrExports(212 /* NamedImports */);
                    }
                    return finishNode(importClause);
                }
                function parseModuleReference() {
                    return isExternalModuleReference()
                        ? parseExternalModuleReference()
                        : parseEntityName(false);
                }
                function parseExternalModuleReference() {
                    var node = createNode(219 /* ExternalModuleReference */);
                    parseExpected(118 /* RequireKeyword */);
                    parseExpected(16 /* OpenParenToken */);
                    node.expression = parseModuleSpecifier();
                    parseExpected(17 /* CloseParenToken */);
                    return finishNode(node);
                }
                function parseModuleSpecifier() {
                    // We allow arbitrary expressions here, even though the grammar only allows string
                    // literals.  We check to ensure that it is only a string literal later in the grammar
                    // walker.
                    var result = parseExpression();
                    // Ensure the string being required is in our 'identifier' table.  This will ensure
                    // that features like 'find refs' will look inside this file when search for its name.
                    if (result.kind === 8 /* StringLiteral */) {
                        internIdentifier(result.text);
                    }
                    return result;
                }
                function parseNamespaceImport() {
                    // NameSpaceImport:
                    //  * as ImportedBinding
                    var namespaceImport = createNode(211 /* NamespaceImport */);
                    parseExpected(35 /* AsteriskToken */);
                    parseExpected(111 /* AsKeyword */);
                    namespaceImport.name = parseIdentifier();
                    return finishNode(namespaceImport);
                }
                function parseNamedImportsOrExports(kind) {
                    var node = createNode(kind);
                    // NamedImports:
                    //  { }
                    //  { ImportsList }
                    //  { ImportsList, }
                    // ImportsList:
                    //  ImportSpecifier
                    //  ImportsList, ImportSpecifier
                    node.elements = parseBracketedList(20 /* ImportOrExportSpecifiers */, kind === 212 /* NamedImports */ ? parseImportSpecifier : parseExportSpecifier, 14 /* OpenBraceToken */, 15 /* CloseBraceToken */);
                    return finishNode(node);
                }
                function parseExportSpecifier() {
                    return parseImportOrExportSpecifier(217 /* ExportSpecifier */);
                }
                function parseImportSpecifier() {
                    return parseImportOrExportSpecifier(213 /* ImportSpecifier */);
                }
                function parseImportOrExportSpecifier(kind) {
                    var node = createNode(kind);
                    // ImportSpecifier:
                    //   BindingIdentifier
                    //   IdentifierName as BindingIdentifier
                    // ExportSpecififer:
                    //   IdentifierName
                    //   IdentifierName as IdentifierName
                    var checkIdentifierIsKeyword = ts.isKeyword(token) && !isIdentifier();
                    var checkIdentifierStart = scanner.getTokenPos();
                    var checkIdentifierEnd = scanner.getTextPos();
                    var identifierName = parseIdentifierName();
                    if (token === 111 /* AsKeyword */) {
                        node.propertyName = identifierName;
                        parseExpected(111 /* AsKeyword */);
                        checkIdentifierIsKeyword = ts.isKeyword(token) && !isIdentifier();
                        checkIdentifierStart = scanner.getTokenPos();
                        checkIdentifierEnd = scanner.getTextPos();
                        node.name = parseIdentifierName();
                    }
                    else {
                        node.name = identifierName;
                    }
                    if (kind === 213 /* ImportSpecifier */ && checkIdentifierIsKeyword) {
                        // Report error identifier expected
                        parseErrorAtPosition(checkIdentifierStart, checkIdentifierEnd - checkIdentifierStart, ts.Diagnostics.Identifier_expected);
                    }
                    return finishNode(node);
                }
                function parseExportDeclaration(fullStart, decorators, modifiers) {
                    var node = createNode(215 /* ExportDeclaration */, fullStart);
                    node.decorators = decorators;
                    setModifiers(node, modifiers);
                    if (parseOptional(35 /* AsteriskToken */)) {
                        parseExpected(124 /* FromKeyword */);
                        node.moduleSpecifier = parseModuleSpecifier();
                    }
                    else {
                        node.exportClause = parseNamedImportsOrExports(216 /* NamedExports */);
                        if (parseOptional(124 /* FromKeyword */)) {
                            node.moduleSpecifier = parseModuleSpecifier();
                        }
                    }
                    parseSemicolon();
                    return finishNode(node);
                }
                function parseExportAssignment(fullStart, decorators, modifiers) {
                    var node = createNode(214 /* ExportAssignment */, fullStart);
                    node.decorators = decorators;
                    setModifiers(node, modifiers);
                    if (parseOptional(53 /* EqualsToken */)) {
                        node.isExportEquals = true;
                    }
                    else {
                        parseExpected(73 /* DefaultKeyword */);
                    }
                    node.expression = parseAssignmentExpressionOrHigher();
                    parseSemicolon();
                    return finishNode(node);
                }
                function isLetDeclaration() {
                    // It is let declaration if in strict mode or next token is identifier\open bracket\open curly on same line.
                    // otherwise it needs to be treated like identifier
                    return inStrictModeContext() || lookAhead(nextTokenIsIdentifierOrStartOfDestructuringOnTheSameLine);
                }
                function isDeclarationStart(followsModifier) {
                    switch (token) {
                        case 98 /* VarKeyword */:
                        case 70 /* ConstKeyword */:
                        case 83 /* FunctionKeyword */:
                            return true;
                        case 104 /* LetKeyword */:
                            return isLetDeclaration();
                        case 69 /* ClassKeyword */:
                        case 103 /* InterfaceKeyword */:
                        case 77 /* EnumKeyword */:
                        case 123 /* TypeKeyword */:
                            // Not true keywords so ensure an identifier follows
                            return lookAhead(nextTokenIsIdentifierOrKeyword);
                        case 85 /* ImportKeyword */:
                            // Not true keywords so ensure an identifier follows or is string literal or asterisk or open brace
                            return lookAhead(nextTokenCanFollowImportKeyword);
                        case 117 /* ModuleKeyword */:
                            // Not a true keyword so ensure an identifier or string literal follows
                            return lookAhead(nextTokenIsIdentifierOrKeywordOrStringLiteral);
                        case 78 /* ExportKeyword */:
                            // Check for export assignment or modifier on source element
                            return lookAhead(nextTokenCanFollowExportKeyword);
                        case 115 /* DeclareKeyword */:
                        case 108 /* PublicKeyword */:
                        case 106 /* PrivateKeyword */:
                        case 107 /* ProtectedKeyword */:
                        case 109 /* StaticKeyword */:
                            // Check for modifier on source element
                            return lookAhead(nextTokenIsDeclarationStart);
                        case 52 /* AtToken */:
                            // a lookahead here is too costly, and decorators are only valid on a declaration. 
                            // We will assume we are parsing a declaration here and report an error later
                            return !followsModifier;
                    }
                }
                function isIdentifierOrKeyword() {
                    return token >= 65 /* Identifier */;
                }
                function nextTokenIsIdentifierOrKeyword() {
                    nextToken();
                    return isIdentifierOrKeyword();
                }
                function nextTokenIsIdentifierOrKeywordOrStringLiteral() {
                    nextToken();
                    return isIdentifierOrKeyword() || token === 8 /* StringLiteral */;
                }
                function nextTokenCanFollowImportKeyword() {
                    nextToken();
                    return isIdentifierOrKeyword() || token === 8 /* StringLiteral */ ||
                        token === 35 /* AsteriskToken */ || token === 14 /* OpenBraceToken */;
                }
                function nextTokenCanFollowExportKeyword() {
                    nextToken();
                    return token === 53 /* EqualsToken */ || token === 35 /* AsteriskToken */ ||
                        token === 14 /* OpenBraceToken */ || token === 73 /* DefaultKeyword */ || isDeclarationStart(true);
                }
                function nextTokenIsDeclarationStart() {
                    nextToken();
                    return isDeclarationStart(true);
                }
                function nextTokenIsAsKeyword() {
                    return nextToken() === 111 /* AsKeyword */;
                }
                function parseDeclaration() {
                    var fullStart = getNodePos();
                    var decorators = parseDecorators();
                    var modifiers = parseModifiers();
                    if (token === 78 /* ExportKeyword */) {
                        nextToken();
                        if (token === 73 /* DefaultKeyword */ || token === 53 /* EqualsToken */) {
                            return parseExportAssignment(fullStart, decorators, modifiers);
                        }
                        if (token === 35 /* AsteriskToken */ || token === 14 /* OpenBraceToken */) {
                            return parseExportDeclaration(fullStart, decorators, modifiers);
                        }
                    }
                    switch (token) {
                        case 98 /* VarKeyword */:
                        case 104 /* LetKeyword */:
                        case 70 /* ConstKeyword */:
                            return parseVariableStatement(fullStart, decorators, modifiers);
                        case 83 /* FunctionKeyword */:
                            return parseFunctionDeclaration(fullStart, decorators, modifiers);
                        case 69 /* ClassKeyword */:
                            return parseClassDeclaration(fullStart, decorators, modifiers);
                        case 103 /* InterfaceKeyword */:
                            return parseInterfaceDeclaration(fullStart, decorators, modifiers);
                        case 123 /* TypeKeyword */:
                            return parseTypeAliasDeclaration(fullStart, decorators, modifiers);
                        case 77 /* EnumKeyword */:
                            return parseEnumDeclaration(fullStart, decorators, modifiers);
                        case 117 /* ModuleKeyword */:
                            return parseModuleDeclaration(fullStart, decorators, modifiers);
                        case 85 /* ImportKeyword */:
                            return parseImportDeclarationOrImportEqualsDeclaration(fullStart, decorators, modifiers);
                        default:
                            if (decorators) {
                                // We reached this point because we encountered an AtToken and assumed a declaration would
                                // follow. For recovery and error reporting purposes, return an incomplete declaration.                        
                                var node = createMissingNode(218 /* MissingDeclaration */, true, ts.Diagnostics.Declaration_expected);
                                node.pos = fullStart;
                                node.decorators = decorators;
                                setModifiers(node, modifiers);
                                return finishNode(node);
                            }
                            ts.Debug.fail("Mismatch between isDeclarationStart and parseDeclaration");
                    }
                }
                function isSourceElement(inErrorRecovery) {
                    return isDeclarationStart() || isStartOfStatement(inErrorRecovery);
                }
                function parseSourceElement() {
                    return parseSourceElementOrModuleElement();
                }
                function parseModuleElement() {
                    return parseSourceElementOrModuleElement();
                }
                function parseSourceElementOrModuleElement() {
                    return isDeclarationStart()
                        ? parseDeclaration()
                        : parseStatement();
                }
                function processReferenceComments(sourceFile) {
                    var triviaScanner = ts.createScanner(sourceFile.languageVersion, false, sourceText);
                    var referencedFiles = [];
                    var amdDependencies = [];
                    var amdModuleName;
                    // Keep scanning all the leading trivia in the file until we get to something that
                    // isn't trivia.  Any single line comment will be analyzed to see if it is a
                    // reference comment.
                    while (true) {
                        var kind = triviaScanner.scan();
                        if (kind === 5 /* WhitespaceTrivia */ || kind === 4 /* NewLineTrivia */ || kind === 3 /* MultiLineCommentTrivia */) {
                            continue;
                        }
                        if (kind !== 2 /* SingleLineCommentTrivia */) {
                            break;
                        }
                        var range = { pos: triviaScanner.getTokenPos(), end: triviaScanner.getTextPos(), kind: triviaScanner.getToken() };
                        var comment = sourceText.substring(range.pos, range.end);
                        var referencePathMatchResult = ts.getFileReferenceFromReferencePath(comment, range);
                        if (referencePathMatchResult) {
                            var fileReference = referencePathMatchResult.fileReference;
                            sourceFile.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
                            var diagnosticMessage = referencePathMatchResult.diagnosticMessage;
                            if (fileReference) {
                                referencedFiles.push(fileReference);
                            }
                            if (diagnosticMessage) {
                                sourceFile.parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage));
                            }
                        }
                        else {
                            var amdModuleNameRegEx = /^\/\/\/\s*<amd-module\s+name\s*=\s*('|")(.+?)\1/gim;
                            var amdModuleNameMatchResult = amdModuleNameRegEx.exec(comment);
                            if (amdModuleNameMatchResult) {
                                if (amdModuleName) {
                                    sourceFile.parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, ts.Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments));
                                }
                                amdModuleName = amdModuleNameMatchResult[2];
                            }
                            var amdDependencyRegEx = /^\/\/\/\s*<amd-dependency\s/gim;
                            var pathRegex = /\spath\s*=\s*('|")(.+?)\1/gim;
                            var nameRegex = /\sname\s*=\s*('|")(.+?)\1/gim;
                            var amdDependencyMatchResult = amdDependencyRegEx.exec(comment);
                            if (amdDependencyMatchResult) {
                                var pathMatchResult = pathRegex.exec(comment);
                                var nameMatchResult = nameRegex.exec(comment);
                                if (pathMatchResult) {
                                    var amdDependency = { path: pathMatchResult[2], name: nameMatchResult ? nameMatchResult[2] : undefined };
                                    amdDependencies.push(amdDependency);
                                }
                            }
                        }
                    }
                    sourceFile.referencedFiles = referencedFiles;
                    sourceFile.amdDependencies = amdDependencies;
                    sourceFile.amdModuleName = amdModuleName;
                }
                function setExternalModuleIndicator(sourceFile) {
                    sourceFile.externalModuleIndicator = ts.forEach(sourceFile.statements, function (node) {
                        return node.flags & 1 /* Export */
                            || node.kind === 208 /* ImportEqualsDeclaration */ && node.moduleReference.kind === 219 /* ExternalModuleReference */
                            || node.kind === 209 /* ImportDeclaration */
                            || node.kind === 214 /* ExportAssignment */
                            || node.kind === 215 /* ExportDeclaration */
                            ? node
                            : undefined;
                    });
                }
                var ParsingContext;
                (function (ParsingContext) {
                    ParsingContext[ParsingContext["SourceElements"] = 0] = "SourceElements";
                    ParsingContext[ParsingContext["ModuleElements"] = 1] = "ModuleElements";
                    ParsingContext[ParsingContext["BlockStatements"] = 2] = "BlockStatements";
                    ParsingContext[ParsingContext["SwitchClauses"] = 3] = "SwitchClauses";
                    ParsingContext[ParsingContext["SwitchClauseStatements"] = 4] = "SwitchClauseStatements";
                    ParsingContext[ParsingContext["TypeMembers"] = 5] = "TypeMembers";
                    ParsingContext[ParsingContext["ClassMembers"] = 6] = "ClassMembers";
                    ParsingContext[ParsingContext["EnumMembers"] = 7] = "EnumMembers";
                    ParsingContext[ParsingContext["HeritageClauseElement"] = 8] = "HeritageClauseElement";
                    ParsingContext[ParsingContext["VariableDeclarations"] = 9] = "VariableDeclarations";
                    ParsingContext[ParsingContext["ObjectBindingElements"] = 10] = "ObjectBindingElements";
                    ParsingContext[ParsingContext["ArrayBindingElements"] = 11] = "ArrayBindingElements";
                    ParsingContext[ParsingContext["ArgumentExpressions"] = 12] = "ArgumentExpressions";
                    ParsingContext[ParsingContext["ObjectLiteralMembers"] = 13] = "ObjectLiteralMembers";
                    ParsingContext[ParsingContext["ArrayLiteralMembers"] = 14] = "ArrayLiteralMembers";
                    ParsingContext[ParsingContext["Parameters"] = 15] = "Parameters";
                    ParsingContext[ParsingContext["TypeParameters"] = 16] = "TypeParameters";
                    ParsingContext[ParsingContext["TypeArguments"] = 17] = "TypeArguments";
                    ParsingContext[ParsingContext["TupleElementTypes"] = 18] = "TupleElementTypes";
                    ParsingContext[ParsingContext["HeritageClauses"] = 19] = "HeritageClauses";
                    ParsingContext[ParsingContext["ImportOrExportSpecifiers"] = 20] = "ImportOrExportSpecifiers";
                    ParsingContext[ParsingContext["Count"] = 21] = "Count"; // Number of parsing contexts
                })(ParsingContext || (ParsingContext = {}));
                var Tristate;
                (function (Tristate) {
                    Tristate[Tristate["False"] = 0] = "False";
                    Tristate[Tristate["True"] = 1] = "True";
                    Tristate[Tristate["Unknown"] = 2] = "Unknown";
                })(Tristate || (Tristate = {}));
            })(Parser || (Parser = {}));
            var IncrementalParser;
            (function (IncrementalParser) {
                function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) {
                    aggressiveChecks = aggressiveChecks || ts.Debug.shouldAssert(2 /* Aggressive */);
                    checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks);
                    if (ts.textChangeRangeIsUnchanged(textChangeRange)) {
                        // if the text didn't change, then we can just return our current source file as-is.
                        return sourceFile;
                    }
                    if (sourceFile.statements.length === 0) {
                        // If we don't have any statements in the current source file, then there's no real
                        // way to incrementally parse.  So just do a full parse instead.
                        return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, undefined, true);
                    }
                    // Make sure we're not trying to incrementally update a source file more than once.  Once
                    // we do an update the original source file is considered unusbale from that point onwards.
                    //
                    // This is because we do incremental parsing in-place.  i.e. we take nodes from the old
                    // tree and give them new positions and parents.  From that point on, trusting the old
                    // tree at all is not possible as far too much of it may violate invariants.
                    var incrementalSourceFile = sourceFile;
                    ts.Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed);
                    incrementalSourceFile.hasBeenIncrementallyParsed = true;
                    var oldText = sourceFile.text;
                    var syntaxCursor = createSyntaxCursor(sourceFile);
                    // Make the actual change larger so that we know to reparse anything whose lookahead
                    // might have intersected the change.
                    var changeRange = extendToAffectedRange(sourceFile, textChangeRange);
                    checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks);
                    // Ensure that extending the affected range only moved the start of the change range
                    // earlier in the file.
                    ts.Debug.assert(changeRange.span.start <= textChangeRange.span.start);
                    ts.Debug.assert(ts.textSpanEnd(changeRange.span) === ts.textSpanEnd(textChangeRange.span));
                    ts.Debug.assert(ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)) === ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange)));
                    // The is the amount the nodes after the edit range need to be adjusted.  It can be
                    // positive (if the edit added characters), negative (if the edit deleted characters)
                    // or zero (if this was a pure overwrite with nothing added/removed).
                    var delta = ts.textChangeRangeNewSpan(changeRange).length - changeRange.span.length;
                    // If we added or removed characters during the edit, then we need to go and adjust all
                    // the nodes after the edit.  Those nodes may move forward (if we inserted chars) or they
                    // may move backward (if we deleted chars).
                    //
                    // Doing this helps us out in two ways.  First, it means that any nodes/tokens we want
                    // to reuse are already at the appropriate position in the new text.  That way when we
                    // reuse them, we don't have to figure out if they need to be adjusted.  Second, it makes
                    // it very easy to determine if we can reuse a node.  If the node's position is at where
                    // we are in the text, then we can reuse it.  Otherwise we can't.  If the node's position
                    // is ahead of us, then we'll need to rescan tokens.  If the node's position is behind
                    // us, then we'll need to skip it or crumble it as appropriate
                    //
                    // We will also adjust the positions of nodes that intersect the change range as well.
                    // By doing this, we ensure that all the positions in the old tree are consistent, not
                    // just the positions of nodes entirely before/after the change range.  By being
                    // consistent, we can then easily map from positions to nodes in the old tree easily.
                    //
                    // Also, mark any syntax elements that intersect the changed span.  We know, up front,
                    // that we cannot reuse these elements.
                    updateTokenPositionsAndMarkElements(incrementalSourceFile, changeRange.span.start, ts.textSpanEnd(changeRange.span), ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks);
                    // Now that we've set up our internal incremental state just proceed and parse the
                    // source file in the normal fashion.  When possible the parser will retrieve and
                    // reuse nodes from the old tree.
                    //
                    // Note: passing in 'true' for setNodeParents is very important.  When incrementally
                    // parsing, we will be reusing nodes from the old tree, and placing it into new
                    // parents.  If we don't set the parents now, we'll end up with an observably
                    // inconsistent tree.  Setting the parents on the new tree should be very fast.  We
                    // will immediately bail out of walking any subtrees when we can see that their parents
                    // are already correct.
                    var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, true);
                    return result;
                }
                IncrementalParser.updateSourceFile = updateSourceFile;
                function moveElementEntirelyPastChangeRange(element, isArray, delta, oldText, newText, aggressiveChecks) {
                    if (isArray) {
                        visitArray(element);
                    }
                    else {
                        visitNode(element);
                    }
                    return;
                    function visitNode(node) {
                        if (aggressiveChecks && shouldCheckNode(node)) {
                            var text = oldText.substring(node.pos, node.end);
                        }
                        // Ditch any existing LS children we may have created.  This way we can avoid
                        // moving them forward.
                        node._children = undefined;
                        node.pos += delta;
                        node.end += delta;
                        if (aggressiveChecks && shouldCheckNode(node)) {
                            ts.Debug.assert(text === newText.substring(node.pos, node.end));
                        }
                        forEachChild(node, visitNode, visitArray);
                        checkNodePositions(node, aggressiveChecks);
                    }
                    function visitArray(array) {
                        array._children = undefined;
                        array.pos += delta;
                        array.end += delta;
                        for (var _i = 0; _i < array.length; _i++) {
                            var node = array[_i];
                            visitNode(node);
                        }
                    }
                }
                function shouldCheckNode(node) {
                    switch (node.kind) {
                        case 8 /* StringLiteral */:
                        case 7 /* NumericLiteral */:
                        case 65 /* Identifier */:
                            return true;
                    }
                    return false;
                }
                function adjustIntersectingElement(element, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta) {
                    ts.Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range");
                    ts.Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range");
                    ts.Debug.assert(element.pos <= element.end);
                    // We have an element that intersects the change range in some way.  It may have its
                    // start, or its end (or both) in the changed range.  We want to adjust any part
                    // that intersects such that the final tree is in a consistent state.  i.e. all
                    // chlidren have spans within the span of their parent, and all siblings are ordered
                    // properly.
                    // We may need to update both the 'pos' and the 'end' of the element.
                    // If the 'pos' is before the start of the change, then we don't need to touch it.
                    // If it isn't, then the 'pos' must be inside the change.  How we update it will
                    // depend if delta is  positive or negative.  If delta is positive then we have
                    // something like:
                    //
                    //  -------------------AAA-----------------
                    //  -------------------BBBCCCCCCC-----------------
                    //
                    // In this case, we consider any node that started in the change range to still be
                    // starting at the same position.
                    //
                    // however, if the delta is negative, then we instead have something like this:
                    //
                    //  -------------------XXXYYYYYYY-----------------
                    //  -------------------ZZZ-----------------
                    //
                    // In this case, any element that started in the 'X' range will keep its position.
                    // However any element htat started after that will have their pos adjusted to be
                    // at the end of the new range.  i.e. any node that started in the 'Y' range will
                    // be adjusted to have their start at the end of the 'Z' range.
                    //
                    // The element will keep its position if possible.  Or Move backward to the new-end
                    // if it's in the 'Y' range.
                    element.pos = Math.min(element.pos, changeRangeNewEnd);
                    // If the 'end' is after the change range, then we always adjust it by the delta
                    // amount.  However, if the end is in the change range, then how we adjust it
                    // will depend on if delta is  positive or negative.  If delta is positive then we
                    // have something like:
                    //
                    //  -------------------AAA-----------------
                    //  -------------------BBBCCCCCCC-----------------
                    //
                    // In this case, we consider any node that ended inside the change range to keep its
                    // end position.
                    //
                    // however, if the delta is negative, then we instead have something like this:
                    //
                    //  -------------------XXXYYYYYYY-----------------
                    //  -------------------ZZZ-----------------
                    //
                    // In this case, any element that ended in the 'X' range will keep its position.
                    // However any element htat ended after that will have their pos adjusted to be
                    // at the end of the new range.  i.e. any node that ended in the 'Y' range will
                    // be adjusted to have their end at the end of the 'Z' range.
                    if (element.end >= changeRangeOldEnd) {
                        // Element ends after the change range.  Always adjust the end pos.
                        element.end += delta;
                    }
                    else {
                        // Element ends in the change range.  The element will keep its position if
                        // possible. Or Move backward to the new-end if it's in the 'Y' range.
                        element.end = Math.min(element.end, changeRangeNewEnd);
                    }
                    ts.Debug.assert(element.pos <= element.end);
                    if (element.parent) {
                        ts.Debug.assert(element.pos >= element.parent.pos);
                        ts.Debug.assert(element.end <= element.parent.end);
                    }
                }
                function checkNodePositions(node, aggressiveChecks) {
                    if (aggressiveChecks) {
                        var pos = node.pos;
                        forEachChild(node, function (child) {
                            ts.Debug.assert(child.pos >= pos);
                            pos = child.end;
                        });
                        ts.Debug.assert(pos <= node.end);
                    }
                }
                function updateTokenPositionsAndMarkElements(sourceFile, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta, oldText, newText, aggressiveChecks) {
                    visitNode(sourceFile);
                    return;
                    function visitNode(child) {
                        ts.Debug.assert(child.pos <= child.end);
                        if (child.pos > changeRangeOldEnd) {
                            // Node is entirely past the change range.  We need to move both its pos and
                            // end, forward or backward appropriately.
                            moveElementEntirelyPastChangeRange(child, false, delta, oldText, newText, aggressiveChecks);
                            return;
                        }
                        // Check if the element intersects the change range.  If it does, then it is not
                        // reusable.  Also, we'll need to recurse to see what constituent portions we may
                        // be able to use.
                        var fullEnd = child.end;
                        if (fullEnd >= changeStart) {
                            child.intersectsChange = true;
                            child._children = undefined;
                            // Adjust the pos or end (or both) of the intersecting element accordingly.
                            adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
                            forEachChild(child, visitNode, visitArray);
                            checkNodePositions(child, aggressiveChecks);
                            return;
                        }
                        // Otherwise, the node is entirely before the change range.  No need to do anything with it.
                        ts.Debug.assert(fullEnd < changeStart);
                    }
                    function visitArray(array) {
                        ts.Debug.assert(array.pos <= array.end);
                        if (array.pos > changeRangeOldEnd) {
                            // Array is entirely after the change range.  We need to move it, and move any of
                            // its children.
                            moveElementEntirelyPastChangeRange(array, true, delta, oldText, newText, aggressiveChecks);
                            return;
                        }
                        // Check if the element intersects the change range.  If it does, then it is not
                        // reusable.  Also, we'll need to recurse to see what constituent portions we may
                        // be able to use.
                        var fullEnd = array.end;
                        if (fullEnd >= changeStart) {
                            array.intersectsChange = true;
                            array._children = undefined;
                            // Adjust the pos or end (or both) of the intersecting array accordingly.
                            adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
                            for (var _i = 0; _i < array.length; _i++) {
                                var node = array[_i];
                                visitNode(node);
                            }
                            return;
                        }
                        // Otherwise, the array is entirely before the change range.  No need to do anything with it.
                        ts.Debug.assert(fullEnd < changeStart);
                    }
                }
                function extendToAffectedRange(sourceFile, changeRange) {
                    // Consider the following code:
                    //      void foo() { /; }
                    //
                    // If the text changes with an insertion of / just before the semicolon then we end up with:
                    //      void foo() { //; }
                    //
                    // If we were to just use the changeRange a is, then we would not rescan the { token
                    // (as it does not intersect the actual original change range).  Because an edit may
                    // change the token touching it, we actually need to look back *at least* one token so
                    // that the prior token sees that change.
                    var maxLookahead = 1;
                    var start = changeRange.span.start;
                    // the first iteration aligns us with the change start. subsequent iteration move us to
                    // the left by maxLookahead tokens.  We only need to do this as long as we're not at the
                    // start of the tree.
                    for (var i = 0; start > 0 && i <= maxLookahead; i++) {
                        var nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start);
                        ts.Debug.assert(nearestNode.pos <= start);
                        var position = nearestNode.pos;
                        start = Math.max(0, position - 1);
                    }
                    var finalSpan = ts.createTextSpanFromBounds(start, ts.textSpanEnd(changeRange.span));
                    var finalLength = changeRange.newLength + (changeRange.span.start - start);
                    return ts.createTextChangeRange(finalSpan, finalLength);
                }
                function findNearestNodeStartingBeforeOrAtPosition(sourceFile, position) {
                    var bestResult = sourceFile;
                    var lastNodeEntirelyBeforePosition;
                    forEachChild(sourceFile, visit);
                    if (lastNodeEntirelyBeforePosition) {
                        var lastChildOfLastEntireNodeBeforePosition = getLastChild(lastNodeEntirelyBeforePosition);
                        if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) {
                            bestResult = lastChildOfLastEntireNodeBeforePosition;
                        }
                    }
                    return bestResult;
                    function getLastChild(node) {
                        while (true) {
                            var lastChild = getLastChildWorker(node);
                            if (lastChild) {
                                node = lastChild;
                            }
                            else {
                                return node;
                            }
                        }
                    }
                    function getLastChildWorker(node) {
                        var last = undefined;
                        forEachChild(node, function (child) {
                            if (ts.nodeIsPresent(child)) {
                                last = child;
                            }
                        });
                        return last;
                    }
                    function visit(child) {
                        if (ts.nodeIsMissing(child)) {
                            // Missing nodes are effectively invisible to us.  We never even consider them
                            // When trying to find the nearest node before us.
                            return;
                        }
                        // If the child intersects this position, then this node is currently the nearest
                        // node that starts before the position.
                        if (child.pos <= position) {
                            if (child.pos >= bestResult.pos) {
                                // This node starts before the position, and is closer to the position than
                                // the previous best node we found.  It is now the new best node.
                                bestResult = child;
                            }
                            // Now, the node may overlap the position, or it may end entirely before the
                            // position.  If it overlaps with the position, then either it, or one of its
                            // children must be the nearest node before the position.  So we can just
                            // recurse into this child to see if we can find something better.
                            if (position < child.end) {
                                // The nearest node is either this child, or one of the children inside
                                // of it.  We've already marked this child as the best so far.  Recurse
                                // in case one of the children is better.
                                forEachChild(child, visit);
                                // Once we look at the children of this node, then there's no need to
                                // continue any further.
                                return true;
                            }
                            else {
                                ts.Debug.assert(child.end <= position);
                                // The child ends entirely before this position.  Say you have the following
                                // (where $ is the position)
                                //
                                //      <complex expr 1> ? <complex expr 2> $ : <...> <...>
                                //
                                // We would want to find the nearest preceding node in "complex expr 2".
                                // To support that, we keep track of this node, and once we're done searching
                                // for a best node, we recurse down this node to see if we can find a good
                                // result in it.
                                //
                                // This approach allows us to quickly skip over nodes that are entirely
                                // before the position, while still allowing us to find any nodes in the
                                // last one that might be what we want.
                                lastNodeEntirelyBeforePosition = child;
                            }
                        }
                        else {
                            ts.Debug.assert(child.pos > position);
                            // We're now at a node that is entirely past the position we're searching for.
                            // This node (and all following nodes) could never contribute to the result,
                            // so just skip them by returning 'true' here.
                            return true;
                        }
                    }
                }
                function checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks) {
                    var oldText = sourceFile.text;
                    if (textChangeRange) {
                        ts.Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length);
                        if (aggressiveChecks || ts.Debug.shouldAssert(3 /* VeryAggressive */)) {
                            var oldTextPrefix = oldText.substr(0, textChangeRange.span.start);
                            var newTextPrefix = newText.substr(0, textChangeRange.span.start);
                            ts.Debug.assert(oldTextPrefix === newTextPrefix);
                            var oldTextSuffix = oldText.substring(ts.textSpanEnd(textChangeRange.span), oldText.length);
                            var newTextSuffix = newText.substring(ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange)), newText.length);
                            ts.Debug.assert(oldTextSuffix === newTextSuffix);
                        }
                    }
                }
                function createSyntaxCursor(sourceFile) {
                    var currentArray = sourceFile.statements;
                    var currentArrayIndex = 0;
                    ts.Debug.assert(currentArrayIndex < currentArray.length);
                    var current = currentArray[currentArrayIndex];
                    var lastQueriedPosition = -1 /* Value */;
                    return {
                        currentNode: function (position) {
                            // Only compute the current node if the position is different than the last time
                            // we were asked.  The parser commonly asks for the node at the same position
                            // twice.  Once to know if can read an appropriate list element at a certain point,
                            // and then to actually read and consume the node.
                            if (position !== lastQueriedPosition) {
                                // Much of the time the parser will need the very next node in the array that
                                // we just returned a node from.So just simply check for that case and move
                                // forward in the array instead of searching for the node again.
                                if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) {
                                    currentArrayIndex++;
                                    current = currentArray[currentArrayIndex];
                                }
                                // If we don't have a node, or the node we have isn't in the right position,
                                // then try to find a viable node at the position requested.
                                if (!current || current.pos !== position) {
                                    findHighestListElementThatStartsAtPosition(position);
                                }
                            }
                            // Cache this query so that we don't do any extra work if the parser calls back
                            // into us.  Note: this is very common as the parser will make pairs of calls like
                            // 'isListElement -> parseListElement'.  If we were unable to find a node when
                            // called with 'isListElement', we don't want to redo the work when parseListElement
                            // is called immediately after.
                            lastQueriedPosition = position;
                            // Either we don'd have a node, or we have a node at the position being asked for.
                            ts.Debug.assert(!current || current.pos === position);
                            return current;
                        }
                    };
                    // Finds the highest element in the tree we can find that starts at the provided position.
                    // The element must be a direct child of some node list in the tree.  This way after we
                    // return it, we can easily return its next sibling in the list.
                    function findHighestListElementThatStartsAtPosition(position) {
                        // Clear out any cached state about the last node we found.
                        currentArray = undefined;
                        currentArrayIndex = -1 /* Value */;
                        current = undefined;
                        // Recurse into the source file to find the highest node at this position.
                        forEachChild(sourceFile, visitNode, visitArray);
                        return;
                        function visitNode(node) {
                            if (position >= node.pos && position < node.end) {
                                // Position was within this node.  Keep searching deeper to find the node.
                                forEachChild(node, visitNode, visitArray);
                                // don't procede any futher in the search.
                                return true;
                            }
                            // position wasn't in this node, have to keep searching.
                            return false;
                        }
                        function visitArray(array) {
                            if (position >= array.pos && position < array.end) {
                                // position was in this array.  Search through this array to see if we find a
                                // viable element.
                                for (var i = 0, n = array.length; i < n; i++) {
                                    var child = array[i];
                                    if (child) {
                                        if (child.pos === position) {
                                            // Found the right node.  We're done.
                                            currentArray = array;
                                            currentArrayIndex = i;
                                            current = child;
                                            return true;
                                        }
                                        else {
                                            if (child.pos < position && position < child.end) {
                                                // Position in somewhere within this child.  Search in it and
                                                // stop searching in this array.
                                                forEachChild(child, visitNode, visitArray);
                                                return true;
                                            }
                                        }
                                    }
                                }
                            }
                            // position wasn't in this array, have to keep searching.
                            return false;
                        }
                    }
                }
                var InvalidPosition;
                (function (InvalidPosition) {
                    InvalidPosition[InvalidPosition["Value"] = -1] = "Value";
                })(InvalidPosition || (InvalidPosition = {}));
            })(IncrementalParser || (IncrementalParser = {}));
        })(ts || (ts = {}));
        /// <reference path="binder.ts"/>
        /* @internal */
        var ts;
        (function (ts) {
            var nextSymbolId = 1;
            var nextNodeId = 1;
            var nextMergeId = 1;
            function getNodeId(node) {
                if (!node.id)
                    node.id = nextNodeId++;
                return node.id;
            }
            ts.getNodeId = getNodeId;
            ts.checkTime = 0;
            function getSymbolId(symbol) {
                if (!symbol.id) {
                    symbol.id = nextSymbolId++;
                }
                return symbol.id;
            }
            ts.getSymbolId = getSymbolId;
            function createTypeChecker(host, produceDiagnostics) {
                var Symbol = ts.objectAllocator.getSymbolConstructor();
                var Type = ts.objectAllocator.getTypeConstructor();
                var Signature = ts.objectAllocator.getSignatureConstructor();
                var typeCount = 0;
                var emptyArray = [];
                var emptySymbols = {};
                var compilerOptions = host.getCompilerOptions();
                var languageVersion = compilerOptions.target || 0 /* ES3 */;
                var emitResolver = createResolver();
                var undefinedSymbol = createSymbol(4 /* Property */ | 67108864 /* Transient */, "undefined");
                var argumentsSymbol = createSymbol(4 /* Property */ | 67108864 /* Transient */, "arguments");
                var checker = {
                    getNodeCount: function () { return ts.sum(host.getSourceFiles(), "nodeCount"); },
                    getIdentifierCount: function () { return ts.sum(host.getSourceFiles(), "identifierCount"); },
                    getSymbolCount: function () { return ts.sum(host.getSourceFiles(), "symbolCount"); },
                    getTypeCount: function () { return typeCount; },
                    isUndefinedSymbol: function (symbol) { return symbol === undefinedSymbol; },
                    isArgumentsSymbol: function (symbol) { return symbol === argumentsSymbol; },
                    getDiagnostics: getDiagnostics,
                    getGlobalDiagnostics: getGlobalDiagnostics,
                    getTypeOfSymbolAtLocation: getTypeOfSymbolAtLocation,
                    getDeclaredTypeOfSymbol: getDeclaredTypeOfSymbol,
                    getPropertiesOfType: getPropertiesOfType,
                    getPropertyOfType: getPropertyOfType,
                    getSignaturesOfType: getSignaturesOfType,
                    getIndexTypeOfType: getIndexTypeOfType,
                    getReturnTypeOfSignature: getReturnTypeOfSignature,
                    getSymbolsInScope: getSymbolsInScope,
                    getSymbolAtLocation: getSymbolAtLocation,
                    getShorthandAssignmentValueSymbol: getShorthandAssignmentValueSymbol,
                    getTypeAtLocation: getTypeAtLocation,
                    typeToString: typeToString,
                    getSymbolDisplayBuilder: getSymbolDisplayBuilder,
                    symbolToString: symbolToString,
                    getAugmentedPropertiesOfType: getAugmentedPropertiesOfType,
                    getRootSymbols: getRootSymbols,
                    getContextualType: getContextualType,
                    getFullyQualifiedName: getFullyQualifiedName,
                    getResolvedSignature: getResolvedSignature,
                    getConstantValue: getConstantValue,
                    isValidPropertyAccess: isValidPropertyAccess,
                    getSignatureFromDeclaration: getSignatureFromDeclaration,
                    isImplementationOfOverload: isImplementationOfOverload,
                    getAliasedSymbol: resolveAlias,
                    getEmitResolver: getEmitResolver,
                    getExportsOfModule: getExportsOfModuleAsArray
                };
                var unknownSymbol = createSymbol(4 /* Property */ | 67108864 /* Transient */, "unknown");
                var resolvingSymbol = createSymbol(67108864 /* Transient */, "__resolving__");
                var anyType = createIntrinsicType(1 /* Any */, "any");
                var stringType = createIntrinsicType(2 /* String */, "string");
                var numberType = createIntrinsicType(4 /* Number */, "number");
                var booleanType = createIntrinsicType(8 /* Boolean */, "boolean");
                var esSymbolType = createIntrinsicType(1048576 /* ESSymbol */, "symbol");
                var voidType = createIntrinsicType(16 /* Void */, "void");
                var undefinedType = createIntrinsicType(32 /* Undefined */ | 262144 /* ContainsUndefinedOrNull */, "undefined");
                var nullType = createIntrinsicType(64 /* Null */ | 262144 /* ContainsUndefinedOrNull */, "null");
                var unknownType = createIntrinsicType(1 /* Any */, "unknown");
                var resolvingType = createIntrinsicType(1 /* Any */, "__resolving__");
                var emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
                var anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
                var noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
                var anySignature = createSignature(undefined, undefined, emptyArray, anyType, 0, false, false);
                var unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, 0, false, false);
                var globals = {};
                var globalArraySymbol;
                var globalESSymbolConstructorSymbol;
                var globalObjectType;
                var globalFunctionType;
                var globalArrayType;
                var globalStringType;
                var globalNumberType;
                var globalBooleanType;
                var globalRegExpType;
                var globalTemplateStringsArrayType;
                var globalESSymbolType;
                var globalIterableType;
                var anyArrayType;
                var getGlobalClassDecoratorType;
                var getGlobalParameterDecoratorType;
                var getGlobalPropertyDecoratorType;
                var getGlobalMethodDecoratorType;
                var tupleTypes = {};
                var unionTypes = {};
                var stringLiteralTypes = {};
                var emitExtends = false;
                var emitDecorate = false;
                var emitParam = false;
                var mergedSymbols = [];
                var symbolLinks = [];
                var nodeLinks = [];
                var potentialThisCollisions = [];
                var diagnostics = ts.createDiagnosticCollection();
                var primitiveTypeInfo = {
                    "string": {
                        type: stringType,
                        flags: 258 /* StringLike */
                    },
                    "number": {
                        type: numberType,
                        flags: 132 /* NumberLike */
                    },
                    "boolean": {
                        type: booleanType,
                        flags: 8 /* Boolean */
                    },
                    "symbol": {
                        type: esSymbolType,
                        flags: 1048576 /* ESSymbol */
                    }
                };
                function getEmitResolver(sourceFile) {
                    // Ensure we have all the type information in place for this file so that all the
                    // emitter questions of this resolver will return the right information.
                    getDiagnostics(sourceFile);
                    return emitResolver;
                }
                function error(location, message, arg0, arg1, arg2) {
                    var diagnostic = location
                        ? ts.createDiagnosticForNode(location, message, arg0, arg1, arg2)
                        : ts.createCompilerDiagnostic(message, arg0, arg1, arg2);
                    diagnostics.add(diagnostic);
                }
                function createSymbol(flags, name) {
                    return new Symbol(flags, name);
                }
                function getExcludedSymbolFlags(flags) {
                    var result = 0;
                    if (flags & 2 /* BlockScopedVariable */)
                        result |= 107455 /* BlockScopedVariableExcludes */;
                    if (flags & 1 /* FunctionScopedVariable */)
                        result |= 107454 /* FunctionScopedVariableExcludes */;
                    if (flags & 4 /* Property */)
                        result |= 107455 /* PropertyExcludes */;
                    if (flags & 8 /* EnumMember */)
                        result |= 107455 /* EnumMemberExcludes */;
                    if (flags & 16 /* Function */)
                        result |= 106927 /* FunctionExcludes */;
                    if (flags & 32 /* Class */)
                        result |= 899583 /* ClassExcludes */;
                    if (flags & 64 /* Interface */)
                        result |= 792992 /* InterfaceExcludes */;
                    if (flags & 256 /* RegularEnum */)
                        result |= 899327 /* RegularEnumExcludes */;
                    if (flags & 128 /* ConstEnum */)
                        result |= 899967 /* ConstEnumExcludes */;
                    if (flags & 512 /* ValueModule */)
                        result |= 106639 /* ValueModuleExcludes */;
                    if (flags & 8192 /* Method */)
                        result |= 99263 /* MethodExcludes */;
                    if (flags & 32768 /* GetAccessor */)
                        result |= 41919 /* GetAccessorExcludes */;
                    if (flags & 65536 /* SetAccessor */)
                        result |= 74687 /* SetAccessorExcludes */;
                    if (flags & 262144 /* TypeParameter */)
                        result |= 530912 /* TypeParameterExcludes */;
                    if (flags & 524288 /* TypeAlias */)
                        result |= 793056 /* TypeAliasExcludes */;
                    if (flags & 8388608 /* Alias */)
                        result |= 8388608 /* AliasExcludes */;
                    return result;
                }
                function recordMergedSymbol(target, source) {
                    if (!source.mergeId)
                        source.mergeId = nextMergeId++;
                    mergedSymbols[source.mergeId] = target;
                }
                function cloneSymbol(symbol) {
                    var result = createSymbol(symbol.flags | 33554432 /* Merged */, symbol.name);
                    result.declarations = symbol.declarations.slice(0);
                    result.parent = symbol.parent;
                    if (symbol.valueDeclaration)
                        result.valueDeclaration = symbol.valueDeclaration;
                    if (symbol.constEnumOnlyModule)
                        result.constEnumOnlyModule = true;
                    if (symbol.members)
                        result.members = cloneSymbolTable(symbol.members);
                    if (symbol.exports)
                        result.exports = cloneSymbolTable(symbol.exports);
                    recordMergedSymbol(result, symbol);
                    return result;
                }
                function mergeSymbol(target, source) {
                    if (!(target.flags & getExcludedSymbolFlags(source.flags))) {
                        if (source.flags & 512 /* ValueModule */ && target.flags & 512 /* ValueModule */ && target.constEnumOnlyModule && !source.constEnumOnlyModule) {
                            // reset flag when merging instantiated module into value module that has only const enums
                            target.constEnumOnlyModule = false;
                        }
                        target.flags |= source.flags;
                        if (!target.valueDeclaration && source.valueDeclaration)
                            target.valueDeclaration = source.valueDeclaration;
                        ts.forEach(source.declarations, function (node) {
                            target.declarations.push(node);
                        });
                        if (source.members) {
                            if (!target.members)
                                target.members = {};
                            mergeSymbolTable(target.members, source.members);
                        }
                        if (source.exports) {
                            if (!target.exports)
                                target.exports = {};
                            mergeSymbolTable(target.exports, source.exports);
                        }
                        recordMergedSymbol(target, source);
                    }
                    else {
                        var message = target.flags & 2 /* BlockScopedVariable */ || source.flags & 2 /* BlockScopedVariable */
                            ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 : ts.Diagnostics.Duplicate_identifier_0;
                        ts.forEach(source.declarations, function (node) {
                            error(node.name ? node.name : node, message, symbolToString(source));
                        });
                        ts.forEach(target.declarations, function (node) {
                            error(node.name ? node.name : node, message, symbolToString(source));
                        });
                    }
                }
                function cloneSymbolTable(symbolTable) {
                    var result = {};
                    for (var id in symbolTable) {
                        if (ts.hasProperty(symbolTable, id)) {
                            result[id] = symbolTable[id];
                        }
                    }
                    return result;
                }
                function mergeSymbolTable(target, source) {
                    for (var id in source) {
                        if (ts.hasProperty(source, id)) {
                            if (!ts.hasProperty(target, id)) {
                                target[id] = source[id];
                            }
                            else {
                                var symbol = target[id];
                                if (!(symbol.flags & 33554432 /* Merged */)) {
                                    target[id] = symbol = cloneSymbol(symbol);
                                }
                                mergeSymbol(symbol, source[id]);
                            }
                        }
                    }
                }
                function getSymbolLinks(symbol) {
                    if (symbol.flags & 67108864 /* Transient */)
                        return symbol;
                    var id = getSymbolId(symbol);
                    return symbolLinks[id] || (symbolLinks[id] = {});
                }
                function getNodeLinks(node) {
                    var nodeId = getNodeId(node);
                    return nodeLinks[nodeId] || (nodeLinks[nodeId] = {});
                }
                function getSourceFile(node) {
                    return ts.getAncestor(node, 227 /* SourceFile */);
                }
                function isGlobalSourceFile(node) {
                    return node.kind === 227 /* SourceFile */ && !ts.isExternalModule(node);
                }
                function getSymbol(symbols, name, meaning) {
                    if (meaning && ts.hasProperty(symbols, name)) {
                        var symbol = symbols[name];
                        ts.Debug.assert((symbol.flags & 16777216 /* Instantiated */) === 0, "Should never get an instantiated symbol here.");
                        if (symbol.flags & meaning) {
                            return symbol;
                        }
                        if (symbol.flags & 8388608 /* Alias */) {
                            var target = resolveAlias(symbol);
                            // Unknown symbol means an error occurred in alias resolution, treat it as positive answer to avoid cascading errors
                            if (target === unknownSymbol || target.flags & meaning) {
                                return symbol;
                            }
                        }
                    }
                    // return undefined if we can't find a symbol.
                }
                /** Returns true if node1 is defined before node 2**/
                function isDefinedBefore(node1, node2) {
                    var file1 = ts.getSourceFileOfNode(node1);
                    var file2 = ts.getSourceFileOfNode(node2);
                    if (file1 === file2) {
                        return node1.pos <= node2.pos;
                    }
                    if (!compilerOptions.out) {
                        return true;
                    }
                    var sourceFiles = host.getSourceFiles();
                    return sourceFiles.indexOf(file1) <= sourceFiles.indexOf(file2);
                }
                // Resolve a given name for a given meaning at a given location. An error is reported if the name was not found and
                // the nameNotFoundMessage argument is not undefined. Returns the resolved symbol, or undefined if no symbol with
                // the given name can be found.
                function resolveName(location, name, meaning, nameNotFoundMessage, nameArg) {
                    var result;
                    var lastLocation;
                    var propertyWithInvalidInitializer;
                    var errorLocation = location;
                    var grandparent;
                    loop: while (location) {
                        // Locals of a source file are not in scope (because they get merged into the global symbol table)
                        if (location.locals && !isGlobalSourceFile(location)) {
                            if (result = getSymbol(location.locals, name, meaning)) {
                                break loop;
                            }
                        }
                        switch (location.kind) {
                            case 227 /* SourceFile */:
                                if (!ts.isExternalModule(location))
                                    break;
                            case 205 /* ModuleDeclaration */:
                                if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & 8914931 /* ModuleMember */)) {
                                    if (result.flags & meaning || !(result.flags & 8388608 /* Alias */ && getDeclarationOfAliasSymbol(result).kind === 217 /* ExportSpecifier */)) {
                                        break loop;
                                    }
                                    result = undefined;
                                }
                                else if (location.kind === 227 /* SourceFile */ ||
                                    (location.kind === 205 /* ModuleDeclaration */ && location.name.kind === 8 /* StringLiteral */)) {
                                    result = getSymbol(getSymbolOfNode(location).exports, "default", meaning & 8914931 /* ModuleMember */);
                                    var localSymbol = ts.getLocalSymbolForExportDefault(result);
                                    if (result && (result.flags & meaning) && localSymbol && localSymbol.name === name) {
                                        break loop;
                                    }
                                    result = undefined;
                                }
                                break;
                            case 204 /* EnumDeclaration */:
                                if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & 8 /* EnumMember */)) {
                                    break loop;
                                }
                                break;
                            case 132 /* PropertyDeclaration */:
                            case 131 /* PropertySignature */:
                                // TypeScript 1.0 spec (April 2014): 8.4.1
                                // Initializer expressions for instance member variables are evaluated in the scope
                                // of the class constructor body but are not permitted to reference parameters or
                                // local variables of the constructor. This effectively means that entities from outer scopes
                                // by the same name as a constructor parameter or local variable are inaccessible
                                // in initializer expressions for instance member variables.
                                if (location.parent.kind === 201 /* ClassDeclaration */ && !(location.flags & 128 /* Static */)) {
                                    var ctor = findConstructorDeclaration(location.parent);
                                    if (ctor && ctor.locals) {
                                        if (getSymbol(ctor.locals, name, meaning & 107455 /* Value */)) {
                                            // Remember the property node, it will be used later to report appropriate error
                                            propertyWithInvalidInitializer = location;
                                        }
                                    }
                                }
                                break;
                            case 201 /* ClassDeclaration */:
                            case 202 /* InterfaceDeclaration */:
                                if (result = getSymbol(getSymbolOfNode(location).members, name, meaning & 793056 /* Type */)) {
                                    if (lastLocation && lastLocation.flags & 128 /* Static */) {
                                        // TypeScript 1.0 spec (April 2014): 3.4.1
                                        // The scope of a type parameter extends over the entire declaration with which the type
                                        // parameter list is associated, with the exception of static member declarations in classes.
                                        error(errorLocation, ts.Diagnostics.Static_members_cannot_reference_class_type_parameters);
                                        return undefined;
                                    }
                                    break loop;
                                }
                                break;
                            // It is not legal to reference a class's own type parameters from a computed property name that
                            // belongs to the class. For example:
                            //
                            //   function foo<T>() { return '' }
                            //   class C<T> { // <-- Class's own type parameter T
                            //       [foo<T>()]() { } // <-- Reference to T from class's own computed property
                            //   }
                            //
                            case 127 /* ComputedPropertyName */:
                                grandparent = location.parent.parent;
                                if (grandparent.kind === 201 /* ClassDeclaration */ || grandparent.kind === 202 /* InterfaceDeclaration */) {
                                    // A reference to this grandparent's type parameters would be an error
                                    if (result = getSymbol(getSymbolOfNode(grandparent).members, name, meaning & 793056 /* Type */)) {
                                        error(errorLocation, ts.Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type);
                                        return undefined;
                                    }
                                }
                                break;
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                            case 135 /* Constructor */:
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                            case 200 /* FunctionDeclaration */:
                            case 163 /* ArrowFunction */:
                                if (name === "arguments") {
                                    result = argumentsSymbol;
                                    break loop;
                                }
                                break;
                            case 162 /* FunctionExpression */:
                                if (name === "arguments") {
                                    result = argumentsSymbol;
                                    break loop;
                                }
                                var functionName = location.name;
                                if (functionName && name === functionName.text) {
                                    result = location.symbol;
                                    break loop;
                                }
                                break;
                            case 174 /* ClassExpression */:
                                var className = location.name;
                                if (className && name === className.text) {
                                    result = location.symbol;
                                    break loop;
                                }
                                break;
                            case 130 /* Decorator */:
                                // Decorators are resolved at the class declaration. Resolving at the parameter 
                                // or member would result in looking up locals in the method.
                                //
                                //   function y() {}
                                //   class C {
                                //       method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter.
                                //   }
                                //
                                if (location.parent && location.parent.kind === 129 /* Parameter */) {
                                    location = location.parent;
                                }
                                //
                                //   function y() {}
                                //   class C {
                                //       @y method(x, y) {} // <-- decorator y should be resolved at the class declaration, not the method.
                                //   }
                                //
                                if (location.parent && ts.isClassElement(location.parent)) {
                                    location = location.parent;
                                }
                                break;
                        }
                        lastLocation = location;
                        location = location.parent;
                    }
                    if (!result) {
                        result = getSymbol(globals, name, meaning);
                    }
                    if (!result) {
                        if (nameNotFoundMessage) {
                            error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : ts.declarationNameToString(nameArg));
                        }
                        return undefined;
                    }
                    // Perform extra checks only if error reporting was requested
                    if (nameNotFoundMessage) {
                        if (propertyWithInvalidInitializer) {
                            // We have a match, but the reference occurred within a property initializer and the identifier also binds
                            // to a local variable in the constructor where the code will be emitted.
                            var propertyName = propertyWithInvalidInitializer.name;
                            error(errorLocation, ts.Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, ts.declarationNameToString(propertyName), typeof nameArg === "string" ? nameArg : ts.declarationNameToString(nameArg));
                            return undefined;
                        }
                        if (result.flags & 2 /* BlockScopedVariable */) {
                            checkResolvedBlockScopedVariable(result, errorLocation);
                        }
                    }
                    return result;
                }
                function checkResolvedBlockScopedVariable(result, errorLocation) {
                    ts.Debug.assert((result.flags & 2 /* BlockScopedVariable */) !== 0);
                    // Block-scoped variables cannot be used before their definition
                    var declaration = ts.forEach(result.declarations, function (d) { return ts.isBlockOrCatchScoped(d) ? d : undefined; });
                    ts.Debug.assert(declaration !== undefined, "Block-scoped variable declaration is undefined");
                    // first check if usage is lexically located after the declaration
                    var isUsedBeforeDeclaration = !isDefinedBefore(declaration, errorLocation);
                    if (!isUsedBeforeDeclaration) {
                        // lexical check succeeded however code still can be illegal.
                        // - block scoped variables cannot be used in its initializers
                        //   let x = x; // illegal but usage is lexically after definition
                        // - in ForIn/ForOf statements variable cannot be contained in expression part
                        //   for (let x in x)
                        //   for (let x of x)
                        // climb up to the variable declaration skipping binding patterns
                        var variableDeclaration = ts.getAncestor(declaration, 198 /* VariableDeclaration */);
                        var container = ts.getEnclosingBlockScopeContainer(variableDeclaration);
                        if (variableDeclaration.parent.parent.kind === 180 /* VariableStatement */ ||
                            variableDeclaration.parent.parent.kind === 186 /* ForStatement */) {
                            // variable statement/for statement case,
                            // use site should not be inside variable declaration (initializer of declaration or binding element)
                            isUsedBeforeDeclaration = isSameScopeDescendentOf(errorLocation, variableDeclaration, container);
                        }
                        else if (variableDeclaration.parent.parent.kind === 188 /* ForOfStatement */ ||
                            variableDeclaration.parent.parent.kind === 187 /* ForInStatement */) {
                            // ForIn/ForOf case - use site should not be used in expression part
                            var expression = variableDeclaration.parent.parent.expression;
                            isUsedBeforeDeclaration = isSameScopeDescendentOf(errorLocation, expression, container);
                        }
                    }
                    if (isUsedBeforeDeclaration) {
                        error(errorLocation, ts.Diagnostics.Block_scoped_variable_0_used_before_its_declaration, ts.declarationNameToString(declaration.name));
                    }
                }
                /* Starting from 'initial' node walk up the parent chain until 'stopAt' node is reached.
                 * If at any point current node is equal to 'parent' node - return true.
                 * Return false if 'stopAt' node is reached or isFunctionLike(current) === true.
                 */
                function isSameScopeDescendentOf(initial, parent, stopAt) {
                    if (!parent) {
                        return false;
                    }
                    for (var current = initial; current && current !== stopAt && !ts.isFunctionLike(current); current = current.parent) {
                        if (current === parent) {
                            return true;
                        }
                    }
                    return false;
                }
                function getAnyImportSyntax(node) {
                    if (ts.isAliasSymbolDeclaration(node)) {
                        if (node.kind === 208 /* ImportEqualsDeclaration */) {
                            return node;
                        }
                        while (node && node.kind !== 209 /* ImportDeclaration */) {
                            node = node.parent;
                        }
                        return node;
                    }
                }
                function getDeclarationOfAliasSymbol(symbol) {
                    return ts.forEach(symbol.declarations, function (d) { return ts.isAliasSymbolDeclaration(d) ? d : undefined; });
                }
                function getTargetOfImportEqualsDeclaration(node) {
                    if (node.moduleReference.kind === 219 /* ExternalModuleReference */) {
                        return resolveExternalModuleSymbol(resolveExternalModuleName(node, ts.getExternalModuleImportEqualsDeclarationExpression(node)));
                    }
                    return getSymbolOfPartOfRightHandSideOfImportEquals(node.moduleReference, node);
                }
                function getTargetOfImportClause(node) {
                    var moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier);
                    if (moduleSymbol) {
                        var exportDefaultSymbol = resolveSymbol(moduleSymbol.exports["default"]);
                        if (!exportDefaultSymbol) {
                            error(node.name, ts.Diagnostics.External_module_0_has_no_default_export, symbolToString(moduleSymbol));
                        }
                        return exportDefaultSymbol;
                    }
                }
                function getTargetOfNamespaceImport(node) {
                    var moduleSpecifier = node.parent.parent.moduleSpecifier;
                    return resolveESModuleSymbol(resolveExternalModuleName(node, moduleSpecifier), moduleSpecifier);
                }
                function getMemberOfModuleVariable(moduleSymbol, name) {
                    if (moduleSymbol.flags & 3 /* Variable */) {
                        var typeAnnotation = moduleSymbol.valueDeclaration.type;
                        if (typeAnnotation) {
                            return getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name);
                        }
                    }
                }
                // This function creates a synthetic symbol that combines the value side of one symbol with the
                // type/namespace side of another symbol. Consider this example:
                //
                //   declare module graphics {
                //       interface Point {
                //           x: number;
                //           y: number;
                //       }
                //   }
                //   declare var graphics: {
                //       Point: new (x: number, y: number) => graphics.Point;
                //   }
                //   declare module "graphics" {
                //       export = graphics;
                //   }
                //
                // An 'import { Point } from "graphics"' needs to create a symbol that combines the value side 'Point'
                // property with the type/namespace side interface 'Point'.
                function combineValueAndTypeSymbols(valueSymbol, typeSymbol) {
                    if (valueSymbol.flags & (793056 /* Type */ | 1536 /* Namespace */)) {
                        return valueSymbol;
                    }
                    var result = createSymbol(valueSymbol.flags | typeSymbol.flags, valueSymbol.name);
                    result.declarations = ts.concatenate(valueSymbol.declarations, typeSymbol.declarations);
                    result.parent = valueSymbol.parent || typeSymbol.parent;
                    if (valueSymbol.valueDeclaration)
                        result.valueDeclaration = valueSymbol.valueDeclaration;
                    if (typeSymbol.members)
                        result.members = typeSymbol.members;
                    if (valueSymbol.exports)
                        result.exports = valueSymbol.exports;
                    return result;
                }
                function getExportOfModule(symbol, name) {
                    if (symbol.flags & 1536 /* Module */) {
                        var exports = getExportsOfSymbol(symbol);
                        if (ts.hasProperty(exports, name)) {
                            return resolveSymbol(exports[name]);
                        }
                    }
                }
                function getPropertyOfVariable(symbol, name) {
                    if (symbol.flags & 3 /* Variable */) {
                        var typeAnnotation = symbol.valueDeclaration.type;
                        if (typeAnnotation) {
                            return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name));
                        }
                    }
                }
                function getExternalModuleMember(node, specifier) {
                    var moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier);
                    var targetSymbol = resolveESModuleSymbol(moduleSymbol, node.moduleSpecifier);
                    if (targetSymbol) {
                        var name_4 = specifier.propertyName || specifier.name;
                        if (name_4.text) {
                            var symbolFromModule = getExportOfModule(targetSymbol, name_4.text);
                            var symbolFromVariable = getPropertyOfVariable(targetSymbol, name_4.text);
                            var symbol = symbolFromModule && symbolFromVariable ?
                                combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) :
                                symbolFromModule || symbolFromVariable;
                            if (!symbol) {
                                error(name_4, ts.Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(moduleSymbol), ts.declarationNameToString(name_4));
                            }
                            return symbol;
                        }
                    }
                }
                function getTargetOfImportSpecifier(node) {
                    return getExternalModuleMember(node.parent.parent.parent, node);
                }
                function getTargetOfExportSpecifier(node) {
                    return node.parent.parent.moduleSpecifier ?
                        getExternalModuleMember(node.parent.parent, node) :
                        resolveEntityName(node.propertyName || node.name, 107455 /* Value */ | 793056 /* Type */ | 1536 /* Namespace */);
                }
                function getTargetOfExportAssignment(node) {
                    return resolveEntityName(node.expression, 107455 /* Value */ | 793056 /* Type */ | 1536 /* Namespace */);
                }
                function getTargetOfAliasDeclaration(node) {
                    switch (node.kind) {
                        case 208 /* ImportEqualsDeclaration */:
                            return getTargetOfImportEqualsDeclaration(node);
                        case 210 /* ImportClause */:
                            return getTargetOfImportClause(node);
                        case 211 /* NamespaceImport */:
                            return getTargetOfNamespaceImport(node);
                        case 213 /* ImportSpecifier */:
                            return getTargetOfImportSpecifier(node);
                        case 217 /* ExportSpecifier */:
                            return getTargetOfExportSpecifier(node);
                        case 214 /* ExportAssignment */:
                            return getTargetOfExportAssignment(node);
                    }
                }
                function resolveSymbol(symbol) {
                    return symbol && symbol.flags & 8388608 /* Alias */ && !(symbol.flags & (107455 /* Value */ | 793056 /* Type */ | 1536 /* Namespace */)) ? resolveAlias(symbol) : symbol;
                }
                function resolveAlias(symbol) {
                    ts.Debug.assert((symbol.flags & 8388608 /* Alias */) !== 0, "Should only get Alias here.");
                    var links = getSymbolLinks(symbol);
                    if (!links.target) {
                        links.target = resolvingSymbol;
                        var node = getDeclarationOfAliasSymbol(symbol);
                        var target = getTargetOfAliasDeclaration(node);
                        if (links.target === resolvingSymbol) {
                            links.target = target || unknownSymbol;
                        }
                        else {
                            error(node, ts.Diagnostics.Circular_definition_of_import_alias_0, symbolToString(symbol));
                        }
                    }
                    else if (links.target === resolvingSymbol) {
                        links.target = unknownSymbol;
                    }
                    return links.target;
                }
                function markExportAsReferenced(node) {
                    var symbol = getSymbolOfNode(node);
                    var target = resolveAlias(symbol);
                    if (target) {
                        var markAlias = (target === unknownSymbol && compilerOptions.separateCompilation) ||
                            (target !== unknownSymbol && (target.flags & 107455 /* Value */) && !isConstEnumOrConstEnumOnlyModule(target));
                        if (markAlias) {
                            markAliasSymbolAsReferenced(symbol);
                        }
                    }
                }
                // When an alias symbol is referenced, we need to mark the entity it references as referenced and in turn repeat that until
                // we reach a non-alias or an exported entity (which is always considered referenced). We do this by checking the target of
                // the alias as an expression (which recursively takes us back here if the target references another alias).
                function markAliasSymbolAsReferenced(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.referenced) {
                        links.referenced = true;
                        var node = getDeclarationOfAliasSymbol(symbol);
                        if (node.kind === 214 /* ExportAssignment */) {
                            // export default <symbol>
                            checkExpressionCached(node.expression);
                        }
                        else if (node.kind === 217 /* ExportSpecifier */) {
                            // export { <symbol> } or export { <symbol> as foo }
                            checkExpressionCached(node.propertyName || node.name);
                        }
                        else if (ts.isInternalModuleImportEqualsDeclaration(node)) {
                            // import foo = <symbol>
                            checkExpressionCached(node.moduleReference);
                        }
                    }
                }
                // This function is only for imports with entity names
                function getSymbolOfPartOfRightHandSideOfImportEquals(entityName, importDeclaration) {
                    if (!importDeclaration) {
                        importDeclaration = ts.getAncestor(entityName, 208 /* ImportEqualsDeclaration */);
                        ts.Debug.assert(importDeclaration !== undefined);
                    }
                    // There are three things we might try to look for. In the following examples,
                    // the search term is enclosed in |...|:
                    //
                    //     import a = |b|; // Namespace
                    //     import a = |b.c|; // Value, type, namespace
                    //     import a = |b.c|.d; // Namespace
                    if (entityName.kind === 65 /* Identifier */ && ts.isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
                        entityName = entityName.parent;
                    }
                    // Check for case 1 and 3 in the above example
                    if (entityName.kind === 65 /* Identifier */ || entityName.parent.kind === 126 /* QualifiedName */) {
                        return resolveEntityName(entityName, 1536 /* Namespace */);
                    }
                    else {
                        // Case 2 in above example
                        // entityName.kind could be a QualifiedName or a Missing identifier
                        ts.Debug.assert(entityName.parent.kind === 208 /* ImportEqualsDeclaration */);
                        return resolveEntityName(entityName, 107455 /* Value */ | 793056 /* Type */ | 1536 /* Namespace */);
                    }
                }
                function getFullyQualifiedName(symbol) {
                    return symbol.parent ? getFullyQualifiedName(symbol.parent) + "." + symbolToString(symbol) : symbolToString(symbol);
                }
                // Resolves a qualified name and any involved aliases
                function resolveEntityName(name, meaning) {
                    if (ts.nodeIsMissing(name)) {
                        return undefined;
                    }
                    var symbol;
                    if (name.kind === 65 /* Identifier */) {
                        symbol = resolveName(name, name.text, meaning, ts.Diagnostics.Cannot_find_name_0, name);
                        if (!symbol) {
                            return undefined;
                        }
                    }
                    else if (name.kind === 126 /* QualifiedName */ || name.kind === 155 /* PropertyAccessExpression */) {
                        var left = name.kind === 126 /* QualifiedName */ ? name.left : name.expression;
                        var right = name.kind === 126 /* QualifiedName */ ? name.right : name.name;
                        var namespace = resolveEntityName(left, 1536 /* Namespace */);
                        if (!namespace || namespace === unknownSymbol || ts.nodeIsMissing(right)) {
                            return undefined;
                        }
                        symbol = getSymbol(getExportsOfSymbol(namespace), right.text, meaning);
                        if (!symbol) {
                            error(right, ts.Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace), ts.declarationNameToString(right));
                            return undefined;
                        }
                    }
                    else {
                        ts.Debug.fail("Unknown entity name kind.");
                    }
                    ts.Debug.assert((symbol.flags & 16777216 /* Instantiated */) === 0, "Should never get an instantiated symbol here.");
                    return symbol.flags & meaning ? symbol : resolveAlias(symbol);
                }
                function isExternalModuleNameRelative(moduleName) {
                    // TypeScript 1.0 spec (April 2014): 11.2.1
                    // An external module name is "relative" if the first term is "." or "..".
                    return moduleName.substr(0, 2) === "./" || moduleName.substr(0, 3) === "../" || moduleName.substr(0, 2) === ".\\" || moduleName.substr(0, 3) === "..\\";
                }
                function resolveExternalModuleName(location, moduleReferenceExpression) {
                    if (moduleReferenceExpression.kind !== 8 /* StringLiteral */) {
                        return;
                    }
                    var moduleReferenceLiteral = moduleReferenceExpression;
                    var searchPath = ts.getDirectoryPath(getSourceFile(location).fileName);
                    // Module names are escaped in our symbol table.  However, string literal values aren't.
                    // Escape the name in the "require(...)" clause to ensure we find the right symbol.
                    var moduleName = ts.escapeIdentifier(moduleReferenceLiteral.text);
                    if (!moduleName)
                        return;
                    var isRelative = isExternalModuleNameRelative(moduleName);
                    if (!isRelative) {
                        var symbol = getSymbol(globals, '"' + moduleName + '"', 512 /* ValueModule */);
                        if (symbol) {
                            return symbol;
                        }
                    }
                    var sourceFile;
                    while (true) {
                        var fileName = ts.normalizePath(ts.combinePaths(searchPath, moduleName));
                        sourceFile = host.getSourceFile(fileName + ".ts") || host.getSourceFile(fileName + ".d.ts");
                        if (sourceFile || isRelative) {
                            break;
                        }
                        var parentPath = ts.getDirectoryPath(searchPath);
                        if (parentPath === searchPath) {
                            break;
                        }
                        searchPath = parentPath;
                    }
                    if (sourceFile) {
                        if (sourceFile.symbol) {
                            return sourceFile.symbol;
                        }
                        error(moduleReferenceLiteral, ts.Diagnostics.File_0_is_not_an_external_module, sourceFile.fileName);
                        return;
                    }
                    error(moduleReferenceLiteral, ts.Diagnostics.Cannot_find_external_module_0, moduleName);
                }
                // An external module with an 'export =' declaration resolves to the target of the 'export =' declaration,
                // and an external module with no 'export =' declaration resolves to the module itself.
                function resolveExternalModuleSymbol(moduleSymbol) {
                    return moduleSymbol && resolveSymbol(moduleSymbol.exports["export="]) || moduleSymbol;
                }
                // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export ='
                // references a symbol that is at least declared as a module or a variable. The target of the 'export =' may
                // combine other declarations with the module or variable (e.g. a class/module, function/module, interface/variable).
                function resolveESModuleSymbol(moduleSymbol, moduleReferenceExpression) {
                    var symbol = resolveExternalModuleSymbol(moduleSymbol);
                    if (symbol && !(symbol.flags & (1536 /* Module */ | 3 /* Variable */))) {
                        error(moduleReferenceExpression, ts.Diagnostics.External_module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol));
                        symbol = undefined;
                    }
                    return symbol;
                }
                function getExportAssignmentSymbol(moduleSymbol) {
                    return moduleSymbol.exports["export="];
                }
                function getExportsOfModuleAsArray(moduleSymbol) {
                    return symbolsToArray(getExportsOfModule(moduleSymbol));
                }
                function getExportsOfSymbol(symbol) {
                    return symbol.flags & 1536 /* Module */ ? getExportsOfModule(symbol) : symbol.exports || emptySymbols;
                }
                function getExportsOfModule(moduleSymbol) {
                    var links = getSymbolLinks(moduleSymbol);
                    return links.resolvedExports || (links.resolvedExports = getExportsForModule(moduleSymbol));
                }
                function extendExportSymbols(target, source) {
                    for (var id in source) {
                        if (id !== "default" && !ts.hasProperty(target, id)) {
                            target[id] = source[id];
                        }
                    }
                }
                function getExportsForModule(moduleSymbol) {
                    var result;
                    var visitedSymbols = [];
                    visit(moduleSymbol);
                    return result || moduleSymbol.exports;
                    // The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example,
                    // module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error.
                    function visit(symbol) {
                        if (symbol && symbol.flags & 1952 /* HasExports */ && !ts.contains(visitedSymbols, symbol)) {
                            visitedSymbols.push(symbol);
                            if (symbol !== moduleSymbol) {
                                if (!result) {
                                    result = cloneSymbolTable(moduleSymbol.exports);
                                }
                                extendExportSymbols(result, symbol.exports);
                            }
                            // All export * declarations are collected in an __export symbol by the binder
                            var exportStars = symbol.exports["__export"];
                            if (exportStars) {
                                for (var _i = 0, _a = exportStars.declarations; _i < _a.length; _i++) {
                                    var node = _a[_i];
                                    visit(resolveExternalModuleName(node, node.moduleSpecifier));
                                }
                            }
                        }
                    }
                }
                function getMergedSymbol(symbol) {
                    var merged;
                    return symbol && symbol.mergeId && (merged = mergedSymbols[symbol.mergeId]) ? merged : symbol;
                }
                function getSymbolOfNode(node) {
                    return getMergedSymbol(node.symbol);
                }
                function getParentOfSymbol(symbol) {
                    return getMergedSymbol(symbol.parent);
                }
                function getExportSymbolOfValueSymbolIfExported(symbol) {
                    return symbol && (symbol.flags & 1048576 /* ExportValue */) !== 0
                        ? getMergedSymbol(symbol.exportSymbol)
                        : symbol;
                }
                function symbolIsValue(symbol) {
                    // If it is an instantiated symbol, then it is a value if the symbol it is an
                    // instantiation of is a value.
                    if (symbol.flags & 16777216 /* Instantiated */) {
                        return symbolIsValue(getSymbolLinks(symbol).target);
                    }
                    // If the symbol has the value flag, it is trivially a value.
                    if (symbol.flags & 107455 /* Value */) {
                        return true;
                    }
                    // If it is an alias, then it is a value if the symbol it resolves to is a value.
                    if (symbol.flags & 8388608 /* Alias */) {
                        return (resolveAlias(symbol).flags & 107455 /* Value */) !== 0;
                    }
                    return false;
                }
                function findConstructorDeclaration(node) {
                    var members = node.members;
                    for (var _i = 0; _i < members.length; _i++) {
                        var member = members[_i];
                        if (member.kind === 135 /* Constructor */ && ts.nodeIsPresent(member.body)) {
                            return member;
                        }
                    }
                }
                function createType(flags) {
                    var result = new Type(checker, flags);
                    result.id = typeCount++;
                    return result;
                }
                function createIntrinsicType(kind, intrinsicName) {
                    var type = createType(kind);
                    type.intrinsicName = intrinsicName;
                    return type;
                }
                function createObjectType(kind, symbol) {
                    var type = createType(kind);
                    type.symbol = symbol;
                    return type;
                }
                // A reserved member name starts with two underscores, but the third character cannot be an underscore
                // or the @ symbol. A third underscore indicates an escaped form of an identifer that started
                // with at least two underscores. The @ character indicates that the name is denoted by a well known ES
                // Symbol instance.
                function isReservedMemberName(name) {
                    return name.charCodeAt(0) === 95 /* _ */ &&
                        name.charCodeAt(1) === 95 /* _ */ &&
                        name.charCodeAt(2) !== 95 /* _ */ &&
                        name.charCodeAt(2) !== 64 /* at */;
                }
                function getNamedMembers(members) {
                    var result;
                    for (var id in members) {
                        if (ts.hasProperty(members, id)) {
                            if (!isReservedMemberName(id)) {
                                if (!result)
                                    result = [];
                                var symbol = members[id];
                                if (symbolIsValue(symbol)) {
                                    result.push(symbol);
                                }
                            }
                        }
                    }
                    return result || emptyArray;
                }
                function setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType) {
                    type.members = members;
                    type.properties = getNamedMembers(members);
                    type.callSignatures = callSignatures;
                    type.constructSignatures = constructSignatures;
                    if (stringIndexType)
                        type.stringIndexType = stringIndexType;
                    if (numberIndexType)
                        type.numberIndexType = numberIndexType;
                    return type;
                }
                function createAnonymousType(symbol, members, callSignatures, constructSignatures, stringIndexType, numberIndexType) {
                    return setObjectTypeMembers(createObjectType(32768 /* Anonymous */, symbol), members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
                }
                function forEachSymbolTableInScope(enclosingDeclaration, callback) {
                    var result;
                    for (var location_1 = enclosingDeclaration; location_1; location_1 = location_1.parent) {
                        // Locals of a source file are not in scope (because they get merged into the global symbol table)
                        if (location_1.locals && !isGlobalSourceFile(location_1)) {
                            if (result = callback(location_1.locals)) {
                                return result;
                            }
                        }
                        switch (location_1.kind) {
                            case 227 /* SourceFile */:
                                if (!ts.isExternalModule(location_1)) {
                                    break;
                                }
                            case 205 /* ModuleDeclaration */:
                                if (result = callback(getSymbolOfNode(location_1).exports)) {
                                    return result;
                                }
                                break;
                            case 201 /* ClassDeclaration */:
                            case 202 /* InterfaceDeclaration */:
                                if (result = callback(getSymbolOfNode(location_1).members)) {
                                    return result;
                                }
                                break;
                        }
                    }
                    return callback(globals);
                }
                function getQualifiedLeftMeaning(rightMeaning) {
                    // If we are looking in value space, the parent meaning is value, other wise it is namespace
                    return rightMeaning === 107455 /* Value */ ? 107455 /* Value */ : 1536 /* Namespace */;
                }
                function getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, useOnlyExternalAliasing) {
                    function getAccessibleSymbolChainFromSymbolTable(symbols) {
                        function canQualifySymbol(symbolFromSymbolTable, meaning) {
                            // If the symbol is equivalent and doesn't need further qualification, this symbol is accessible
                            if (!needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning)) {
                                return true;
                            }
                            // If symbol needs qualification, make sure that parent is accessible, if it is then this symbol is accessible too
                            var accessibleParent = getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing);
                            return !!accessibleParent;
                        }
                        function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol) {
                            if (symbol === (resolvedAliasSymbol || symbolFromSymbolTable)) {
                                // if the symbolFromSymbolTable is not external module (it could be if it was determined as ambient external module and would be in globals table)
                                // and if symbolfrom symbolTable or alias resolution matches the symbol,
                                // check the symbol can be qualified, it is only then this symbol is accessible
                                return !ts.forEach(symbolFromSymbolTable.declarations, hasExternalModuleSymbol) &&
                                    canQualifySymbol(symbolFromSymbolTable, meaning);
                            }
                        }
                        // If symbol is directly available by its name in the symbol table
                        if (isAccessible(ts.lookUp(symbols, symbol.name))) {
                            return [symbol];
                        }
                        // Check if symbol is any of the alias
                        return ts.forEachValue(symbols, function (symbolFromSymbolTable) {
                            if (symbolFromSymbolTable.flags & 8388608 /* Alias */ && symbolFromSymbolTable.name !== "export=") {
                                if (!useOnlyExternalAliasing ||
                                    // Is this external alias, then use it to name
                                    ts.forEach(symbolFromSymbolTable.declarations, ts.isExternalModuleImportEqualsDeclaration)) {
                                    var resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
                                    if (isAccessible(symbolFromSymbolTable, resolveAlias(symbolFromSymbolTable))) {
                                        return [symbolFromSymbolTable];
                                    }
                                    // Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain
                                    // but only if the symbolFromSymbolTable can be qualified
                                    var accessibleSymbolsFromExports = resolvedImportedSymbol.exports ? getAccessibleSymbolChainFromSymbolTable(resolvedImportedSymbol.exports) : undefined;
                                    if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
                                        return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports);
                                    }
                                }
                            }
                        });
                    }
                    if (symbol) {
                        return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable);
                    }
                }
                function needsQualification(symbol, enclosingDeclaration, meaning) {
                    var qualify = false;
                    forEachSymbolTableInScope(enclosingDeclaration, function (symbolTable) {
                        // If symbol of this name is not available in the symbol table we are ok
                        if (!ts.hasProperty(symbolTable, symbol.name)) {
                            // Continue to the next symbol table
                            return false;
                        }
                        // If the symbol with this name is present it should refer to the symbol
                        var symbolFromSymbolTable = symbolTable[symbol.name];
                        if (symbolFromSymbolTable === symbol) {
                            // No need to qualify
                            return true;
                        }
                        // Qualify if the symbol from symbol table has same meaning as expected
                        symbolFromSymbolTable = (symbolFromSymbolTable.flags & 8388608 /* Alias */) ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable;
                        if (symbolFromSymbolTable.flags & meaning) {
                            qualify = true;
                            return true;
                        }
                        // Continue to the next symbol table
                        return false;
                    });
                    return qualify;
                }
                function isSymbolAccessible(symbol, enclosingDeclaration, meaning) {
                    if (symbol && enclosingDeclaration && !(symbol.flags & 262144 /* TypeParameter */)) {
                        var initialSymbol = symbol;
                        var meaningToLook = meaning;
                        while (symbol) {
                            // Symbol is accessible if it by itself is accessible
                            var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaningToLook, false);
                            if (accessibleSymbolChain) {
                                var hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0]);
                                if (!hasAccessibleDeclarations) {
                                    return {
                                        accessibility: 1 /* NotAccessible */,
                                        errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
                                        errorModuleName: symbol !== initialSymbol ? symbolToString(symbol, enclosingDeclaration, 1536 /* Namespace */) : undefined
                                    };
                                }
                                return hasAccessibleDeclarations;
                            }
                            // If we haven't got the accessible symbol, it doesn't mean the symbol is actually inaccessible.
                            // It could be a qualified symbol and hence verify the path
                            // e.g.:
                            // module m {
                            //     export class c {
                            //     }
                            // }
                            // let x: typeof m.c
                            // In the above example when we start with checking if typeof m.c symbol is accessible,
                            // we are going to see if c can be accessed in scope directly.
                            // But it can't, hence the accessible is going to be undefined, but that doesn't mean m.c is inaccessible
                            // It is accessible if the parent m is accessible because then m.c can be accessed through qualification
                            meaningToLook = getQualifiedLeftMeaning(meaning);
                            symbol = getParentOfSymbol(symbol);
                        }
                        // This could be a symbol that is not exported in the external module
                        // or it could be a symbol from different external module that is not aliased and hence cannot be named
                        var symbolExternalModule = ts.forEach(initialSymbol.declarations, getExternalModuleContainer);
                        if (symbolExternalModule) {
                            var enclosingExternalModule = getExternalModuleContainer(enclosingDeclaration);
                            if (symbolExternalModule !== enclosingExternalModule) {
                                // name from different external module that is not visible
                                return {
                                    accessibility: 2 /* CannotBeNamed */,
                                    errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
                                    errorModuleName: symbolToString(symbolExternalModule)
                                };
                            }
                        }
                        // Just a local name that is not accessible
                        return {
                            accessibility: 1 /* NotAccessible */,
                            errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning)
                        };
                    }
                    return { accessibility: 0 /* Accessible */ };
                    function getExternalModuleContainer(declaration) {
                        for (; declaration; declaration = declaration.parent) {
                            if (hasExternalModuleSymbol(declaration)) {
                                return getSymbolOfNode(declaration);
                            }
                        }
                    }
                }
                function hasExternalModuleSymbol(declaration) {
                    return (declaration.kind === 205 /* ModuleDeclaration */ && declaration.name.kind === 8 /* StringLiteral */) ||
                        (declaration.kind === 227 /* SourceFile */ && ts.isExternalModule(declaration));
                }
                function hasVisibleDeclarations(symbol) {
                    var aliasesToMakeVisible;
                    if (ts.forEach(symbol.declarations, function (declaration) { return !getIsDeclarationVisible(declaration); })) {
                        return undefined;
                    }
                    return { accessibility: 0 /* Accessible */, aliasesToMakeVisible: aliasesToMakeVisible };
                    function getIsDeclarationVisible(declaration) {
                        if (!isDeclarationVisible(declaration)) {
                            // Mark the unexported alias as visible if its parent is visible
                            // because these kind of aliases can be used to name types in declaration file
                            var anyImportSyntax = getAnyImportSyntax(declaration);
                            if (anyImportSyntax &&
                                !(anyImportSyntax.flags & 1 /* Export */) &&
                                isDeclarationVisible(anyImportSyntax.parent)) {
                                getNodeLinks(declaration).isVisible = true;
                                if (aliasesToMakeVisible) {
                                    if (!ts.contains(aliasesToMakeVisible, anyImportSyntax)) {
                                        aliasesToMakeVisible.push(anyImportSyntax);
                                    }
                                }
                                else {
                                    aliasesToMakeVisible = [anyImportSyntax];
                                }
                                return true;
                            }
                            // Declaration is not visible
                            return false;
                        }
                        return true;
                    }
                }
                function isEntityNameVisible(entityName, enclosingDeclaration) {
                    // get symbol of the first identifier of the entityName
                    var meaning;
                    if (entityName.parent.kind === 144 /* TypeQuery */) {
                        // Typeof value
                        meaning = 107455 /* Value */ | 1048576 /* ExportValue */;
                    }
                    else if (entityName.kind === 126 /* QualifiedName */ || entityName.kind === 155 /* PropertyAccessExpression */ ||
                        entityName.parent.kind === 208 /* ImportEqualsDeclaration */) {
                        // Left identifier from type reference or TypeAlias
                        // Entity name of the import declaration
                        meaning = 1536 /* Namespace */;
                    }
                    else {
                        // Type Reference or TypeAlias entity = Identifier
                        meaning = 793056 /* Type */;
                    }
                    var firstIdentifier = getFirstIdentifier(entityName);
                    var symbol = resolveName(enclosingDeclaration, firstIdentifier.text, meaning, undefined, undefined);
                    // Verify if the symbol is accessible
                    return (symbol && hasVisibleDeclarations(symbol)) || {
                        accessibility: 1 /* NotAccessible */,
                        errorSymbolName: ts.getTextOfNode(firstIdentifier),
                        errorNode: firstIdentifier
                    };
                }
                function writeKeyword(writer, kind) {
                    writer.writeKeyword(ts.tokenToString(kind));
                }
                function writePunctuation(writer, kind) {
                    writer.writePunctuation(ts.tokenToString(kind));
                }
                function writeSpace(writer) {
                    writer.writeSpace(" ");
                }
                function symbolToString(symbol, enclosingDeclaration, meaning) {
                    var writer = ts.getSingleLineStringWriter();
                    getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning);
                    var result = writer.string();
                    ts.releaseStringWriter(writer);
                    return result;
                }
                function typeToString(type, enclosingDeclaration, flags) {
                    var writer = ts.getSingleLineStringWriter();
                    getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
                    var result = writer.string();
                    ts.releaseStringWriter(writer);
                    var maxLength = compilerOptions.noErrorTruncation || flags & 4 /* NoTruncation */ ? undefined : 100;
                    if (maxLength && result.length >= maxLength) {
                        result = result.substr(0, maxLength - "...".length) + "...";
                    }
                    return result;
                }
                function getTypeAliasForTypeLiteral(type) {
                    if (type.symbol && type.symbol.flags & 2048 /* TypeLiteral */) {
                        var node = type.symbol.declarations[0].parent;
                        while (node.kind === 149 /* ParenthesizedType */) {
                            node = node.parent;
                        }
                        if (node.kind === 203 /* TypeAliasDeclaration */) {
                            return getSymbolOfNode(node);
                        }
                    }
                    return undefined;
                }
                // This is for caching the result of getSymbolDisplayBuilder. Do not access directly.
                var _displayBuilder;
                function getSymbolDisplayBuilder() {
                    /**
                     * Writes only the name of the symbol out to the writer. Uses the original source text
                     * for the name of the symbol if it is available to match how the user inputted the name.
                     */
                    function appendSymbolNameOnly(symbol, writer) {
                        if (symbol.declarations && symbol.declarations.length > 0) {
                            var declaration = symbol.declarations[0];
                            if (declaration.name) {
                                writer.writeSymbol(ts.declarationNameToString(declaration.name), symbol);
                                return;
                            }
                        }
                        writer.writeSymbol(symbol.name, symbol);
                    }
                    /**
                     * Enclosing declaration is optional when we don't want to get qualified name in the enclosing declaration scope
                     * Meaning needs to be specified if the enclosing declaration is given
                     */
                    function buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags, typeFlags) {
                        var parentSymbol;
                        function appendParentTypeArgumentsAndSymbolName(symbol) {
                            if (parentSymbol) {
                                // Write type arguments of instantiated class/interface here
                                if (flags & 1 /* WriteTypeParametersOrArguments */) {
                                    if (symbol.flags & 16777216 /* Instantiated */) {
                                        buildDisplayForTypeArgumentsAndDelimiters(getTypeParametersOfClassOrInterface(parentSymbol), symbol.mapper, writer, enclosingDeclaration);
                                    }
                                    else {
                                        buildTypeParameterDisplayFromSymbol(parentSymbol, writer, enclosingDeclaration);
                                    }
                                }
                                writePunctuation(writer, 20 /* DotToken */);
                            }
                            parentSymbol = symbol;
                            appendSymbolNameOnly(symbol, writer);
                        }
                        // Let the writer know we just wrote out a symbol.  The declaration emitter writer uses
                        // this to determine if an import it has previously seen (and not written out) needs
                        // to be written to the file once the walk of the tree is complete.
                        //
                        // NOTE(cyrusn): This approach feels somewhat unfortunate.  A simple pass over the tree
                        // up front (for example, during checking) could determine if we need to emit the imports
                        // and we could then access that data during declaration emit.
                        writer.trackSymbol(symbol, enclosingDeclaration, meaning);
                        function walkSymbol(symbol, meaning) {
                            if (symbol) {
                                var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, !!(flags & 2 /* UseOnlyExternalAliasing */));
                                if (!accessibleSymbolChain ||
                                    needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) {
                                    // Go up and add our parent.
                                    walkSymbol(getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol), getQualifiedLeftMeaning(meaning));
                                }
                                if (accessibleSymbolChain) {
                                    for (var _i = 0; _i < accessibleSymbolChain.length; _i++) {
                                        var accessibleSymbol = accessibleSymbolChain[_i];
                                        appendParentTypeArgumentsAndSymbolName(accessibleSymbol);
                                    }
                                }
                                else {
                                    // If we didn't find accessible symbol chain for this symbol, break if this is external module
                                    if (!parentSymbol && ts.forEach(symbol.declarations, hasExternalModuleSymbol)) {
                                        return;
                                    }
                                    // if this is anonymous type break
                                    if (symbol.flags & 2048 /* TypeLiteral */ || symbol.flags & 4096 /* ObjectLiteral */) {
                                        return;
                                    }
                                    appendParentTypeArgumentsAndSymbolName(symbol);
                                }
                            }
                        }
                        // Get qualified name if the symbol is not a type parameter
                        // and there is an enclosing declaration or we specifically
                        // asked for it
                        var isTypeParameter = symbol.flags & 262144 /* TypeParameter */;
                        var typeFormatFlag = 128 /* UseFullyQualifiedType */ & typeFlags;
                        if (!isTypeParameter && (enclosingDeclaration || typeFormatFlag)) {
                            walkSymbol(symbol, meaning);
                            return;
                        }
                        return appendParentTypeArgumentsAndSymbolName(symbol);
                    }
                    function buildTypeDisplay(type, writer, enclosingDeclaration, globalFlags, typeStack) {
                        var globalFlagsToPass = globalFlags & 16 /* WriteOwnNameForAnyLike */;
                        return writeType(type, globalFlags);
                        function writeType(type, flags) {
                            // Write undefined/null type as any
                            if (type.flags & 1048703 /* Intrinsic */) {
                                // Special handling for unknown / resolving types, they should show up as any and not unknown or __resolving
                                writer.writeKeyword(!(globalFlags & 16 /* WriteOwnNameForAnyLike */) &&
                                    (type.flags & 1 /* Any */) ? "any" : type.intrinsicName);
                            }
                            else if (type.flags & 4096 /* Reference */) {
                                writeTypeReference(type, flags);
                            }
                            else if (type.flags & (1024 /* Class */ | 2048 /* Interface */ | 128 /* Enum */ | 512 /* TypeParameter */)) {
                                // The specified symbol flags need to be reinterpreted as type flags
                                buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, 793056 /* Type */, 0 /* None */, flags);
                            }
                            else if (type.flags & 8192 /* Tuple */) {
                                writeTupleType(type);
                            }
                            else if (type.flags & 16384 /* Union */) {
                                writeUnionType(type, flags);
                            }
                            else if (type.flags & 32768 /* Anonymous */) {
                                writeAnonymousType(type, flags);
                            }
                            else if (type.flags & 256 /* StringLiteral */) {
                                writer.writeStringLiteral(type.text);
                            }
                            else {
                                // Should never get here
                                // { ... }
                                writePunctuation(writer, 14 /* OpenBraceToken */);
                                writeSpace(writer);
                                writePunctuation(writer, 21 /* DotDotDotToken */);
                                writeSpace(writer);
                                writePunctuation(writer, 15 /* CloseBraceToken */);
                            }
                        }
                        function writeTypeList(types, union) {
                            for (var i = 0; i < types.length; i++) {
                                if (i > 0) {
                                    if (union) {
                                        writeSpace(writer);
                                    }
                                    writePunctuation(writer, union ? 44 /* BarToken */ : 23 /* CommaToken */);
                                    writeSpace(writer);
                                }
                                writeType(types[i], union ? 64 /* InElementType */ : 0 /* None */);
                            }
                        }
                        function writeTypeReference(type, flags) {
                            if (type.target === globalArrayType && !(flags & 1 /* WriteArrayAsGenericType */)) {
                                writeType(type.typeArguments[0], 64 /* InElementType */);
                                writePunctuation(writer, 18 /* OpenBracketToken */);
                                writePunctuation(writer, 19 /* CloseBracketToken */);
                            }
                            else {
                                buildSymbolDisplay(type.target.symbol, writer, enclosingDeclaration, 793056 /* Type */);
                                writePunctuation(writer, 24 /* LessThanToken */);
                                writeTypeList(type.typeArguments, false);
                                writePunctuation(writer, 25 /* GreaterThanToken */);
                            }
                        }
                        function writeTupleType(type) {
                            writePunctuation(writer, 18 /* OpenBracketToken */);
                            writeTypeList(type.elementTypes, false);
                            writePunctuation(writer, 19 /* CloseBracketToken */);
                        }
                        function writeUnionType(type, flags) {
                            if (flags & 64 /* InElementType */) {
                                writePunctuation(writer, 16 /* OpenParenToken */);
                            }
                            writeTypeList(type.types, true);
                            if (flags & 64 /* InElementType */) {
                                writePunctuation(writer, 17 /* CloseParenToken */);
                            }
                        }
                        function writeAnonymousType(type, flags) {
                            // Always use 'typeof T' for type of class, enum, and module objects
                            if (type.symbol && type.symbol.flags & (32 /* Class */ | 384 /* Enum */ | 512 /* ValueModule */)) {
                                writeTypeofSymbol(type, flags);
                            }
                            else if (shouldWriteTypeOfFunctionSymbol()) {
                                writeTypeofSymbol(type, flags);
                            }
                            else if (typeStack && ts.contains(typeStack, type)) {
                                // If type is an anonymous type literal in a type alias declaration, use type alias name
                                var typeAlias = getTypeAliasForTypeLiteral(type);
                                if (typeAlias) {
                                    // The specified symbol flags need to be reinterpreted as type flags
                                    buildSymbolDisplay(typeAlias, writer, enclosingDeclaration, 793056 /* Type */, 0 /* None */, flags);
                                }
                                else {
                                    // Recursive usage, use any
                                    writeKeyword(writer, 112 /* AnyKeyword */);
                                }
                            }
                            else {
                                if (!typeStack) {
                                    typeStack = [];
                                }
                                typeStack.push(type);
                                writeLiteralType(type, flags);
                                typeStack.pop();
                            }
                            function shouldWriteTypeOfFunctionSymbol() {
                                if (type.symbol) {
                                    var isStaticMethodSymbol = !!(type.symbol.flags & 8192 /* Method */ &&
                                        ts.forEach(type.symbol.declarations, function (declaration) { return declaration.flags & 128 /* Static */; }));
                                    var isNonLocalFunctionSymbol = !!(type.symbol.flags & 16 /* Function */) &&
                                        (type.symbol.parent ||
                                            ts.forEach(type.symbol.declarations, function (declaration) {
                                                return declaration.parent.kind === 227 /* SourceFile */ || declaration.parent.kind === 206 /* ModuleBlock */;
                                            }));
                                    if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
                                        // typeof is allowed only for static/non local functions
                                        return !!(flags & 2 /* UseTypeOfFunction */) ||
                                            (typeStack && ts.contains(typeStack, type)); // it is type of the symbol uses itself recursively
                                    }
                                }
                            }
                        }
                        function writeTypeofSymbol(type, typeFormatFlags) {
                            writeKeyword(writer, 97 /* TypeOfKeyword */);
                            writeSpace(writer);
                            buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, 107455 /* Value */, 0 /* None */, typeFormatFlags);
                        }
                        function getIndexerParameterName(type, indexKind, fallbackName) {
                            var declaration = getIndexDeclarationOfSymbol(type.symbol, indexKind);
                            if (!declaration) {
                                // declaration might not be found if indexer was added from the contextual type.
                                // in this case use fallback name
                                return fallbackName;
                            }
                            ts.Debug.assert(declaration.parameters.length !== 0);
                            return ts.declarationNameToString(declaration.parameters[0].name);
                        }
                        function writeLiteralType(type, flags) {
                            var resolved = resolveObjectOrUnionTypeMembers(type);
                            if (!resolved.properties.length && !resolved.stringIndexType && !resolved.numberIndexType) {
                                if (!resolved.callSignatures.length && !resolved.constructSignatures.length) {
                                    writePunctuation(writer, 14 /* OpenBraceToken */);
                                    writePunctuation(writer, 15 /* CloseBraceToken */);
                                    return;
                                }
                                if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) {
                                    if (flags & 64 /* InElementType */) {
                                        writePunctuation(writer, 16 /* OpenParenToken */);
                                    }
                                    buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | 8 /* WriteArrowStyleSignature */, typeStack);
                                    if (flags & 64 /* InElementType */) {
                                        writePunctuation(writer, 17 /* CloseParenToken */);
                                    }
                                    return;
                                }
                                if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) {
                                    if (flags & 64 /* InElementType */) {
                                        writePunctuation(writer, 16 /* OpenParenToken */);
                                    }
                                    writeKeyword(writer, 88 /* NewKeyword */);
                                    writeSpace(writer);
                                    buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | 8 /* WriteArrowStyleSignature */, typeStack);
                                    if (flags & 64 /* InElementType */) {
                                        writePunctuation(writer, 17 /* CloseParenToken */);
                                    }
                                    return;
                                }
                            }
                            writePunctuation(writer, 14 /* OpenBraceToken */);
                            writer.writeLine();
                            writer.increaseIndent();
                            for (var _i = 0, _a = resolved.callSignatures; _i < _a.length; _i++) {
                                var signature = _a[_i];
                                buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
                                writePunctuation(writer, 22 /* SemicolonToken */);
                                writer.writeLine();
                            }
                            for (var _b = 0, _c = resolved.constructSignatures; _b < _c.length; _b++) {
                                var signature = _c[_b];
                                writeKeyword(writer, 88 /* NewKeyword */);
                                writeSpace(writer);
                                buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
                                writePunctuation(writer, 22 /* SemicolonToken */);
                                writer.writeLine();
                            }
                            if (resolved.stringIndexType) {
                                // [x: string]:
                                writePunctuation(writer, 18 /* OpenBracketToken */);
                                writer.writeParameter(getIndexerParameterName(resolved, 0 /* String */, "x"));
                                writePunctuation(writer, 51 /* ColonToken */);
                                writeSpace(writer);
                                writeKeyword(writer, 121 /* StringKeyword */);
                                writePunctuation(writer, 19 /* CloseBracketToken */);
                                writePunctuation(writer, 51 /* ColonToken */);
                                writeSpace(writer);
                                writeType(resolved.stringIndexType, 0 /* None */);
                                writePunctuation(writer, 22 /* SemicolonToken */);
                                writer.writeLine();
                            }
                            if (resolved.numberIndexType) {
                                // [x: number]:
                                writePunctuation(writer, 18 /* OpenBracketToken */);
                                writer.writeParameter(getIndexerParameterName(resolved, 1 /* Number */, "x"));
                                writePunctuation(writer, 51 /* ColonToken */);
                                writeSpace(writer);
                                writeKeyword(writer, 119 /* NumberKeyword */);
                                writePunctuation(writer, 19 /* CloseBracketToken */);
                                writePunctuation(writer, 51 /* ColonToken */);
                                writeSpace(writer);
                                writeType(resolved.numberIndexType, 0 /* None */);
                                writePunctuation(writer, 22 /* SemicolonToken */);
                                writer.writeLine();
                            }
                            for (var _d = 0, _e = resolved.properties; _d < _e.length; _d++) {
                                var p = _e[_d];
                                var t = getTypeOfSymbol(p);
                                if (p.flags & (16 /* Function */ | 8192 /* Method */) && !getPropertiesOfObjectType(t).length) {
                                    var signatures = getSignaturesOfType(t, 0 /* Call */);
                                    for (var _f = 0; _f < signatures.length; _f++) {
                                        var signature = signatures[_f];
                                        buildSymbolDisplay(p, writer);
                                        if (p.flags & 536870912 /* Optional */) {
                                            writePunctuation(writer, 50 /* QuestionToken */);
                                        }
                                        buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
                                        writePunctuation(writer, 22 /* SemicolonToken */);
                                        writer.writeLine();
                                    }
                                }
                                else {
                                    buildSymbolDisplay(p, writer);
                                    if (p.flags & 536870912 /* Optional */) {
                                        writePunctuation(writer, 50 /* QuestionToken */);
                                    }
                                    writePunctuation(writer, 51 /* ColonToken */);
                                    writeSpace(writer);
                                    writeType(t, 0 /* None */);
                                    writePunctuation(writer, 22 /* SemicolonToken */);
                                    writer.writeLine();
                                }
                            }
                            writer.decreaseIndent();
                            writePunctuation(writer, 15 /* CloseBraceToken */);
                        }
                    }
                    function buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaraiton, flags) {
                        var targetSymbol = getTargetSymbol(symbol);
                        if (targetSymbol.flags & 32 /* Class */ || targetSymbol.flags & 64 /* Interface */) {
                            buildDisplayForTypeParametersAndDelimiters(getTypeParametersOfClassOrInterface(symbol), writer, enclosingDeclaraiton, flags);
                        }
                    }
                    function buildTypeParameterDisplay(tp, writer, enclosingDeclaration, flags, typeStack) {
                        appendSymbolNameOnly(tp.symbol, writer);
                        var constraint = getConstraintOfTypeParameter(tp);
                        if (constraint) {
                            writeSpace(writer);
                            writeKeyword(writer, 79 /* ExtendsKeyword */);
                            writeSpace(writer);
                            buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, typeStack);
                        }
                    }
                    function buildParameterDisplay(p, writer, enclosingDeclaration, flags, typeStack) {
                        if (ts.hasDotDotDotToken(p.valueDeclaration)) {
                            writePunctuation(writer, 21 /* DotDotDotToken */);
                        }
                        appendSymbolNameOnly(p, writer);
                        if (ts.hasQuestionToken(p.valueDeclaration) || p.valueDeclaration.initializer) {
                            writePunctuation(writer, 50 /* QuestionToken */);
                        }
                        writePunctuation(writer, 51 /* ColonToken */);
                        writeSpace(writer);
                        buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, typeStack);
                    }
                    function buildDisplayForTypeParametersAndDelimiters(typeParameters, writer, enclosingDeclaration, flags, typeStack) {
                        if (typeParameters && typeParameters.length) {
                            writePunctuation(writer, 24 /* LessThanToken */);
                            for (var i = 0; i < typeParameters.length; i++) {
                                if (i > 0) {
                                    writePunctuation(writer, 23 /* CommaToken */);
                                    writeSpace(writer);
                                }
                                buildTypeParameterDisplay(typeParameters[i], writer, enclosingDeclaration, flags, typeStack);
                            }
                            writePunctuation(writer, 25 /* GreaterThanToken */);
                        }
                    }
                    function buildDisplayForTypeArgumentsAndDelimiters(typeParameters, mapper, writer, enclosingDeclaration, flags, typeStack) {
                        if (typeParameters && typeParameters.length) {
                            writePunctuation(writer, 24 /* LessThanToken */);
                            for (var i = 0; i < typeParameters.length; i++) {
                                if (i > 0) {
                                    writePunctuation(writer, 23 /* CommaToken */);
                                    writeSpace(writer);
                                }
                                buildTypeDisplay(mapper(typeParameters[i]), writer, enclosingDeclaration, 0 /* None */);
                            }
                            writePunctuation(writer, 25 /* GreaterThanToken */);
                        }
                    }
                    function buildDisplayForParametersAndDelimiters(parameters, writer, enclosingDeclaration, flags, typeStack) {
                        writePunctuation(writer, 16 /* OpenParenToken */);
                        for (var i = 0; i < parameters.length; i++) {
                            if (i > 0) {
                                writePunctuation(writer, 23 /* CommaToken */);
                                writeSpace(writer);
                            }
                            buildParameterDisplay(parameters[i], writer, enclosingDeclaration, flags, typeStack);
                        }
                        writePunctuation(writer, 17 /* CloseParenToken */);
                    }
                    function buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, typeStack) {
                        if (flags & 8 /* WriteArrowStyleSignature */) {
                            writeSpace(writer);
                            writePunctuation(writer, 32 /* EqualsGreaterThanToken */);
                        }
                        else {
                            writePunctuation(writer, 51 /* ColonToken */);
                        }
                        writeSpace(writer);
                        buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags, typeStack);
                    }
                    function buildSignatureDisplay(signature, writer, enclosingDeclaration, flags, typeStack) {
                        if (signature.target && (flags & 32 /* WriteTypeArgumentsOfSignature */)) {
                            // Instantiated signature, write type arguments instead
                            // This is achieved by passing in the mapper separately
                            buildDisplayForTypeArgumentsAndDelimiters(signature.target.typeParameters, signature.mapper, writer, enclosingDeclaration);
                        }
                        else {
                            buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, typeStack);
                        }
                        buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, typeStack);
                        buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, typeStack);
                    }
                    return _displayBuilder || (_displayBuilder = {
                        symbolToString: symbolToString,
                        typeToString: typeToString,
                        buildSymbolDisplay: buildSymbolDisplay,
                        buildTypeDisplay: buildTypeDisplay,
                        buildTypeParameterDisplay: buildTypeParameterDisplay,
                        buildParameterDisplay: buildParameterDisplay,
                        buildDisplayForParametersAndDelimiters: buildDisplayForParametersAndDelimiters,
                        buildDisplayForTypeParametersAndDelimiters: buildDisplayForTypeParametersAndDelimiters,
                        buildDisplayForTypeArgumentsAndDelimiters: buildDisplayForTypeArgumentsAndDelimiters,
                        buildTypeParameterDisplayFromSymbol: buildTypeParameterDisplayFromSymbol,
                        buildSignatureDisplay: buildSignatureDisplay,
                        buildReturnTypeDisplay: buildReturnTypeDisplay
                    });
                }
                function isDeclarationVisible(node) {
                    function getContainingExternalModule(node) {
                        for (; node; node = node.parent) {
                            if (node.kind === 205 /* ModuleDeclaration */) {
                                if (node.name.kind === 8 /* StringLiteral */) {
                                    return node;
                                }
                            }
                            else if (node.kind === 227 /* SourceFile */) {
                                return ts.isExternalModule(node) ? node : undefined;
                            }
                        }
                        ts.Debug.fail("getContainingModule cant reach here");
                    }
                    function isUsedInExportAssignment(node) {
                        // Get source File and see if it is external module and has export assigned symbol
                        var externalModule = getContainingExternalModule(node);
                        var exportAssignmentSymbol;
                        var resolvedExportSymbol;
                        if (externalModule) {
                            // This is export assigned symbol node
                            var externalModuleSymbol = getSymbolOfNode(externalModule);
                            exportAssignmentSymbol = getExportAssignmentSymbol(externalModuleSymbol);
                            var symbolOfNode = getSymbolOfNode(node);
                            if (isSymbolUsedInExportAssignment(symbolOfNode)) {
                                return true;
                            }
                            // if symbolOfNode is alias declaration, resolve the symbol declaration and check
                            if (symbolOfNode.flags & 8388608 /* Alias */) {
                                return isSymbolUsedInExportAssignment(resolveAlias(symbolOfNode));
                            }
                        }
                        // Check if the symbol is used in export assignment
                        function isSymbolUsedInExportAssignment(symbol) {
                            if (exportAssignmentSymbol === symbol) {
                                return true;
                            }
                            if (exportAssignmentSymbol && !!(exportAssignmentSymbol.flags & 8388608 /* Alias */)) {
                                // if export assigned symbol is alias declaration, resolve the alias
                                resolvedExportSymbol = resolvedExportSymbol || resolveAlias(exportAssignmentSymbol);
                                if (resolvedExportSymbol === symbol) {
                                    return true;
                                }
                                // Container of resolvedExportSymbol is visible
                                return ts.forEach(resolvedExportSymbol.declarations, function (current) {
                                    while (current) {
                                        if (current === node) {
                                            return true;
                                        }
                                        current = current.parent;
                                    }
                                });
                            }
                        }
                    }
                    function determineIfDeclarationIsVisible() {
                        switch (node.kind) {
                            case 152 /* BindingElement */:
                                return isDeclarationVisible(node.parent.parent);
                            case 198 /* VariableDeclaration */:
                                if (ts.isBindingPattern(node.name) &&
                                    !node.name.elements.length) {
                                    // If the binding pattern is empty, this variable declaration is not visible
                                    return false;
                                }
                            // Otherwise fall through
                            case 205 /* ModuleDeclaration */:
                            case 201 /* ClassDeclaration */:
                            case 202 /* InterfaceDeclaration */:
                            case 203 /* TypeAliasDeclaration */:
                            case 200 /* FunctionDeclaration */:
                            case 204 /* EnumDeclaration */:
                            case 208 /* ImportEqualsDeclaration */:
                                var parent_2 = getDeclarationContainer(node);
                                // If the node is not exported or it is not ambient module element (except import declaration)
                                if (!(ts.getCombinedNodeFlags(node) & 1 /* Export */) &&
                                    !(node.kind !== 208 /* ImportEqualsDeclaration */ && parent_2.kind !== 227 /* SourceFile */ && ts.isInAmbientContext(parent_2))) {
                                    return isGlobalSourceFile(parent_2);
                                }
                                // Exported members/ambient module elements (exception import declaration) are visible if parent is visible
                                return isDeclarationVisible(parent_2);
                            case 132 /* PropertyDeclaration */:
                            case 131 /* PropertySignature */:
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                                if (node.flags & (32 /* Private */ | 64 /* Protected */)) {
                                    // Private/protected properties/methods are not visible
                                    return false;
                                }
                            // Public properties/methods are visible if its parents are visible, so let it fall into next case statement
                            case 135 /* Constructor */:
                            case 139 /* ConstructSignature */:
                            case 138 /* CallSignature */:
                            case 140 /* IndexSignature */:
                            case 129 /* Parameter */:
                            case 206 /* ModuleBlock */:
                            case 142 /* FunctionType */:
                            case 143 /* ConstructorType */:
                            case 145 /* TypeLiteral */:
                            case 141 /* TypeReference */:
                            case 146 /* ArrayType */:
                            case 147 /* TupleType */:
                            case 148 /* UnionType */:
                            case 149 /* ParenthesizedType */:
                                return isDeclarationVisible(node.parent);
                            // Default binding, import specifier and namespace import is visible 
                            // only on demand so by default it is not visible
                            case 210 /* ImportClause */:
                            case 211 /* NamespaceImport */:
                            case 213 /* ImportSpecifier */:
                                return false;
                            // Type parameters are always visible
                            case 128 /* TypeParameter */:
                            // Source file is always visible
                            case 227 /* SourceFile */:
                                return true;
                            // Export assignements do not create name bindings outside the module
                            case 214 /* ExportAssignment */:
                                return false;
                            default:
                                ts.Debug.fail("isDeclarationVisible unknown: SyntaxKind: " + node.kind);
                        }
                    }
                    if (node) {
                        var links = getNodeLinks(node);
                        if (links.isVisible === undefined) {
                            links.isVisible = !!determineIfDeclarationIsVisible();
                        }
                        return links.isVisible;
                    }
                }
                function collectLinkedAliases(node) {
                    var exportSymbol;
                    if (node.parent && node.parent.kind === 214 /* ExportAssignment */) {
                        exportSymbol = resolveName(node.parent, node.text, 107455 /* Value */ | 793056 /* Type */ | 1536 /* Namespace */, ts.Diagnostics.Cannot_find_name_0, node);
                    }
                    else if (node.parent.kind === 217 /* ExportSpecifier */) {
                        exportSymbol = getTargetOfExportSpecifier(node.parent);
                    }
                    var result = [];
                    if (exportSymbol) {
                        buildVisibleNodeList(exportSymbol.declarations);
                    }
                    return result;
                    function buildVisibleNodeList(declarations) {
                        ts.forEach(declarations, function (declaration) {
                            getNodeLinks(declaration).isVisible = true;
                            var resultNode = getAnyImportSyntax(declaration) || declaration;
                            if (!ts.contains(result, resultNode)) {
                                result.push(resultNode);
                            }
                            if (ts.isInternalModuleImportEqualsDeclaration(declaration)) {
                                // Add the referenced top container visible
                                var internalModuleReference = declaration.moduleReference;
                                var firstIdentifier = getFirstIdentifier(internalModuleReference);
                                var importSymbol = resolveName(declaration, firstIdentifier.text, 107455 /* Value */ | 793056 /* Type */ | 1536 /* Namespace */, ts.Diagnostics.Cannot_find_name_0, firstIdentifier);
                                buildVisibleNodeList(importSymbol.declarations);
                            }
                        });
                    }
                }
                function getRootDeclaration(node) {
                    while (node.kind === 152 /* BindingElement */) {
                        node = node.parent.parent;
                    }
                    return node;
                }
                function getDeclarationContainer(node) {
                    node = getRootDeclaration(node);
                    // Parent chain:
                    // VaribleDeclaration -> VariableDeclarationList -> VariableStatement -> 'Declaration Container'
                    return node.kind === 198 /* VariableDeclaration */ ? node.parent.parent.parent : node.parent;
                }
                function getTypeOfPrototypeProperty(prototype) {
                    // TypeScript 1.0 spec (April 2014): 8.4
                    // Every class automatically contains a static property member named 'prototype',
                    // the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter.
                    // It is an error to explicitly declare a static property member with the name 'prototype'.
                    var classType = getDeclaredTypeOfSymbol(prototype.parent);
                    return classType.typeParameters ? createTypeReference(classType, ts.map(classType.typeParameters, function (_) { return anyType; })) : classType;
                }
                // Return the type of the given property in the given type, or undefined if no such property exists
                function getTypeOfPropertyOfType(type, name) {
                    var prop = getPropertyOfType(type, name);
                    return prop ? getTypeOfSymbol(prop) : undefined;
                }
                // Return the inferred type for a binding element
                function getTypeForBindingElement(declaration) {
                    var pattern = declaration.parent;
                    var parentType = getTypeForVariableLikeDeclaration(pattern.parent);
                    // If parent has the unknown (error) type, then so does this binding element
                    if (parentType === unknownType) {
                        return unknownType;
                    }
                    // If no type was specified or inferred for parent, or if the specified or inferred type is any,
                    // infer from the initializer of the binding element if one is present. Otherwise, go with the
                    // undefined or any type of the parent.
                    if (!parentType || parentType === anyType) {
                        if (declaration.initializer) {
                            return checkExpressionCached(declaration.initializer);
                        }
                        return parentType;
                    }
                    var type;
                    if (pattern.kind === 150 /* ObjectBindingPattern */) {
                        // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form)
                        var name_5 = declaration.propertyName || declaration.name;
                        // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature,
                        // or otherwise the type of the string index signature.
                        type = getTypeOfPropertyOfType(parentType, name_5.text) ||
                            isNumericLiteralName(name_5.text) && getIndexTypeOfType(parentType, 1 /* Number */) ||
                            getIndexTypeOfType(parentType, 0 /* String */);
                        if (!type) {
                            error(name_5, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), ts.declarationNameToString(name_5));
                            return unknownType;
                        }
                    }
                    else {
                        // This elementType will be used if the specific property corresponding to this index is not
                        // present (aka the tuple element property). This call also checks that the parentType is in
                        // fact an iterable or array (depending on target language).
                        var elementType = checkIteratedTypeOrElementType(parentType, pattern, false);
                        if (!declaration.dotDotDotToken) {
                            if (elementType.flags & 1 /* Any */) {
                                return elementType;
                            }
                            // Use specific property type when parent is a tuple or numeric index type when parent is an array
                            var propName = "" + ts.indexOf(pattern.elements, declaration);
                            type = isTupleLikeType(parentType)
                                ? getTypeOfPropertyOfType(parentType, propName)
                                : elementType;
                            if (!type) {
                                if (isTupleType(parentType)) {
                                    error(declaration, ts.Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(parentType), parentType.elementTypes.length, pattern.elements.length);
                                }
                                else {
                                    error(declaration, ts.Diagnostics.Type_0_has_no_property_1, typeToString(parentType), propName);
                                }
                                return unknownType;
                            }
                        }
                        else {
                            // Rest element has an array type with the same element type as the parent type
                            type = createArrayType(elementType);
                        }
                    }
                    return type;
                }
                // Return the inferred type for a variable, parameter, or property declaration
                function getTypeForVariableLikeDeclaration(declaration) {
                    // A variable declared in a for..in statement is always of type any
                    if (declaration.parent.parent.kind === 187 /* ForInStatement */) {
                        return anyType;
                    }
                    if (declaration.parent.parent.kind === 188 /* ForOfStatement */) {
                        // checkRightHandSideOfForOf will return undefined if the for-of expression type was
                        // missing properties/signatures required to get its iteratedType (like
                        // [Symbol.iterator] or next). This may be because we accessed properties from anyType,
                        // or it may have led to an error inside getIteratedType.
                        return checkRightHandSideOfForOf(declaration.parent.parent.expression) || anyType;
                    }
                    if (ts.isBindingPattern(declaration.parent)) {
                        return getTypeForBindingElement(declaration);
                    }
                    // Use type from type annotation if one is present
                    if (declaration.type) {
                        return getTypeFromTypeNode(declaration.type);
                    }
                    if (declaration.kind === 129 /* Parameter */) {
                        var func = declaration.parent;
                        // For a parameter of a set accessor, use the type of the get accessor if one is present
                        if (func.kind === 137 /* SetAccessor */ && !ts.hasDynamicName(func)) {
                            var getter = ts.getDeclarationOfKind(declaration.parent.symbol, 136 /* GetAccessor */);
                            if (getter) {
                                return getReturnTypeOfSignature(getSignatureFromDeclaration(getter));
                            }
                        }
                        // Use contextual parameter type if one is available
                        var type = getContextuallyTypedParameterType(declaration);
                        if (type) {
                            return type;
                        }
                    }
                    // Use the type of the initializer expression if one is present
                    if (declaration.initializer) {
                        return checkExpressionCached(declaration.initializer);
                    }
                    // If it is a short-hand property assignment, use the type of the identifier
                    if (declaration.kind === 225 /* ShorthandPropertyAssignment */) {
                        return checkIdentifier(declaration.name);
                    }
                    // No type specified and nothing can be inferred
                    return undefined;
                }
                // Return the type implied by a binding pattern element. This is the type of the initializer of the element if
                // one is present. Otherwise, if the element is itself a binding pattern, it is the type implied by the binding
                // pattern. Otherwise, it is the type any.
                function getTypeFromBindingElement(element) {
                    if (element.initializer) {
                        return getWidenedType(checkExpressionCached(element.initializer));
                    }
                    if (ts.isBindingPattern(element.name)) {
                        return getTypeFromBindingPattern(element.name);
                    }
                    return anyType;
                }
                // Return the type implied by an object binding pattern
                function getTypeFromObjectBindingPattern(pattern) {
                    var members = {};
                    ts.forEach(pattern.elements, function (e) {
                        var flags = 4 /* Property */ | 67108864 /* Transient */ | (e.initializer ? 536870912 /* Optional */ : 0);
                        var name = e.propertyName || e.name;
                        var symbol = createSymbol(flags, name.text);
                        symbol.type = getTypeFromBindingElement(e);
                        members[symbol.name] = symbol;
                    });
                    return createAnonymousType(undefined, members, emptyArray, emptyArray, undefined, undefined);
                }
                // Return the type implied by an array binding pattern
                function getTypeFromArrayBindingPattern(pattern) {
                    var hasSpreadElement = false;
                    var elementTypes = [];
                    ts.forEach(pattern.elements, function (e) {
                        elementTypes.push(e.kind === 175 /* OmittedExpression */ || e.dotDotDotToken ? anyType : getTypeFromBindingElement(e));
                        if (e.dotDotDotToken) {
                            hasSpreadElement = true;
                        }
                    });
                    if (!elementTypes.length) {
                        return languageVersion >= 2 /* ES6 */ ? createIterableType(anyType) : anyArrayType;
                    }
                    else if (hasSpreadElement) {
                        var unionOfElements = getUnionType(elementTypes);
                        return languageVersion >= 2 /* ES6 */ ? createIterableType(unionOfElements) : createArrayType(unionOfElements);
                    }
                    // If the pattern has at least one element, and no rest element, then it should imply a tuple type.
                    return createTupleType(elementTypes);
                }
                // Return the type implied by a binding pattern. This is the type implied purely by the binding pattern itself
                // and without regard to its context (i.e. without regard any type annotation or initializer associated with the
                // declaration in which the binding pattern is contained). For example, the implied type of [x, y] is [any, any]
                // and the implied type of { x, y: z = 1 } is { x: any; y: number; }. The type implied by a binding pattern is
                // used as the contextual type of an initializer associated with the binding pattern. Also, for a destructuring
                // parameter with no type annotation or initializer, the type implied by the binding pattern becomes the type of
                // the parameter.
                function getTypeFromBindingPattern(pattern) {
                    return pattern.kind === 150 /* ObjectBindingPattern */
                        ? getTypeFromObjectBindingPattern(pattern)
                        : getTypeFromArrayBindingPattern(pattern);
                }
                // Return the type associated with a variable, parameter, or property declaration. In the simple case this is the type
                // specified in a type annotation or inferred from an initializer. However, in the case of a destructuring declaration it
                // is a bit more involved. For example:
                //
                //   var [x, s = ""] = [1, "one"];
                //
                // Here, the array literal [1, "one"] is contextually typed by the type [any, string], which is the implied type of the
                // binding pattern [x, s = ""]. Because the contextual type is a tuple type, the resulting type of [1, "one"] is the
                // tuple type [number, string]. Thus, the type inferred for 'x' is number and the type inferred for 's' is string.
                function getWidenedTypeForVariableLikeDeclaration(declaration, reportErrors) {
                    var type = getTypeForVariableLikeDeclaration(declaration);
                    if (type) {
                        if (reportErrors) {
                            reportErrorsFromWidening(declaration, type);
                        }
                        // During a normal type check we'll never get to here with a property assignment (the check of the containing
                        // object literal uses a different path). We exclude widening only so that language services and type verification
                        // tools see the actual type.
                        return declaration.kind !== 224 /* PropertyAssignment */ ? getWidenedType(type) : type;
                    }
                    // If no type was specified and nothing could be inferred, and if the declaration specifies a binding pattern, use
                    // the type implied by the binding pattern
                    if (ts.isBindingPattern(declaration.name)) {
                        return getTypeFromBindingPattern(declaration.name);
                    }
                    // Rest parameters default to type any[], other parameters default to type any
                    type = declaration.dotDotDotToken ? anyArrayType : anyType;
                    // Report implicit any errors unless this is a private property within an ambient declaration
                    if (reportErrors && compilerOptions.noImplicitAny) {
                        var root = getRootDeclaration(declaration);
                        if (!isPrivateWithinAmbient(root) && !(root.kind === 129 /* Parameter */ && isPrivateWithinAmbient(root.parent))) {
                            reportImplicitAnyError(declaration, type);
                        }
                    }
                    return type;
                }
                function getTypeOfVariableOrParameterOrProperty(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.type) {
                        // Handle prototype property
                        if (symbol.flags & 134217728 /* Prototype */) {
                            return links.type = getTypeOfPrototypeProperty(symbol);
                        }
                        // Handle catch clause variables
                        var declaration = symbol.valueDeclaration;
                        if (declaration.parent.kind === 223 /* CatchClause */) {
                            return links.type = anyType;
                        }
                        // Handle export default expressions
                        if (declaration.kind === 214 /* ExportAssignment */) {
                            return links.type = checkExpression(declaration.expression);
                        }
                        // Handle variable, parameter or property
                        links.type = resolvingType;
                        var type = getWidenedTypeForVariableLikeDeclaration(declaration, true);
                        if (links.type === resolvingType) {
                            links.type = type;
                        }
                    }
                    else if (links.type === resolvingType) {
                        links.type = anyType;
                        if (compilerOptions.noImplicitAny) {
                            var diagnostic = symbol.valueDeclaration.type ?
                                ts.Diagnostics._0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation :
                                ts.Diagnostics._0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer;
                            error(symbol.valueDeclaration, diagnostic, symbolToString(symbol));
                        }
                    }
                    return links.type;
                }
                function getSetAccessorTypeAnnotationNode(accessor) {
                    return accessor && accessor.parameters.length > 0 && accessor.parameters[0].type;
                }
                function getAnnotatedAccessorType(accessor) {
                    if (accessor) {
                        if (accessor.kind === 136 /* GetAccessor */) {
                            return accessor.type && getTypeFromTypeNode(accessor.type);
                        }
                        else {
                            var setterTypeAnnotation = getSetAccessorTypeAnnotationNode(accessor);
                            return setterTypeAnnotation && getTypeFromTypeNode(setterTypeAnnotation);
                        }
                    }
                    return undefined;
                }
                function getTypeOfAccessors(symbol) {
                    var links = getSymbolLinks(symbol);
                    checkAndStoreTypeOfAccessors(symbol, links);
                    return links.type;
                }
                function checkAndStoreTypeOfAccessors(symbol, links) {
                    links = links || getSymbolLinks(symbol);
                    if (!links.type) {
                        links.type = resolvingType;
                        var getter = ts.getDeclarationOfKind(symbol, 136 /* GetAccessor */);
                        var setter = ts.getDeclarationOfKind(symbol, 137 /* SetAccessor */);
                        var type;
                        // First try to see if the user specified a return type on the get-accessor.
                        var getterReturnType = getAnnotatedAccessorType(getter);
                        if (getterReturnType) {
                            type = getterReturnType;
                        }
                        else {
                            // If the user didn't specify a return type, try to use the set-accessor's parameter type.
                            var setterParameterType = getAnnotatedAccessorType(setter);
                            if (setterParameterType) {
                                type = setterParameterType;
                            }
                            else {
                                // If there are no specified types, try to infer it from the body of the get accessor if it exists.
                                if (getter && getter.body) {
                                    type = getReturnTypeFromBody(getter);
                                }
                                else {
                                    if (compilerOptions.noImplicitAny) {
                                        error(setter, ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbolToString(symbol));
                                    }
                                    type = anyType;
                                }
                            }
                        }
                        if (links.type === resolvingType) {
                            links.type = type;
                        }
                    }
                    else if (links.type === resolvingType) {
                        links.type = anyType;
                        if (compilerOptions.noImplicitAny) {
                            var getter = ts.getDeclarationOfKind(symbol, 136 /* GetAccessor */);
                            error(getter, ts.Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
                        }
                    }
                }
                function getTypeOfFuncClassEnumModule(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.type) {
                        links.type = createObjectType(32768 /* Anonymous */, symbol);
                    }
                    return links.type;
                }
                function getTypeOfEnumMember(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.type) {
                        links.type = getDeclaredTypeOfEnum(getParentOfSymbol(symbol));
                    }
                    return links.type;
                }
                function getTypeOfAlias(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.type) {
                        links.type = getTypeOfSymbol(resolveAlias(symbol));
                    }
                    return links.type;
                }
                function getTypeOfInstantiatedSymbol(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.type) {
                        links.type = instantiateType(getTypeOfSymbol(links.target), links.mapper);
                    }
                    return links.type;
                }
                function getTypeOfSymbol(symbol) {
                    if (symbol.flags & 16777216 /* Instantiated */) {
                        return getTypeOfInstantiatedSymbol(symbol);
                    }
                    if (symbol.flags & (3 /* Variable */ | 4 /* Property */)) {
                        return getTypeOfVariableOrParameterOrProperty(symbol);
                    }
                    if (symbol.flags & (16 /* Function */ | 8192 /* Method */ | 32 /* Class */ | 384 /* Enum */ | 512 /* ValueModule */)) {
                        return getTypeOfFuncClassEnumModule(symbol);
                    }
                    if (symbol.flags & 8 /* EnumMember */) {
                        return getTypeOfEnumMember(symbol);
                    }
                    if (symbol.flags & 98304 /* Accessor */) {
                        return getTypeOfAccessors(symbol);
                    }
                    if (symbol.flags & 8388608 /* Alias */) {
                        return getTypeOfAlias(symbol);
                    }
                    return unknownType;
                }
                function getTargetType(type) {
                    return type.flags & 4096 /* Reference */ ? type.target : type;
                }
                function hasBaseType(type, checkBase) {
                    return check(type);
                    function check(type) {
                        var target = getTargetType(type);
                        return target === checkBase || ts.forEach(getBaseTypes(target), check);
                    }
                }
                // Return combined list of type parameters from all declarations of a class or interface. Elsewhere we check they're all
                // the same, but even if they're not we still need the complete list to ensure instantiations supply type arguments
                // for all type parameters.
                function getTypeParametersOfClassOrInterface(symbol) {
                    var result;
                    ts.forEach(symbol.declarations, function (node) {
                        if (node.kind === 202 /* InterfaceDeclaration */ || node.kind === 201 /* ClassDeclaration */) {
                            var declaration = node;
                            if (declaration.typeParameters && declaration.typeParameters.length) {
                                ts.forEach(declaration.typeParameters, function (node) {
                                    var tp = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node));
                                    if (!result) {
                                        result = [tp];
                                    }
                                    else if (!ts.contains(result, tp)) {
                                        result.push(tp);
                                    }
                                });
                            }
                        }
                    });
                    return result;
                }
                function getBaseTypes(type) {
                    var typeWithBaseTypes = type;
                    if (!typeWithBaseTypes.baseTypes) {
                        if (type.symbol.flags & 32 /* Class */) {
                            resolveBaseTypesOfClass(typeWithBaseTypes);
                        }
                        else if (type.symbol.flags & 64 /* Interface */) {
                            resolveBaseTypesOfInterface(typeWithBaseTypes);
                        }
                        else {
                            ts.Debug.fail("type must be class or interface");
                        }
                    }
                    return typeWithBaseTypes.baseTypes;
                }
                function resolveBaseTypesOfClass(type) {
                    type.baseTypes = [];
                    var declaration = ts.getDeclarationOfKind(type.symbol, 201 /* ClassDeclaration */);
                    var baseTypeNode = ts.getClassExtendsHeritageClauseElement(declaration);
                    if (baseTypeNode) {
                        var baseType = getTypeFromHeritageClauseElement(baseTypeNode);
                        if (baseType !== unknownType) {
                            if (getTargetType(baseType).flags & 1024 /* Class */) {
                                if (type !== baseType && !hasBaseType(baseType, type)) {
                                    type.baseTypes.push(baseType);
                                }
                                else {
                                    error(declaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, undefined, 1 /* WriteArrayAsGenericType */));
                                }
                            }
                            else {
                                error(baseTypeNode, ts.Diagnostics.A_class_may_only_extend_another_class);
                            }
                        }
                    }
                }
                function resolveBaseTypesOfInterface(type) {
                    type.baseTypes = [];
                    for (var _i = 0, _a = type.symbol.declarations; _i < _a.length; _i++) {
                        var declaration = _a[_i];
                        if (declaration.kind === 202 /* InterfaceDeclaration */ && ts.getInterfaceBaseTypeNodes(declaration)) {
                            for (var _b = 0, _c = ts.getInterfaceBaseTypeNodes(declaration); _b < _c.length; _b++) {
                                var node = _c[_b];
                                var baseType = getTypeFromHeritageClauseElement(node);
                                if (baseType !== unknownType) {
                                    if (getTargetType(baseType).flags & (1024 /* Class */ | 2048 /* Interface */)) {
                                        if (type !== baseType && !hasBaseType(baseType, type)) {
                                            type.baseTypes.push(baseType);
                                        }
                                        else {
                                            error(declaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, undefined, 1 /* WriteArrayAsGenericType */));
                                        }
                                    }
                                    else {
                                        error(node, ts.Diagnostics.An_interface_may_only_extend_a_class_or_another_interface);
                                    }
                                }
                            }
                        }
                    }
                }
                function getDeclaredTypeOfClassOrInterface(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.declaredType) {
                        var kind = symbol.flags & 32 /* Class */ ? 1024 /* Class */ : 2048 /* Interface */;
                        var type = links.declaredType = createObjectType(kind, symbol);
                        var typeParameters = getTypeParametersOfClassOrInterface(symbol);
                        if (typeParameters) {
                            type.flags |= 4096 /* Reference */;
                            type.typeParameters = typeParameters;
                            type.instantiations = {};
                            type.instantiations[getTypeListId(type.typeParameters)] = type;
                            type.target = type;
                            type.typeArguments = type.typeParameters;
                        }
                    }
                    return links.declaredType;
                }
                function getDeclaredTypeOfTypeAlias(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.declaredType) {
                        links.declaredType = resolvingType;
                        var declaration = ts.getDeclarationOfKind(symbol, 203 /* TypeAliasDeclaration */);
                        var type = getTypeFromTypeNode(declaration.type);
                        if (links.declaredType === resolvingType) {
                            links.declaredType = type;
                        }
                    }
                    else if (links.declaredType === resolvingType) {
                        links.declaredType = unknownType;
                        var declaration = ts.getDeclarationOfKind(symbol, 203 /* TypeAliasDeclaration */);
                        error(declaration.name, ts.Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
                    }
                    return links.declaredType;
                }
                function getDeclaredTypeOfEnum(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.declaredType) {
                        var type = createType(128 /* Enum */);
                        type.symbol = symbol;
                        links.declaredType = type;
                    }
                    return links.declaredType;
                }
                function getDeclaredTypeOfTypeParameter(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.declaredType) {
                        var type = createType(512 /* TypeParameter */);
                        type.symbol = symbol;
                        if (!ts.getDeclarationOfKind(symbol, 128 /* TypeParameter */).constraint) {
                            type.constraint = noConstraintType;
                        }
                        links.declaredType = type;
                    }
                    return links.declaredType;
                }
                function getDeclaredTypeOfAlias(symbol) {
                    var links = getSymbolLinks(symbol);
                    if (!links.declaredType) {
                        links.declaredType = getDeclaredTypeOfSymbol(resolveAlias(symbol));
                    }
                    return links.declaredType;
                }
                function getDeclaredTypeOfSymbol(symbol) {
                    ts.Debug.assert((symbol.flags & 16777216 /* Instantiated */) === 0);
                    if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) {
                        return getDeclaredTypeOfClassOrInterface(symbol);
                    }
                    if (symbol.flags & 524288 /* TypeAlias */) {
                        return getDeclaredTypeOfTypeAlias(symbol);
                    }
                    if (symbol.flags & 384 /* Enum */) {
                        return getDeclaredTypeOfEnum(symbol);
                    }
                    if (symbol.flags & 262144 /* TypeParameter */) {
                        return getDeclaredTypeOfTypeParameter(symbol);
                    }
                    if (symbol.flags & 8388608 /* Alias */) {
                        return getDeclaredTypeOfAlias(symbol);
                    }
                    return unknownType;
                }
                function createSymbolTable(symbols) {
                    var result = {};
                    for (var _i = 0; _i < symbols.length; _i++) {
                        var symbol = symbols[_i];
                        result[symbol.name] = symbol;
                    }
                    return result;
                }
                function createInstantiatedSymbolTable(symbols, mapper) {
                    var result = {};
                    for (var _i = 0; _i < symbols.length; _i++) {
                        var symbol = symbols[_i];
                        result[symbol.name] = instantiateSymbol(symbol, mapper);
                    }
                    return result;
                }
                function addInheritedMembers(symbols, baseSymbols) {
                    for (var _i = 0; _i < baseSymbols.length; _i++) {
                        var s = baseSymbols[_i];
                        if (!ts.hasProperty(symbols, s.name)) {
                            symbols[s.name] = s;
                        }
                    }
                }
                function addInheritedSignatures(signatures, baseSignatures) {
                    if (baseSignatures) {
                        for (var _i = 0; _i < baseSignatures.length; _i++) {
                            var signature = baseSignatures[_i];
                            signatures.push(signature);
                        }
                    }
                }
                function resolveDeclaredMembers(type) {
                    if (!type.declaredProperties) {
                        var symbol = type.symbol;
                        type.declaredProperties = getNamedMembers(symbol.members);
                        type.declaredCallSignatures = getSignaturesOfSymbol(symbol.members["__call"]);
                        type.declaredConstructSignatures = getSignaturesOfSymbol(symbol.members["__new"]);
                        type.declaredStringIndexType = getIndexTypeOfSymbol(symbol, 0 /* String */);
                        type.declaredNumberIndexType = getIndexTypeOfSymbol(symbol, 1 /* Number */);
                    }
                    return type;
                }
                function resolveClassOrInterfaceMembers(type) {
                    var target = resolveDeclaredMembers(type);
                    var members = target.symbol.members;
                    var callSignatures = target.declaredCallSignatures;
                    var constructSignatures = target.declaredConstructSignatures;
                    var stringIndexType = target.declaredStringIndexType;
                    var numberIndexType = target.declaredNumberIndexType;
                    var baseTypes = getBaseTypes(target);
                    if (baseTypes.length) {
                        members = createSymbolTable(target.declaredProperties);
                        for (var _i = 0; _i < baseTypes.length; _i++) {
                            var baseType = baseTypes[_i];
                            addInheritedMembers(members, getPropertiesOfObjectType(baseType));
                            callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(baseType, 0 /* Call */));
                            constructSignatures = ts.concatenate(constructSignatures, getSignaturesOfType(baseType, 1 /* Construct */));
                            stringIndexType = stringIndexType || getIndexTypeOfType(baseType, 0 /* String */);
                            numberIndexType = numberIndexType || getIndexTypeOfType(baseType, 1 /* Number */);
                        }
                    }
                    setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
                }
                function resolveTypeReferenceMembers(type) {
                    var target = resolveDeclaredMembers(type.target);
                    var mapper = createTypeMapper(target.typeParameters, type.typeArguments);
                    var members = createInstantiatedSymbolTable(target.declaredProperties, mapper);
                    var callSignatures = instantiateList(target.declaredCallSignatures, mapper, instantiateSignature);
                    var constructSignatures = instantiateList(target.declaredConstructSignatures, mapper, instantiateSignature);
                    var stringIndexType = target.declaredStringIndexType ? instantiateType(target.declaredStringIndexType, mapper) : undefined;
                    var numberIndexType = target.declaredNumberIndexType ? instantiateType(target.declaredNumberIndexType, mapper) : undefined;
                    ts.forEach(getBaseTypes(target), function (baseType) {
                        var instantiatedBaseType = instantiateType(baseType, mapper);
                        addInheritedMembers(members, getPropertiesOfObjectType(instantiatedBaseType));
                        callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, 0 /* Call */));
                        constructSignatures = ts.concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, 1 /* Construct */));
                        stringIndexType = stringIndexType || getIndexTypeOfType(instantiatedBaseType, 0 /* String */);
                        numberIndexType = numberIndexType || getIndexTypeOfType(instantiatedBaseType, 1 /* Number */);
                    });
                    setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
                }
                function createSignature(declaration, typeParameters, parameters, resolvedReturnType, minArgumentCount, hasRestParameter, hasStringLiterals) {
                    var sig = new Signature(checker);
                    sig.declaration = declaration;
                    sig.typeParameters = typeParameters;
                    sig.parameters = parameters;
                    sig.resolvedReturnType = resolvedReturnType;
                    sig.minArgumentCount = minArgumentCount;
                    sig.hasRestParameter = hasRestParameter;
                    sig.hasStringLiterals = hasStringLiterals;
                    return sig;
                }
                function cloneSignature(sig) {
                    return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.resolvedReturnType, sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals);
                }
                function getDefaultConstructSignatures(classType) {
                    var baseTypes = getBaseTypes(classType);
                    if (baseTypes.length) {
                        var baseType = baseTypes[0];
                        var baseSignatures = getSignaturesOfType(getTypeOfSymbol(baseType.symbol), 1 /* Construct */);
                        return ts.map(baseSignatures, function (baseSignature) {
                            var signature = baseType.flags & 4096 /* Reference */ ?
                                getSignatureInstantiation(baseSignature, baseType.typeArguments) : cloneSignature(baseSignature);
                            signature.typeParameters = classType.typeParameters;
                            signature.resolvedReturnType = classType;
                            return signature;
                        });
                    }
                    return [createSignature(undefined, classType.typeParameters, emptyArray, classType, 0, false, false)];
                }
                function createTupleTypeMemberSymbols(memberTypes) {
                    var members = {};
                    for (var i = 0; i < memberTypes.length; i++) {
                        var symbol = createSymbol(4 /* Property */ | 67108864 /* Transient */, "" + i);
                        symbol.type = memberTypes[i];
                        members[i] = symbol;
                    }
                    return members;
                }
                function resolveTupleTypeMembers(type) {
                    var arrayType = resolveObjectOrUnionTypeMembers(createArrayType(getUnionType(type.elementTypes)));
                    var members = createTupleTypeMemberSymbols(type.elementTypes);
                    addInheritedMembers(members, arrayType.properties);
                    setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
                }
                function signatureListsIdentical(s, t) {
                    if (s.length !== t.length) {
                        return false;
                    }
                    for (var i = 0; i < s.length; i++) {
                        if (!compareSignatures(s[i], t[i], false, compareTypes)) {
                            return false;
                        }
                    }
                    return true;
                }
                // If the lists of call or construct signatures in the given types are all identical except for return types,
                // and if none of the signatures are generic, return a list of signatures that has substitutes a union of the
                // return types of the corresponding signatures in each resulting signature.
                function getUnionSignatures(types, kind) {
                    var signatureLists = ts.map(types, function (t) { return getSignaturesOfType(t, kind); });
                    var signatures = signatureLists[0];
                    for (var _i = 0; _i < signatures.length; _i++) {
                        var signature = signatures[_i];
                        if (signature.typeParameters) {
                            return emptyArray;
                        }
                    }
                    for (var i_1 = 1; i_1 < signatureLists.length; i_1++) {
                        if (!signatureListsIdentical(signatures, signatureLists[i_1])) {
                            return emptyArray;
                        }
                    }
                    var result = ts.map(signatures, cloneSignature);
                    for (var i = 0; i < result.length; i++) {
                        var s = result[i];
                        // Clear resolved return type we possibly got from cloneSignature
                        s.resolvedReturnType = undefined;
                        s.unionSignatures = ts.map(signatureLists, function (signatures) { return signatures[i]; });
                    }
                    return result;
                }
                function getUnionIndexType(types, kind) {
                    var indexTypes = [];
                    for (var _i = 0; _i < types.length; _i++) {
                        var type = types[_i];
                        var indexType = getIndexTypeOfType(type, kind);
                        if (!indexType) {
                            return undefined;
                        }
                        indexTypes.push(indexType);
                    }
                    return getUnionType(indexTypes);
                }
                function resolveUnionTypeMembers(type) {
                    // The members and properties collections are empty for union types. To get all properties of a union
                    // type use getPropertiesOfType (only the language service uses this).
                    var callSignatures = getUnionSignatures(type.types, 0 /* Call */);
                    var constructSignatures = getUnionSignatures(type.types, 1 /* Construct */);
                    var stringIndexType = getUnionIndexType(type.types, 0 /* String */);
                    var numberIndexType = getUnionIndexType(type.types, 1 /* Number */);
                    setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexType, numberIndexType);
                }
                function resolveAnonymousTypeMembers(type) {
                    var symbol = type.symbol;
                    var members;
                    var callSignatures;
                    var constructSignatures;
                    var stringIndexType;
                    var numberIndexType;
                    if (symbol.flags & 2048 /* TypeLiteral */) {
                        members = symbol.members;
                        callSignatures = getSignaturesOfSymbol(members["__call"]);
                        constructSignatures = getSignaturesOfSymbol(members["__new"]);
                        stringIndexType = getIndexTypeOfSymbol(symbol, 0 /* String */);
                        numberIndexType = getIndexTypeOfSymbol(symbol, 1 /* Number */);
                    }
                    else {
                        // Combinations of function, class, enum and module
                        members = emptySymbols;
                        callSignatures = emptyArray;
                        constructSignatures = emptyArray;
                        if (symbol.flags & 1952 /* HasExports */) {
                            members = getExportsOfSymbol(symbol);
                        }
                        if (symbol.flags & (16 /* Function */ | 8192 /* Method */)) {
                            callSignatures = getSignaturesOfSymbol(symbol);
                        }
                        if (symbol.flags & 32 /* Class */) {
                            var classType = getDeclaredTypeOfClassOrInterface(symbol);
                            constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]);
                            if (!constructSignatures.length) {
                                constructSignatures = getDefaultConstructSignatures(classType);
                            }
                            var baseTypes = getBaseTypes(classType);
                            if (baseTypes.length) {
                                members = createSymbolTable(getNamedMembers(members));
                                addInheritedMembers(members, getPropertiesOfObjectType(getTypeOfSymbol(baseTypes[0].symbol)));
                            }
                        }
                        stringIndexType = undefined;
                        numberIndexType = (symbol.flags & 384 /* Enum */) ? stringType : undefined;
                    }
                    setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
                }
                function resolveObjectOrUnionTypeMembers(type) {
                    if (!type.members) {
                        if (type.flags & (1024 /* Class */ | 2048 /* Interface */)) {
                            resolveClassOrInterfaceMembers(type);
                        }
                        else if (type.flags & 32768 /* Anonymous */) {
                            resolveAnonymousTypeMembers(type);
                        }
                        else if (type.flags & 8192 /* Tuple */) {
                            resolveTupleTypeMembers(type);
                        }
                        else if (type.flags & 16384 /* Union */) {
                            resolveUnionTypeMembers(type);
                        }
                        else {
                            resolveTypeReferenceMembers(type);
                        }
                    }
                    return type;
                }
                // Return properties of an object type or an empty array for other types
                function getPropertiesOfObjectType(type) {
                    if (type.flags & 48128 /* ObjectType */) {
                        return resolveObjectOrUnionTypeMembers(type).properties;
                    }
                    return emptyArray;
                }
                // If the given type is an object type and that type has a property by the given name, return
                // the symbol for that property. Otherwise return undefined.
                function getPropertyOfObjectType(type, name) {
                    if (type.flags & 48128 /* ObjectType */) {
                        var resolved = resolveObjectOrUnionTypeMembers(type);
                        if (ts.hasProperty(resolved.members, name)) {
                            var symbol = resolved.members[name];
                            if (symbolIsValue(symbol)) {
                                return symbol;
                            }
                        }
                    }
                }
                function getPropertiesOfUnionType(type) {
                    var result = [];
                    ts.forEach(getPropertiesOfType(type.types[0]), function (prop) {
                        var unionProp = getPropertyOfUnionType(type, prop.name);
                        if (unionProp) {
                            result.push(unionProp);
                        }
                    });
                    return result;
                }
                function getPropertiesOfType(type) {
                    type = getApparentType(type);
                    return type.flags & 16384 /* Union */ ? getPropertiesOfUnionType(type) : getPropertiesOfObjectType(type);
                }
                // For a type parameter, return the base constraint of the type parameter. For the string, number,
                // boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
                // type itself. Note that the apparent type of a union type is the union type itself.
                function getApparentType(type) {
                    if (type.flags & 16384 /* Union */) {
                        type = getReducedTypeOfUnionType(type);
                    }
                    if (type.flags & 512 /* TypeParameter */) {
                        do {
                            type = getConstraintOfTypeParameter(type);
                        } while (type && type.flags & 512 /* TypeParameter */);
                        if (!type) {
                            type = emptyObjectType;
                        }
                    }
                    if (type.flags & 258 /* StringLike */) {
                        type = globalStringType;
                    }
                    else if (type.flags & 132 /* NumberLike */) {
                        type = globalNumberType;
                    }
                    else if (type.flags & 8 /* Boolean */) {
                        type = globalBooleanType;
                    }
                    else if (type.flags & 1048576 /* ESSymbol */) {
                        type = globalESSymbolType;
                    }
                    return type;
                }
                function createUnionProperty(unionType, name) {
                    var types = unionType.types;
                    var props;
                    for (var _i = 0; _i < types.length; _i++) {
                        var current = types[_i];
                        var type = getApparentType(current);
                        if (type !== unknownType) {
                            var prop = getPropertyOfType(type, name);
                            if (!prop || getDeclarationFlagsFromSymbol(prop) & (32 /* Private */ | 64 /* Protected */)) {
                                return undefined;
                            }
                            if (!props) {
                                props = [prop];
                            }
                            else {
                                props.push(prop);
                            }
                        }
                    }
                    var propTypes = [];
                    var declarations = [];
                    for (var _a = 0; _a < props.length; _a++) {
                        var prop = props[_a];
                        if (prop.declarations) {
                            declarations.push.apply(declarations, prop.declarations);
                        }
                        propTypes.push(getTypeOfSymbol(prop));
                    }
                    var result = createSymbol(4 /* Property */ | 67108864 /* Transient */ | 268435456 /* UnionProperty */, name);
                    result.unionType = unionType;
                    result.declarations = declarations;
                    result.type = getUnionType(propTypes);
                    return result;
                }
                function getPropertyOfUnionType(type, name) {
                    var properties = type.resolvedProperties || (type.resolvedProperties = {});
                    if (ts.hasProperty(properties, name)) {
                        return properties[name];
                    }
                    var property = createUnionProperty(type, name);
                    if (property) {
                        properties[name] = property;
                    }
                    return property;
                }
                // Return the symbol for the property with the given name in the given type. Creates synthetic union properties when
                // necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from
                // Object and Function as appropriate.
                function getPropertyOfType(type, name) {
                    type = getApparentType(type);
                    if (type.flags & 48128 /* ObjectType */) {
                        var resolved = resolveObjectOrUnionTypeMembers(type);
                        if (ts.hasProperty(resolved.members, name)) {
                            var symbol = resolved.members[name];
                            if (symbolIsValue(symbol)) {
                                return symbol;
                            }
                        }
                        if (resolved === anyFunctionType || resolved.callSignatures.length || resolved.constructSignatures.length) {
                            var symbol = getPropertyOfObjectType(globalFunctionType, name);
                            if (symbol) {
                                return symbol;
                            }
                        }
                        return getPropertyOfObjectType(globalObjectType, name);
                    }
                    if (type.flags & 16384 /* Union */) {
                        return getPropertyOfUnionType(type, name);
                    }
                    return undefined;
                }
                function getSignaturesOfObjectOrUnionType(type, kind) {
                    if (type.flags & (48128 /* ObjectType */ | 16384 /* Union */)) {
                        var resolved = resolveObjectOrUnionTypeMembers(type);
                        return kind === 0 /* Call */ ? resolved.callSignatures : resolved.constructSignatures;
                    }
                    return emptyArray;
                }
                // Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and
                // maps primitive types and type parameters are to their apparent types.
                function getSignaturesOfType(type, kind) {
                    return getSignaturesOfObjectOrUnionType(getApparentType(type), kind);
                }
                function typeHasCallOrConstructSignatures(type) {
                    var apparentType = getApparentType(type);
                    if (apparentType.flags & (48128 /* ObjectType */ | 16384 /* Union */)) {
                        var resolved = resolveObjectOrUnionTypeMembers(type);
                        return resolved.callSignatures.length > 0
                            || resolved.constructSignatures.length > 0;
                    }
                    return false;
                }
                function getIndexTypeOfObjectOrUnionType(type, kind) {
                    if (type.flags & (48128 /* ObjectType */ | 16384 /* Union */)) {
                        var resolved = resolveObjectOrUnionTypeMembers(type);
                        return kind === 0 /* String */ ? resolved.stringIndexType : resolved.numberIndexType;
                    }
                }
                // Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and
                // maps primitive types and type parameters are to their apparent types.
                function getIndexTypeOfType(type, kind) {
                    return getIndexTypeOfObjectOrUnionType(getApparentType(type), kind);
                }
                // Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual
                // type checking functions).
                function getTypeParametersFromDeclaration(typeParameterDeclarations) {
                    var result = [];
                    ts.forEach(typeParameterDeclarations, function (node) {
                        var tp = getDeclaredTypeOfTypeParameter(node.symbol);
                        if (!ts.contains(result, tp)) {
                            result.push(tp);
                        }
                    });
                    return result;
                }
                function symbolsToArray(symbols) {
                    var result = [];
                    for (var id in symbols) {
                        if (!isReservedMemberName(id)) {
                            result.push(symbols[id]);
                        }
                    }
                    return result;
                }
                function getSignatureFromDeclaration(declaration) {
                    var links = getNodeLinks(declaration);
                    if (!links.resolvedSignature) {
                        var classType = declaration.kind === 135 /* Constructor */ ? getDeclaredTypeOfClassOrInterface(declaration.parent.symbol) : undefined;
                        var typeParameters = classType ? classType.typeParameters :
                            declaration.typeParameters ? getTypeParametersFromDeclaration(declaration.typeParameters) : undefined;
                        var parameters = [];
                        var hasStringLiterals = false;
                        var minArgumentCount = -1;
                        for (var i = 0, n = declaration.parameters.length; i < n; i++) {
                            var param = declaration.parameters[i];
                            parameters.push(param.symbol);
                            if (param.type && param.type.kind === 8 /* StringLiteral */) {
                                hasStringLiterals = true;
                            }
                            if (minArgumentCount < 0) {
                                if (param.initializer || param.questionToken || param.dotDotDotToken) {
                                    minArgumentCount = i;
                                }
                            }
                        }
                        if (minArgumentCount < 0) {
                            minArgumentCount = declaration.parameters.length;
                        }
                        var returnType;
                        if (classType) {
                            returnType = classType;
                        }
                        else if (declaration.type) {
                            returnType = getTypeFromTypeNode(declaration.type);
                        }
                        else {
                            // TypeScript 1.0 spec (April 2014):
                            // If only one accessor includes a type annotation, the other behaves as if it had the same type annotation.
                            if (declaration.kind === 136 /* GetAccessor */ && !ts.hasDynamicName(declaration)) {
                                var setter = ts.getDeclarationOfKind(declaration.symbol, 137 /* SetAccessor */);
                                returnType = getAnnotatedAccessorType(setter);
                            }
                            if (!returnType && ts.nodeIsMissing(declaration.body)) {
                                returnType = anyType;
                            }
                        }
                        links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType, minArgumentCount, ts.hasRestParameters(declaration), hasStringLiterals);
                    }
                    return links.resolvedSignature;
                }
                function getSignaturesOfSymbol(symbol) {
                    if (!symbol)
                        return emptyArray;
                    var result = [];
                    for (var i = 0, len = symbol.declarations.length; i < len; i++) {
                        var node = symbol.declarations[i];
                        switch (node.kind) {
                            case 142 /* FunctionType */:
                            case 143 /* ConstructorType */:
                            case 200 /* FunctionDeclaration */:
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                            case 135 /* Constructor */:
                            case 138 /* CallSignature */:
                            case 139 /* ConstructSignature */:
                            case 140 /* IndexSignature */:
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                            case 162 /* FunctionExpression */:
                            case 163 /* ArrowFunction */:
                                // Don't include signature if node is the implementation of an overloaded function. A node is considered
                                // an implementation node if it has a body and the previous node is of the same kind and immediately
                                // precedes the implementation node (i.e. has the same parent and ends where the implementation starts).
                                if (i > 0 && node.body) {
                                    var previous = symbol.declarations[i - 1];
                                    if (node.parent === previous.parent && node.kind === previous.kind && node.pos === previous.end) {
                                        break;
                                    }
                                }
                                result.push(getSignatureFromDeclaration(node));
                        }
                    }
                    return result;
                }
                function getReturnTypeOfSignature(signature) {
                    if (!signature.resolvedReturnType) {
                        signature.resolvedReturnType = resolvingType;
                        var type;
                        if (signature.target) {
                            type = instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper);
                        }
                        else if (signature.unionSignatures) {
                            type = getUnionType(ts.map(signature.unionSignatures, getReturnTypeOfSignature));
                        }
                        else {
                            type = getReturnTypeFromBody(signature.declaration);
                        }
                        if (signature.resolvedReturnType === resolvingType) {
                            signature.resolvedReturnType = type;
                        }
                    }
                    else if (signature.resolvedReturnType === resolvingType) {
                        signature.resolvedReturnType = anyType;
                        if (compilerOptions.noImplicitAny) {
                            var declaration = signature.declaration;
                            if (declaration.name) {
                                error(declaration.name, ts.Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, ts.declarationNameToString(declaration.name));
                            }
                            else {
                                error(declaration, ts.Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions);
                            }
                        }
                    }
                    return signature.resolvedReturnType;
                }
                function getRestTypeOfSignature(signature) {
                    if (signature.hasRestParameter) {
                        var type = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
                        if (type.flags & 4096 /* Reference */ && type.target === globalArrayType) {
                            return type.typeArguments[0];
                        }
                    }
                    return anyType;
                }
                function getSignatureInstantiation(signature, typeArguments) {
                    return instantiateSignature(signature, createTypeMapper(signature.typeParameters, typeArguments), true);
                }
                function getErasedSignature(signature) {
                    if (!signature.typeParameters)
                        return signature;
                    if (!signature.erasedSignatureCache) {
                        if (signature.target) {
                            signature.erasedSignatureCache = instantiateSignature(getErasedSignature(signature.target), signature.mapper);
                        }
                        else {
                            signature.erasedSignatureCache = instantiateSignature(signature, createTypeEraser(signature.typeParameters), true);
                        }
                    }
                    return signature.erasedSignatureCache;
                }
                function getOrCreateTypeFromSignature(signature) {
                    // There are two ways to declare a construct signature, one is by declaring a class constructor
                    // using the constructor keyword, and the other is declaring a bare construct signature in an
                    // object type literal or interface (using the new keyword). Each way of declaring a constructor
                    // will result in a different declaration kind.
                    if (!signature.isolatedSignatureType) {
                        var isConstructor = signature.declaration.kind === 135 /* Constructor */ || signature.declaration.kind === 139 /* ConstructSignature */;
                        var type = createObjectType(32768 /* Anonymous */ | 65536 /* FromSignature */);
                        type.members = emptySymbols;
                        type.properties = emptyArray;
                        type.callSignatures = !isConstructor ? [signature] : emptyArray;
                        type.constructSignatures = isConstructor ? [signature] : emptyArray;
                        signature.isolatedSignatureType = type;
                    }
                    return signature.isolatedSignatureType;
                }
                function getIndexSymbol(symbol) {
                    return symbol.members["__index"];
                }
                function getIndexDeclarationOfSymbol(symbol, kind) {
                    var syntaxKind = kind === 1 /* Number */ ? 119 /* NumberKeyword */ : 121 /* StringKeyword */;
                    var indexSymbol = getIndexSymbol(symbol);
                    if (indexSymbol) {
                        var len = indexSymbol.declarations.length;
                        for (var _i = 0, _a = indexSymbol.declarations; _i < _a.length; _i++) {
                            var decl = _a[_i];
                            var node = decl;
                            if (node.parameters.length === 1) {
                                var parameter = node.parameters[0];
                                if (parameter && parameter.type && parameter.type.kind === syntaxKind) {
                                    return node;
                                }
                            }
                        }
                    }
                    return undefined;
                }
                function getIndexTypeOfSymbol(symbol, kind) {
                    var declaration = getIndexDeclarationOfSymbol(symbol, kind);
                    return declaration
                        ? declaration.type ? getTypeFromTypeNode(declaration.type) : anyType
                        : undefined;
                }
                function getConstraintOfTypeParameter(type) {
                    if (!type.constraint) {
                        if (type.target) {
                            var targetConstraint = getConstraintOfTypeParameter(type.target);
                            type.constraint = targetConstraint ? instantiateType(targetConstraint, type.mapper) : noConstraintType;
                        }
                        else {
                            type.constraint = getTypeFromTypeNode(ts.getDeclarationOfKind(type.symbol, 128 /* TypeParameter */).constraint);
                        }
                    }
                    return type.constraint === noConstraintType ? undefined : type.constraint;
                }
                function getTypeListId(types) {
                    switch (types.length) {
                        case 1:
                            return "" + types[0].id;
                        case 2:
                            return types[0].id + "," + types[1].id;
                        default:
                            var result = "";
                            for (var i = 0; i < types.length; i++) {
                                if (i > 0) {
                                    result += ",";
                                }
                                result += types[i].id;
                            }
                            return result;
                    }
                }
                // This function is used to propagate widening flags when creating new object types references and union types.
                // It is only necessary to do so if a constituent type might be the undefined type, the null type, or the type
                // of an object literal (since those types have widening related information we need to track).
                function getWideningFlagsOfTypes(types) {
                    var result = 0;
                    for (var _i = 0; _i < types.length; _i++) {
                        var type = types[_i];
                        result |= type.flags;
                    }
                    return result & 786432 /* RequiresWidening */;
                }
                function createTypeReference(target, typeArguments) {
                    var id = getTypeListId(typeArguments);
                    var type = target.instantiations[id];
                    if (!type) {
                        var flags = 4096 /* Reference */ | getWideningFlagsOfTypes(typeArguments);
                        type = target.instantiations[id] = createObjectType(flags, target.symbol);
                        type.target = target;
                        type.typeArguments = typeArguments;
                    }
                    return type;
                }
                function isTypeParameterReferenceIllegalInConstraint(typeReferenceNode, typeParameterSymbol) {
                    var links = getNodeLinks(typeReferenceNode);
                    if (links.isIllegalTypeReferenceInConstraint !== undefined) {
                        return links.isIllegalTypeReferenceInConstraint;
                    }
                    // bubble up to the declaration
                    var currentNode = typeReferenceNode;
                    // forEach === exists
                    while (!ts.forEach(typeParameterSymbol.declarations, function (d) { return d.parent === currentNode.parent; })) {
                        currentNode = currentNode.parent;
                    }
                    // if last step was made from the type parameter this means that path has started somewhere in constraint which is illegal
                    links.isIllegalTypeReferenceInConstraint = currentNode.kind === 128 /* TypeParameter */;
                    return links.isIllegalTypeReferenceInConstraint;
                }
                function checkTypeParameterHasIllegalReferencesInConstraint(typeParameter) {
                    var typeParameterSymbol;
                    function check(n) {
                        if (n.kind === 141 /* TypeReference */ && n.typeName.kind === 65 /* Identifier */) {
                            var links = getNodeLinks(n);
                            if (links.isIllegalTypeReferenceInConstraint === undefined) {
                                var symbol = resolveName(typeParameter, n.typeName.text, 793056 /* Type */, undefined, undefined);
                                if (symbol && (symbol.flags & 262144 /* TypeParameter */)) {
                                    // TypeScript 1.0 spec (April 2014): 3.4.1
                                    // Type parameters declared in a particular type parameter list
                                    // may not be referenced in constraints in that type parameter list
                                    // symbol.declaration.parent === typeParameter.parent
                                    // -> typeParameter and symbol.declaration originate from the same type parameter list
                                    // -> illegal for all declarations in symbol
                                    // forEach === exists
                                    links.isIllegalTypeReferenceInConstraint = ts.forEach(symbol.declarations, function (d) { return d.parent == typeParameter.parent; });
                                }
                            }
                            if (links.isIllegalTypeReferenceInConstraint) {
                                error(typeParameter, ts.Diagnostics.Constraint_of_a_type_parameter_cannot_reference_any_type_parameter_from_the_same_type_parameter_list);
                            }
                        }
                        ts.forEachChild(n, check);
                    }
                    if (typeParameter.constraint) {
                        typeParameterSymbol = getSymbolOfNode(typeParameter);
                        check(typeParameter.constraint);
                    }
                }
                function getTypeFromTypeReference(node) {
                    return getTypeFromTypeReferenceOrHeritageClauseElement(node);
                }
                function getTypeFromHeritageClauseElement(node) {
                    return getTypeFromTypeReferenceOrHeritageClauseElement(node);
                }
                function getTypeFromTypeReferenceOrHeritageClauseElement(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        var type;
                        // We don't currently support heritage clauses with complex expressions in them.
                        // For these cases, we just set the type to be the unknownType.
                        if (node.kind !== 177 /* HeritageClauseElement */ || ts.isSupportedHeritageClauseElement(node)) {
                            var typeNameOrExpression = node.kind === 141 /* TypeReference */
                                ? node.typeName
                                : node.expression;
                            var symbol = resolveEntityName(typeNameOrExpression, 793056 /* Type */);
                            if (symbol) {
                                if ((symbol.flags & 262144 /* TypeParameter */) && isTypeParameterReferenceIllegalInConstraint(node, symbol)) {
                                    // TypeScript 1.0 spec (April 2014): 3.4.1
                                    // Type parameters declared in a particular type parameter list
                                    // may not be referenced in constraints in that type parameter list
                                    // Implementation: such type references are resolved to 'unknown' type that usually denotes error
                                    type = unknownType;
                                }
                                else {
                                    type = getDeclaredTypeOfSymbol(symbol);
                                    if (type.flags & (1024 /* Class */ | 2048 /* Interface */) && type.flags & 4096 /* Reference */) {
                                        var typeParameters = type.typeParameters;
                                        if (node.typeArguments && node.typeArguments.length === typeParameters.length) {
                                            type = createTypeReference(type, ts.map(node.typeArguments, getTypeFromTypeNode));
                                        }
                                        else {
                                            error(node, ts.Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, undefined, 1 /* WriteArrayAsGenericType */), typeParameters.length);
                                            type = undefined;
                                        }
                                    }
                                    else {
                                        if (node.typeArguments) {
                                            error(node, ts.Diagnostics.Type_0_is_not_generic, typeToString(type));
                                            type = undefined;
                                        }
                                    }
                                }
                            }
                        }
                        links.resolvedType = type || unknownType;
                    }
                    return links.resolvedType;
                }
                function getTypeFromTypeQueryNode(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        // TypeScript 1.0 spec (April 2014): 3.6.3
                        // The expression is processed as an identifier expression (section 4.3)
                        // or property access expression(section 4.10),
                        // the widened type(section 3.9) of which becomes the result.
                        links.resolvedType = getWidenedType(checkExpressionOrQualifiedName(node.exprName));
                    }
                    return links.resolvedType;
                }
                function getTypeOfGlobalSymbol(symbol, arity) {
                    function getTypeDeclaration(symbol) {
                        var declarations = symbol.declarations;
                        for (var _i = 0; _i < declarations.length; _i++) {
                            var declaration = declarations[_i];
                            switch (declaration.kind) {
                                case 201 /* ClassDeclaration */:
                                case 202 /* InterfaceDeclaration */:
                                case 204 /* EnumDeclaration */:
                                    return declaration;
                            }
                        }
                    }
                    if (!symbol) {
                        return emptyObjectType;
                    }
                    var type = getDeclaredTypeOfSymbol(symbol);
                    if (!(type.flags & 48128 /* ObjectType */)) {
                        error(getTypeDeclaration(symbol), ts.Diagnostics.Global_type_0_must_be_a_class_or_interface_type, symbol.name);
                        return emptyObjectType;
                    }
                    if ((type.typeParameters ? type.typeParameters.length : 0) !== arity) {
                        error(getTypeDeclaration(symbol), ts.Diagnostics.Global_type_0_must_have_1_type_parameter_s, symbol.name, arity);
                        return emptyObjectType;
                    }
                    return type;
                }
                function getGlobalValueSymbol(name) {
                    return getGlobalSymbol(name, 107455 /* Value */, ts.Diagnostics.Cannot_find_global_value_0);
                }
                function getGlobalTypeSymbol(name) {
                    return getGlobalSymbol(name, 793056 /* Type */, ts.Diagnostics.Cannot_find_global_type_0);
                }
                function getGlobalSymbol(name, meaning, diagnostic) {
                    return resolveName(undefined, name, meaning, diagnostic, name);
                }
                function getGlobalType(name, arity) {
                    if (arity === void 0) { arity = 0; }
                    return getTypeOfGlobalSymbol(getGlobalTypeSymbol(name), arity);
                }
                function getGlobalESSymbolConstructorSymbol() {
                    return globalESSymbolConstructorSymbol || (globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol"));
                }
                function createIterableType(elementType) {
                    return globalIterableType !== emptyObjectType ? createTypeReference(globalIterableType, [elementType]) : emptyObjectType;
                }
                function createArrayType(elementType) {
                    // globalArrayType will be undefined if we get here during creation of the Array type. This for example happens if
                    // user code augments the Array type with call or construct signatures that have an array type as the return type.
                    // We instead use globalArraySymbol to obtain the (not yet fully constructed) Array type.
                    var arrayType = globalArrayType || getDeclaredTypeOfSymbol(globalArraySymbol);
                    return arrayType !== emptyObjectType ? createTypeReference(arrayType, [elementType]) : emptyObjectType;
                }
                function getTypeFromArrayTypeNode(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        links.resolvedType = createArrayType(getTypeFromTypeNode(node.elementType));
                    }
                    return links.resolvedType;
                }
                function createTupleType(elementTypes) {
                    var id = getTypeListId(elementTypes);
                    var type = tupleTypes[id];
                    if (!type) {
                        type = tupleTypes[id] = createObjectType(8192 /* Tuple */);
                        type.elementTypes = elementTypes;
                    }
                    return type;
                }
                function getTypeFromTupleTypeNode(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        links.resolvedType = createTupleType(ts.map(node.elementTypes, getTypeFromTypeNode));
                    }
                    return links.resolvedType;
                }
                function addTypeToSortedSet(sortedSet, type) {
                    if (type.flags & 16384 /* Union */) {
                        addTypesToSortedSet(sortedSet, type.types);
                    }
                    else {
                        var i = 0;
                        var id = type.id;
                        while (i < sortedSet.length && sortedSet[i].id < id) {
                            i++;
                        }
                        if (i === sortedSet.length || sortedSet[i].id !== id) {
                            sortedSet.splice(i, 0, type);
                        }
                    }
                }
                function addTypesToSortedSet(sortedTypes, types) {
                    for (var _i = 0; _i < types.length; _i++) {
                        var type = types[_i];
                        addTypeToSortedSet(sortedTypes, type);
                    }
                }
                function isSubtypeOfAny(candidate, types) {
                    for (var _i = 0; _i < types.length; _i++) {
                        var type = types[_i];
                        if (candidate !== type && isTypeSubtypeOf(candidate, type)) {
                            return true;
                        }
                    }
                    return false;
                }
                function removeSubtypes(types) {
                    var i = types.length;
                    while (i > 0) {
                        i--;
                        if (isSubtypeOfAny(types[i], types)) {
                            types.splice(i, 1);
                        }
                    }
                }
                function containsAnyType(types) {
                    for (var _i = 0; _i < types.length; _i++) {
                        var type = types[_i];
                        if (type.flags & 1 /* Any */) {
                            return true;
                        }
                    }
                    return false;
                }
                function removeAllButLast(types, typeToRemove) {
                    var i = types.length;
                    while (i > 0 && types.length > 1) {
                        i--;
                        if (types[i] === typeToRemove) {
                            types.splice(i, 1);
                        }
                    }
                }
                // The noSubtypeReduction flag is there because it isn't possible to always do subtype reduction. The flag
                // is true when creating a union type from a type node and when instantiating a union type. In both of those
                // cases subtype reduction has to be deferred to properly support recursive union types. For example, a
                // type alias of the form "type Item = string | (() => Item)" cannot be reduced during its declaration.
                function getUnionType(types, noSubtypeReduction) {
                    if (types.length === 0) {
                        return emptyObjectType;
                    }
                    var sortedTypes = [];
                    addTypesToSortedSet(sortedTypes, types);
                    if (noSubtypeReduction) {
                        if (containsAnyType(sortedTypes)) {
                            return anyType;
                        }
                        removeAllButLast(sortedTypes, undefinedType);
                        removeAllButLast(sortedTypes, nullType);
                    }
                    else {
                        removeSubtypes(sortedTypes);
                    }
                    if (sortedTypes.length === 1) {
                        return sortedTypes[0];
                    }
                    var id = getTypeListId(sortedTypes);
                    var type = unionTypes[id];
                    if (!type) {
                        type = unionTypes[id] = createObjectType(16384 /* Union */ | getWideningFlagsOfTypes(sortedTypes));
                        type.types = sortedTypes;
                        type.reducedType = noSubtypeReduction ? undefined : type;
                    }
                    return type;
                }
                function getReducedTypeOfUnionType(type) {
                    // If union type was created without subtype reduction, perform the deferred reduction now
                    if (!type.reducedType) {
                        type.reducedType = getUnionType(type.types, false);
                    }
                    return type.reducedType;
                }
                function getTypeFromUnionTypeNode(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        links.resolvedType = getUnionType(ts.map(node.types, getTypeFromTypeNode), true);
                    }
                    return links.resolvedType;
                }
                function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        // Deferred resolution of members is handled by resolveObjectTypeMembers
                        links.resolvedType = createObjectType(32768 /* Anonymous */, node.symbol);
                    }
                    return links.resolvedType;
                }
                function getStringLiteralType(node) {
                    if (ts.hasProperty(stringLiteralTypes, node.text)) {
                        return stringLiteralTypes[node.text];
                    }
                    var type = stringLiteralTypes[node.text] = createType(256 /* StringLiteral */);
                    type.text = ts.getTextOfNode(node);
                    return type;
                }
                function getTypeFromStringLiteral(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        links.resolvedType = getStringLiteralType(node);
                    }
                    return links.resolvedType;
                }
                function getTypeFromTypeNode(node) {
                    switch (node.kind) {
                        case 112 /* AnyKeyword */:
                            return anyType;
                        case 121 /* StringKeyword */:
                            return stringType;
                        case 119 /* NumberKeyword */:
                            return numberType;
                        case 113 /* BooleanKeyword */:
                            return booleanType;
                        case 122 /* SymbolKeyword */:
                            return esSymbolType;
                        case 99 /* VoidKeyword */:
                            return voidType;
                        case 8 /* StringLiteral */:
                            return getTypeFromStringLiteral(node);
                        case 141 /* TypeReference */:
                            return getTypeFromTypeReference(node);
                        case 177 /* HeritageClauseElement */:
                            return getTypeFromHeritageClauseElement(node);
                        case 144 /* TypeQuery */:
                            return getTypeFromTypeQueryNode(node);
                        case 146 /* ArrayType */:
                            return getTypeFromArrayTypeNode(node);
                        case 147 /* TupleType */:
                            return getTypeFromTupleTypeNode(node);
                        case 148 /* UnionType */:
                            return getTypeFromUnionTypeNode(node);
                        case 149 /* ParenthesizedType */:
                            return getTypeFromTypeNode(node.type);
                        case 142 /* FunctionType */:
                        case 143 /* ConstructorType */:
                        case 145 /* TypeLiteral */:
                            return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
                        // This function assumes that an identifier or qualified name is a type expression
                        // Callers should first ensure this by calling isTypeNode
                        case 65 /* Identifier */:
                        case 126 /* QualifiedName */:
                            var symbol = getSymbolInfo(node);
                            return symbol && getDeclaredTypeOfSymbol(symbol);
                        default:
                            return unknownType;
                    }
                }
                function instantiateList(items, mapper, instantiator) {
                    if (items && items.length) {
                        var result = [];
                        for (var _i = 0; _i < items.length; _i++) {
                            var v = items[_i];
                            result.push(instantiator(v, mapper));
                        }
                        return result;
                    }
                    return items;
                }
                function createUnaryTypeMapper(source, target) {
                    return function (t) { return t === source ? target : t; };
                }
                function createBinaryTypeMapper(source1, target1, source2, target2) {
                    return function (t) { return t === source1 ? target1 : t === source2 ? target2 : t; };
                }
                function createTypeMapper(sources, targets) {
                    switch (sources.length) {
                        case 1: return createUnaryTypeMapper(sources[0], targets[0]);
                        case 2: return createBinaryTypeMapper(sources[0], targets[0], sources[1], targets[1]);
                    }
                    return function (t) {
                        for (var i = 0; i < sources.length; i++) {
                            if (t === sources[i]) {
                                return targets[i];
                            }
                        }
                        return t;
                    };
                }
                function createUnaryTypeEraser(source) {
                    return function (t) { return t === source ? anyType : t; };
                }
                function createBinaryTypeEraser(source1, source2) {
                    return function (t) { return t === source1 || t === source2 ? anyType : t; };
                }
                function createTypeEraser(sources) {
                    switch (sources.length) {
                        case 1: return createUnaryTypeEraser(sources[0]);
                        case 2: return createBinaryTypeEraser(sources[0], sources[1]);
                    }
                    return function (t) {
                        for (var _i = 0; _i < sources.length; _i++) {
                            var source = sources[_i];
                            if (t === source) {
                                return anyType;
                            }
                        }
                        return t;
                    };
                }
                function createInferenceMapper(context) {
                    return function (t) {
                        for (var i = 0; i < context.typeParameters.length; i++) {
                            if (t === context.typeParameters[i]) {
                                context.inferences[i].isFixed = true;
                                return getInferredType(context, i);
                            }
                        }
                        return t;
                    };
                }
                function identityMapper(type) {
                    return type;
                }
                function combineTypeMappers(mapper1, mapper2) {
                    return function (t) { return instantiateType(mapper1(t), mapper2); };
                }
                function instantiateTypeParameter(typeParameter, mapper) {
                    var result = createType(512 /* TypeParameter */);
                    result.symbol = typeParameter.symbol;
                    if (typeParameter.constraint) {
                        result.constraint = instantiateType(typeParameter.constraint, mapper);
                    }
                    else {
                        result.target = typeParameter;
                        result.mapper = mapper;
                    }
                    return result;
                }
                function instantiateSignature(signature, mapper, eraseTypeParameters) {
                    var freshTypeParameters;
                    if (signature.typeParameters && !eraseTypeParameters) {
                        freshTypeParameters = instantiateList(signature.typeParameters, mapper, instantiateTypeParameter);
                        mapper = combineTypeMappers(createTypeMapper(signature.typeParameters, freshTypeParameters), mapper);
                    }
                    var result = createSignature(signature.declaration, freshTypeParameters, instantiateList(signature.parameters, mapper, instantiateSymbol), signature.resolvedReturnType ? instantiateType(signature.resolvedReturnType, mapper) : undefined, signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals);
                    result.target = signature;
                    result.mapper = mapper;
                    return result;
                }
                function instantiateSymbol(symbol, mapper) {
                    if (symbol.flags & 16777216 /* Instantiated */) {
                        var links = getSymbolLinks(symbol);
                        // If symbol being instantiated is itself a instantiation, fetch the original target and combine the
                        // type mappers. This ensures that original type identities are properly preserved and that aliases
                        // always reference a non-aliases.
                        symbol = links.target;
                        mapper = combineTypeMappers(links.mapper, mapper);
                    }
                    // Keep the flags from the symbol we're instantiating.  Mark that is instantiated, and
                    // also transient so that we can just store data on it directly.
                    var result = createSymbol(16777216 /* Instantiated */ | 67108864 /* Transient */ | symbol.flags, symbol.name);
                    result.declarations = symbol.declarations;
                    result.parent = symbol.parent;
                    result.target = symbol;
                    result.mapper = mapper;
                    if (symbol.valueDeclaration) {
                        result.valueDeclaration = symbol.valueDeclaration;
                    }
                    return result;
                }
                function instantiateAnonymousType(type, mapper) {
                    var result = createObjectType(32768 /* Anonymous */, type.symbol);
                    result.properties = instantiateList(getPropertiesOfObjectType(type), mapper, instantiateSymbol);
                    result.members = createSymbolTable(result.properties);
                    result.callSignatures = instantiateList(getSignaturesOfType(type, 0 /* Call */), mapper, instantiateSignature);
                    result.constructSignatures = instantiateList(getSignaturesOfType(type, 1 /* Construct */), mapper, instantiateSignature);
                    var stringIndexType = getIndexTypeOfType(type, 0 /* String */);
                    var numberIndexType = getIndexTypeOfType(type, 1 /* Number */);
                    if (stringIndexType)
                        result.stringIndexType = instantiateType(stringIndexType, mapper);
                    if (numberIndexType)
                        result.numberIndexType = instantiateType(numberIndexType, mapper);
                    return result;
                }
                function instantiateType(type, mapper) {
                    if (mapper !== identityMapper) {
                        if (type.flags & 512 /* TypeParameter */) {
                            return mapper(type);
                        }
                        if (type.flags & 32768 /* Anonymous */) {
                            return type.symbol && type.symbol.flags & (16 /* Function */ | 8192 /* Method */ | 2048 /* TypeLiteral */ | 4096 /* ObjectLiteral */) ?
                                instantiateAnonymousType(type, mapper) : type;
                        }
                        if (type.flags & 4096 /* Reference */) {
                            return createTypeReference(type.target, instantiateList(type.typeArguments, mapper, instantiateType));
                        }
                        if (type.flags & 8192 /* Tuple */) {
                            return createTupleType(instantiateList(type.elementTypes, mapper, instantiateType));
                        }
                        if (type.flags & 16384 /* Union */) {
                            return getUnionType(instantiateList(type.types, mapper, instantiateType), true);
                        }
                    }
                    return type;
                }
                // Returns true if the given expression contains (at any level of nesting) a function or arrow expression
                // that is subject to contextual typing.
                function isContextSensitive(node) {
                    ts.Debug.assert(node.kind !== 134 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node));
                    switch (node.kind) {
                        case 162 /* FunctionExpression */:
                        case 163 /* ArrowFunction */:
                            return isContextSensitiveFunctionLikeDeclaration(node);
                        case 154 /* ObjectLiteralExpression */:
                            return ts.forEach(node.properties, isContextSensitive);
                        case 153 /* ArrayLiteralExpression */:
                            return ts.forEach(node.elements, isContextSensitive);
                        case 170 /* ConditionalExpression */:
                            return isContextSensitive(node.whenTrue) ||
                                isContextSensitive(node.whenFalse);
                        case 169 /* BinaryExpression */:
                            return node.operatorToken.kind === 49 /* BarBarToken */ &&
                                (isContextSensitive(node.left) || isContextSensitive(node.right));
                        case 224 /* PropertyAssignment */:
                            return isContextSensitive(node.initializer);
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                            return isContextSensitiveFunctionLikeDeclaration(node);
                        case 161 /* ParenthesizedExpression */:
                            return isContextSensitive(node.expression);
                    }
                    return false;
                }
                function isContextSensitiveFunctionLikeDeclaration(node) {
                    return !node.typeParameters && node.parameters.length && !ts.forEach(node.parameters, function (p) { return p.type; });
                }
                function getTypeWithoutConstructors(type) {
                    if (type.flags & 48128 /* ObjectType */) {
                        var resolved = resolveObjectOrUnionTypeMembers(type);
                        if (resolved.constructSignatures.length) {
                            var result = createObjectType(32768 /* Anonymous */, type.symbol);
                            result.members = resolved.members;
                            result.properties = resolved.properties;
                            result.callSignatures = resolved.callSignatures;
                            result.constructSignatures = emptyArray;
                            type = result;
                        }
                    }
                    return type;
                }
                // TYPE CHECKING
                var subtypeRelation = {};
                var assignableRelation = {};
                var identityRelation = {};
                function isTypeIdenticalTo(source, target) {
                    return checkTypeRelatedTo(source, target, identityRelation, undefined);
                }
                function compareTypes(source, target) {
                    return checkTypeRelatedTo(source, target, identityRelation, undefined) ? -1 /* True */ : 0 /* False */;
                }
                function isTypeSubtypeOf(source, target) {
                    return checkTypeSubtypeOf(source, target, undefined);
                }
                function isTypeAssignableTo(source, target) {
                    return checkTypeAssignableTo(source, target, undefined);
                }
                function checkTypeSubtypeOf(source, target, errorNode, headMessage, containingMessageChain) {
                    return checkTypeRelatedTo(source, target, subtypeRelation, errorNode, headMessage, containingMessageChain);
                }
                function checkTypeAssignableTo(source, target, errorNode, headMessage) {
                    return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage);
                }
                function isSignatureAssignableTo(source, target) {
                    var sourceType = getOrCreateTypeFromSignature(source);
                    var targetType = getOrCreateTypeFromSignature(target);
                    return checkTypeRelatedTo(sourceType, targetType, assignableRelation, undefined);
                }
                function checkTypeRelatedTo(source, target, relation, errorNode, headMessage, containingMessageChain) {
                    var errorInfo;
                    var sourceStack;
                    var targetStack;
                    var maybeStack;
                    var expandingFlags;
                    var depth = 0;
                    var overflow = false;
                    var elaborateErrors = false;
                    ts.Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking");
                    var result = isRelatedTo(source, target, errorNode !== undefined, headMessage);
                    if (overflow) {
                        error(errorNode, ts.Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target));
                    }
                    else if (errorInfo) {
                        // If we already computed this relation, but in a context where we didn't want to report errors (e.g. overload resolution),
                        // then we'll only have a top-level error (e.g. 'Class X does not implement interface Y') without any details. If this happened,
                        // request a recompuation to get a complete error message. This will be skipped if we've already done this computation in a context
                        // where errors were being reported.
                        if (errorInfo.next === undefined) {
                            errorInfo = undefined;
                            elaborateErrors = true;
                            isRelatedTo(source, target, errorNode !== undefined, headMessage);
                        }
                        if (containingMessageChain) {
                            errorInfo = ts.concatenateDiagnosticMessageChains(containingMessageChain, errorInfo);
                        }
                        diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(errorNode, errorInfo));
                    }
                    return result !== 0 /* False */;
                    function reportError(message, arg0, arg1, arg2) {
                        errorInfo = ts.chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2);
                    }
                    // Compare two types and return
                    // Ternary.True if they are related with no assumptions,
                    // Ternary.Maybe if they are related with assumptions of other relationships, or
                    // Ternary.False if they are not related.
                    function isRelatedTo(source, target, reportErrors, headMessage) {
                        var result;
                        // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases
                        if (source === target)
                            return -1 /* True */;
                        if (relation !== identityRelation) {
                            if (target.flags & 1 /* Any */)
                                return -1 /* True */;
                            if (source === undefinedType)
                                return -1 /* True */;
                            if (source === nullType && target !== undefinedType)
                                return -1 /* True */;
                            if (source.flags & 128 /* Enum */ && target === numberType)
                                return -1 /* True */;
                            if (source.flags & 256 /* StringLiteral */ && target === stringType)
                                return -1 /* True */;
                            if (relation === assignableRelation) {
                                if (source.flags & 1 /* Any */)
                                    return -1 /* True */;
                                if (source === numberType && target.flags & 128 /* Enum */)
                                    return -1 /* True */;
                            }
                        }
                        var saveErrorInfo = errorInfo;
                        if (source.flags & 16384 /* Union */ || target.flags & 16384 /* Union */) {
                            if (relation === identityRelation) {
                                if (source.flags & 16384 /* Union */ && target.flags & 16384 /* Union */) {
                                    if (result = unionTypeRelatedToUnionType(source, target)) {
                                        if (result &= unionTypeRelatedToUnionType(target, source)) {
                                            return result;
                                        }
                                    }
                                }
                                else if (source.flags & 16384 /* Union */) {
                                    if (result = unionTypeRelatedToType(source, target, reportErrors)) {
                                        return result;
                                    }
                                }
                                else {
                                    if (result = unionTypeRelatedToType(target, source, reportErrors)) {
                                        return result;
                                    }
                                }
                            }
                            else {
                                if (source.flags & 16384 /* Union */) {
                                    if (result = unionTypeRelatedToType(source, target, reportErrors)) {
                                        return result;
                                    }
                                }
                                else {
                                    if (result = typeRelatedToUnionType(source, target, reportErrors)) {
                                        return result;
                                    }
                                }
                            }
                        }
                        else if (source.flags & 512 /* TypeParameter */ && target.flags & 512 /* TypeParameter */) {
                            if (result = typeParameterRelatedTo(source, target, reportErrors)) {
                                return result;
                            }
                        }
                        else if (source.flags & 4096 /* Reference */ && target.flags & 4096 /* Reference */ && source.target === target.target) {
                            // We have type references to same target type, see if relationship holds for all type arguments
                            if (result = typesRelatedTo(source.typeArguments, target.typeArguments, reportErrors)) {
                                return result;
                            }
                        }
                        // Even if relationship doesn't hold for unions, type parameters, or generic type references,
                        // it may hold in a structural comparison.
                        // Report structural errors only if we haven't reported any errors yet
                        var reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
                        // identity relation does not use apparent type
                        var sourceOrApparentType = relation === identityRelation ? source : getApparentType(source);
                        if (sourceOrApparentType.flags & 48128 /* ObjectType */ && target.flags & 48128 /* ObjectType */) {
                            if (result = objectTypeRelatedTo(sourceOrApparentType, target, reportStructuralErrors)) {
                                errorInfo = saveErrorInfo;
                                return result;
                            }
                        }
                        else if (source.flags & 512 /* TypeParameter */ && sourceOrApparentType.flags & 16384 /* Union */) {
                            // We clear the errors first because the following check often gives a better error than
                            // the union comparison above if it is applicable.
                            errorInfo = saveErrorInfo;
                            if (result = isRelatedTo(sourceOrApparentType, target, reportErrors)) {
                                return result;
                            }
                        }
                        if (reportErrors) {
                            headMessage = headMessage || ts.Diagnostics.Type_0_is_not_assignable_to_type_1;
                            var sourceType = typeToString(source);
                            var targetType = typeToString(target);
                            if (sourceType === targetType) {
                                sourceType = typeToString(source, undefined, 128 /* UseFullyQualifiedType */);
                                targetType = typeToString(target, undefined, 128 /* UseFullyQualifiedType */);
                            }
                            reportError(headMessage, sourceType, targetType);
                        }
                        return 0 /* False */;
                    }
                    function unionTypeRelatedToUnionType(source, target) {
                        var result = -1 /* True */;
                        var sourceTypes = source.types;
                        for (var _i = 0; _i < sourceTypes.length; _i++) {
                            var sourceType = sourceTypes[_i];
                            var related = typeRelatedToUnionType(sourceType, target, false);
                            if (!related) {
                                return 0 /* False */;
                            }
                            result &= related;
                        }
                        return result;
                    }
                    function typeRelatedToUnionType(source, target, reportErrors) {
                        var targetTypes = target.types;
                        for (var i = 0, len = targetTypes.length; i < len; i++) {
                            var related = isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1);
                            if (related) {
                                return related;
                            }
                        }
                        return 0 /* False */;
                    }
                    function unionTypeRelatedToType(source, target, reportErrors) {
                        var result = -1 /* True */;
                        var sourceTypes = source.types;
                        for (var _i = 0; _i < sourceTypes.length; _i++) {
                            var sourceType = sourceTypes[_i];
                            var related = isRelatedTo(sourceType, target, reportErrors);
                            if (!related) {
                                return 0 /* False */;
                            }
                            result &= related;
                        }
                        return result;
                    }
                    function typesRelatedTo(sources, targets, reportErrors) {
                        var result = -1 /* True */;
                        for (var i = 0, len = sources.length; i < len; i++) {
                            var related = isRelatedTo(sources[i], targets[i], reportErrors);
                            if (!related) {
                                return 0 /* False */;
                            }
                            result &= related;
                        }
                        return result;
                    }
                    function typeParameterRelatedTo(source, target, reportErrors) {
                        if (relation === identityRelation) {
                            if (source.symbol.name !== target.symbol.name) {
                                return 0 /* False */;
                            }
                            // covers case when both type parameters does not have constraint (both equal to noConstraintType)
                            if (source.constraint === target.constraint) {
                                return -1 /* True */;
                            }
                            if (source.constraint === noConstraintType || target.constraint === noConstraintType) {
                                return 0 /* False */;
                            }
                            return isRelatedTo(source.constraint, target.constraint, reportErrors);
                        }
                        else {
                            while (true) {
                                var constraint = getConstraintOfTypeParameter(source);
                                if (constraint === target)
                                    return -1 /* True */;
                                if (!(constraint && constraint.flags & 512 /* TypeParameter */))
                                    break;
                                source = constraint;
                            }
                            return 0 /* False */;
                        }
                    }
                    // Determine if two object types are related by structure. First, check if the result is already available in the global cache.
                    // Second, check if we have already started a comparison of the given two types in which case we assume the result to be true.
                    // Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are
                    // equal and infinitely expanding. Fourth, if we have reached a depth of 100 nested comparisons, assume we have runaway recursion
                    // and issue an error. Otherwise, actually compare the structure of the two types.
                    function objectTypeRelatedTo(source, target, reportErrors) {
                        if (overflow) {
                            return 0 /* False */;
                        }
                        var id = relation !== identityRelation || source.id < target.id ? source.id + "," + target.id : target.id + "," + source.id;
                        var related = relation[id];
                        //let related: RelationComparisonResult = undefined; // relation[id];
                        if (related !== undefined) {
                            // If we computed this relation already and it was failed and reported, or if we're not being asked to elaborate
                            // errors, we can use the cached value. Otherwise, recompute the relation
                            if (!elaborateErrors || (related === 3 /* FailedAndReported */)) {
                                return related === 1 /* Succeeded */ ? -1 /* True */ : 0 /* False */;
                            }
                        }
                        if (depth > 0) {
                            for (var i = 0; i < depth; i++) {
                                // If source and target are already being compared, consider them related with assumptions
                                if (maybeStack[i][id]) {
                                    return 1 /* Maybe */;
                                }
                            }
                            if (depth === 100) {
                                overflow = true;
                                return 0 /* False */;
                            }
                        }
                        else {
                            sourceStack = [];
                            targetStack = [];
                            maybeStack = [];
                            expandingFlags = 0;
                        }
                        sourceStack[depth] = source;
                        targetStack[depth] = target;
                        maybeStack[depth] = {};
                        maybeStack[depth][id] = 1 /* Succeeded */;
                        depth++;
                        var saveExpandingFlags = expandingFlags;
                        if (!(expandingFlags & 1) && isDeeplyNestedGeneric(source, sourceStack))
                            expandingFlags |= 1;
                        if (!(expandingFlags & 2) && isDeeplyNestedGeneric(target, targetStack))
                            expandingFlags |= 2;
                        var result;
                        if (expandingFlags === 3) {
                            result = 1 /* Maybe */;
                        }
                        else {
                            result = propertiesRelatedTo(source, target, reportErrors);
                            if (result) {
                                result &= signaturesRelatedTo(source, target, 0 /* Call */, reportErrors);
                                if (result) {
                                    result &= signaturesRelatedTo(source, target, 1 /* Construct */, reportErrors);
                                    if (result) {
                                        result &= stringIndexTypesRelatedTo(source, target, reportErrors);
                                        if (result) {
                                            result &= numberIndexTypesRelatedTo(source, target, reportErrors);
                                        }
                                    }
                                }
                            }
                        }
                        expandingFlags = saveExpandingFlags;
                        depth--;
                        if (result) {
                            var maybeCache = maybeStack[depth];
                            // If result is definitely true, copy assumptions to global cache, else copy to next level up
                            var destinationCache = (result === -1 /* True */ || depth === 0) ? relation : maybeStack[depth - 1];
                            ts.copyMap(maybeCache, destinationCache);
                        }
                        else {
                            // A false result goes straight into global cache (when something is false under assumptions it
                            // will also be false without assumptions)
                            relation[id] = reportErrors ? 3 /* FailedAndReported */ : 2 /* Failed */;
                        }
                        return result;
                    }
                    // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case
                    // when structural type comparisons have been started for 10 or more instantiations of the same generic type. It is possible,
                    // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely expanding.
                    // Effectively, we will generate a false positive when two types are structurally equal to at least 10 levels, but unequal at
                    // some level beyond that.
                    function isDeeplyNestedGeneric(type, stack) {
                        if (type.flags & 4096 /* Reference */ && depth >= 10) {
                            var target_1 = type.target;
                            var count = 0;
                            for (var i = 0; i < depth; i++) {
                                var t = stack[i];
                                if (t.flags & 4096 /* Reference */ && t.target === target_1) {
                                    count++;
                                    if (count >= 10)
                                        return true;
                                }
                            }
                        }
                        return false;
                    }
                    function propertiesRelatedTo(source, target, reportErrors) {
                        if (relation === identityRelation) {
                            return propertiesIdenticalTo(source, target);
                        }
                        var result = -1 /* True */;
                        var properties = getPropertiesOfObjectType(target);
                        var requireOptionalProperties = relation === subtypeRelation && !(source.flags & 131072 /* ObjectLiteral */);
                        for (var _i = 0; _i < properties.length; _i++) {
                            var targetProp = properties[_i];
                            var sourceProp = getPropertyOfType(source, targetProp.name);
                            if (sourceProp !== targetProp) {
                                if (!sourceProp) {
                                    if (!(targetProp.flags & 536870912 /* Optional */) || requireOptionalProperties) {
                                        if (reportErrors) {
                                            reportError(ts.Diagnostics.Property_0_is_missing_in_type_1, symbolToString(targetProp), typeToString(source));
                                        }
                                        return 0 /* False */;
                                    }
                                }
                                else if (!(targetProp.flags & 134217728 /* Prototype */)) {
                                    var sourceFlags = getDeclarationFlagsFromSymbol(sourceProp);
                                    var targetFlags = getDeclarationFlagsFromSymbol(targetProp);
                                    if (sourceFlags & 32 /* Private */ || targetFlags & 32 /* Private */) {
                                        if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) {
                                            if (reportErrors) {
                                                if (sourceFlags & 32 /* Private */ && targetFlags & 32 /* Private */) {
                                                    reportError(ts.Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp));
                                                }
                                                else {
                                                    reportError(ts.Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp), typeToString(sourceFlags & 32 /* Private */ ? source : target), typeToString(sourceFlags & 32 /* Private */ ? target : source));
                                                }
                                            }
                                            return 0 /* False */;
                                        }
                                    }
                                    else if (targetFlags & 64 /* Protected */) {
                                        var sourceDeclaredInClass = sourceProp.parent && sourceProp.parent.flags & 32 /* Class */;
                                        var sourceClass = sourceDeclaredInClass ? getDeclaredTypeOfSymbol(sourceProp.parent) : undefined;
                                        var targetClass = getDeclaredTypeOfSymbol(targetProp.parent);
                                        if (!sourceClass || !hasBaseType(sourceClass, targetClass)) {
                                            if (reportErrors) {
                                                reportError(ts.Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, symbolToString(targetProp), typeToString(sourceClass || source), typeToString(targetClass));
                                            }
                                            return 0 /* False */;
                                        }
                                    }
                                    else if (sourceFlags & 64 /* Protected */) {
                                        if (reportErrors) {
                                            reportError(ts.Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target));
                                        }
                                        return 0 /* False */;
                                    }
                                    var related = isRelatedTo(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp), reportErrors);
                                    if (!related) {
                                        if (reportErrors) {
                                            reportError(ts.Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp));
                                        }
                                        return 0 /* False */;
                                    }
                                    result &= related;
                                    if (sourceProp.flags & 536870912 /* Optional */ && !(targetProp.flags & 536870912 /* Optional */)) {
                                        // TypeScript 1.0 spec (April 2014): 3.8.3
                                        // S is a subtype of a type T, and T is a supertype of S if ...
                                        // S' and T are object types and, for each member M in T..
                                        // M is a property and S' contains a property N where
                                        // if M is a required property, N is also a required property
                                        // (M - property in T)
                                        // (N - property in S)
                                        if (reportErrors) {
                                            reportError(ts.Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target));
                                        }
                                        return 0 /* False */;
                                    }
                                }
                            }
                        }
                        return result;
                    }
                    function propertiesIdenticalTo(source, target) {
                        var sourceProperties = getPropertiesOfObjectType(source);
                        var targetProperties = getPropertiesOfObjectType(target);
                        if (sourceProperties.length !== targetProperties.length) {
                            return 0 /* False */;
                        }
                        var result = -1 /* True */;
                        for (var _i = 0; _i < sourceProperties.length; _i++) {
                            var sourceProp = sourceProperties[_i];
                            var targetProp = getPropertyOfObjectType(target, sourceProp.name);
                            if (!targetProp) {
                                return 0 /* False */;
                            }
                            var related = compareProperties(sourceProp, targetProp, isRelatedTo);
                            if (!related) {
                                return 0 /* False */;
                            }
                            result &= related;
                        }
                        return result;
                    }
                    function signaturesRelatedTo(source, target, kind, reportErrors) {
                        if (relation === identityRelation) {
                            return signaturesIdenticalTo(source, target, kind);
                        }
                        if (target === anyFunctionType || source === anyFunctionType) {
                            return -1 /* True */;
                        }
                        var sourceSignatures = getSignaturesOfType(source, kind);
                        var targetSignatures = getSignaturesOfType(target, kind);
                        var result = -1 /* True */;
                        var saveErrorInfo = errorInfo;
                        outer: for (var _i = 0; _i < targetSignatures.length; _i++) {
                            var t = targetSignatures[_i];
                            if (!t.hasStringLiterals || target.flags & 65536 /* FromSignature */) {
                                var localErrors = reportErrors;
                                for (var _a = 0; _a < sourceSignatures.length; _a++) {
                                    var s = sourceSignatures[_a];
                                    if (!s.hasStringLiterals || source.flags & 65536 /* FromSignature */) {
                                        var related = signatureRelatedTo(s, t, localErrors);
                                        if (related) {
                                            result &= related;
                                            errorInfo = saveErrorInfo;
                                            continue outer;
                                        }
                                        // Only report errors from the first failure
                                        localErrors = false;
                                    }
                                }
                                return 0 /* False */;
                            }
                        }
                        return result;
                    }
                    function signatureRelatedTo(source, target, reportErrors) {
                        if (source === target) {
                            return -1 /* True */;
                        }
                        if (!target.hasRestParameter && source.minArgumentCount > target.parameters.length) {
                            return 0 /* False */;
                        }
                        var sourceMax = source.parameters.length;
                        var targetMax = target.parameters.length;
                        var checkCount;
                        if (source.hasRestParameter && target.hasRestParameter) {
                            checkCount = sourceMax > targetMax ? sourceMax : targetMax;
                            sourceMax--;
                            targetMax--;
                        }
                        else if (source.hasRestParameter) {
                            sourceMax--;
                            checkCount = targetMax;
                        }
                        else if (target.hasRestParameter) {
                            targetMax--;
                            checkCount = sourceMax;
                        }
                        else {
                            checkCount = sourceMax < targetMax ? sourceMax : targetMax;
                        }
                        // Spec 1.0 Section 3.8.3 & 3.8.4:
                        // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
                        source = getErasedSignature(source);
                        target = getErasedSignature(target);
                        var result = -1 /* True */;
                        for (var i = 0; i < checkCount; i++) {
                            var s_1 = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source);
                            var t_1 = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target);
                            var saveErrorInfo = errorInfo;
                            var related = isRelatedTo(s_1, t_1, reportErrors);
                            if (!related) {
                                related = isRelatedTo(t_1, s_1, false);
                                if (!related) {
                                    if (reportErrors) {
                                        reportError(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, source.parameters[i < sourceMax ? i : sourceMax].name, target.parameters[i < targetMax ? i : targetMax].name);
                                    }
                                    return 0 /* False */;
                                }
                                errorInfo = saveErrorInfo;
                            }
                            result &= related;
                        }
                        var t = getReturnTypeOfSignature(target);
                        if (t === voidType)
                            return result;
                        var s = getReturnTypeOfSignature(source);
                        return result & isRelatedTo(s, t, reportErrors);
                    }
                    function signaturesIdenticalTo(source, target, kind) {
                        var sourceSignatures = getSignaturesOfType(source, kind);
                        var targetSignatures = getSignaturesOfType(target, kind);
                        if (sourceSignatures.length !== targetSignatures.length) {
                            return 0 /* False */;
                        }
                        var result = -1 /* True */;
                        for (var i = 0, len = sourceSignatures.length; i < len; ++i) {
                            var related = compareSignatures(sourceSignatures[i], targetSignatures[i], true, isRelatedTo);
                            if (!related) {
                                return 0 /* False */;
                            }
                            result &= related;
                        }
                        return result;
                    }
                    function stringIndexTypesRelatedTo(source, target, reportErrors) {
                        if (relation === identityRelation) {
                            return indexTypesIdenticalTo(0 /* String */, source, target);
                        }
                        var targetType = getIndexTypeOfType(target, 0 /* String */);
                        if (targetType) {
                            var sourceType = getIndexTypeOfType(source, 0 /* String */);
                            if (!sourceType) {
                                if (reportErrors) {
                                    reportError(ts.Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
                                }
                                return 0 /* False */;
                            }
                            var related = isRelatedTo(sourceType, targetType, reportErrors);
                            if (!related) {
                                if (reportErrors) {
                                    reportError(ts.Diagnostics.Index_signatures_are_incompatible);
                                }
                                return 0 /* False */;
                            }
                            return related;
                        }
                        return -1 /* True */;
                    }
                    function numberIndexTypesRelatedTo(source, target, reportErrors) {
                        if (relation === identityRelation) {
                            return indexTypesIdenticalTo(1 /* Number */, source, target);
                        }
                        var targetType = getIndexTypeOfType(target, 1 /* Number */);
                        if (targetType) {
                            var sourceStringType = getIndexTypeOfType(source, 0 /* String */);
                            var sourceNumberType = getIndexTypeOfType(source, 1 /* Number */);
                            if (!(sourceStringType || sourceNumberType)) {
                                if (reportErrors) {
                                    reportError(ts.Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
                                }
                                return 0 /* False */;
                            }
                            var related;
                            if (sourceStringType && sourceNumberType) {
                                // If we know for sure we're testing both string and numeric index types then only report errors from the second one
                                related = isRelatedTo(sourceStringType, targetType, false) || isRelatedTo(sourceNumberType, targetType, reportErrors);
                            }
                            else {
                                related = isRelatedTo(sourceStringType || sourceNumberType, targetType, reportErrors);
                            }
                            if (!related) {
                                if (reportErrors) {
                                    reportError(ts.Diagnostics.Index_signatures_are_incompatible);
                                }
                                return 0 /* False */;
                            }
                            return related;
                        }
                        return -1 /* True */;
                    }
                    function indexTypesIdenticalTo(indexKind, source, target) {
                        var targetType = getIndexTypeOfType(target, indexKind);
                        var sourceType = getIndexTypeOfType(source, indexKind);
                        if (!sourceType && !targetType) {
                            return -1 /* True */;
                        }
                        if (sourceType && targetType) {
                            return isRelatedTo(sourceType, targetType);
                        }
                        return 0 /* False */;
                    }
                }
                function isPropertyIdenticalTo(sourceProp, targetProp) {
                    return compareProperties(sourceProp, targetProp, compareTypes) !== 0 /* False */;
                }
                function compareProperties(sourceProp, targetProp, compareTypes) {
                    // Two members are considered identical when
                    // - they are public properties with identical names, optionality, and types,
                    // - they are private or protected properties originating in the same declaration and having identical types
                    if (sourceProp === targetProp) {
                        return -1 /* True */;
                    }
                    var sourcePropAccessibility = getDeclarationFlagsFromSymbol(sourceProp) & (32 /* Private */ | 64 /* Protected */);
                    var targetPropAccessibility = getDeclarationFlagsFromSymbol(targetProp) & (32 /* Private */ | 64 /* Protected */);
                    if (sourcePropAccessibility !== targetPropAccessibility) {
                        return 0 /* False */;
                    }
                    if (sourcePropAccessibility) {
                        if (getTargetSymbol(sourceProp) !== getTargetSymbol(targetProp)) {
                            return 0 /* False */;
                        }
                    }
                    else {
                        if ((sourceProp.flags & 536870912 /* Optional */) !== (targetProp.flags & 536870912 /* Optional */)) {
                            return 0 /* False */;
                        }
                    }
                    return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
                }
                function compareSignatures(source, target, compareReturnTypes, compareTypes) {
                    if (source === target) {
                        return -1 /* True */;
                    }
                    if (source.parameters.length !== target.parameters.length ||
                        source.minArgumentCount !== target.minArgumentCount ||
                        source.hasRestParameter !== target.hasRestParameter) {
                        return 0 /* False */;
                    }
                    var result = -1 /* True */;
                    if (source.typeParameters && target.typeParameters) {
                        if (source.typeParameters.length !== target.typeParameters.length) {
                            return 0 /* False */;
                        }
                        for (var i = 0, len = source.typeParameters.length; i < len; ++i) {
                            var related = compareTypes(source.typeParameters[i], target.typeParameters[i]);
                            if (!related) {
                                return 0 /* False */;
                            }
                            result &= related;
                        }
                    }
                    else if (source.typeParameters || target.typeParameters) {
                        return 0 /* False */;
                    }
                    // Spec 1.0 Section 3.8.3 & 3.8.4:
                    // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
                    source = getErasedSignature(source);
                    target = getErasedSignature(target);
                    for (var i = 0, len = source.parameters.length; i < len; i++) {
                        var s = source.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
                        var t = target.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
                        var related = compareTypes(s, t);
                        if (!related) {
                            return 0 /* False */;
                        }
                        result &= related;
                    }
                    if (compareReturnTypes) {
                        result &= compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
                    }
                    return result;
                }
                function isSupertypeOfEach(candidate, types) {
                    for (var _i = 0; _i < types.length; _i++) {
                        var type = types[_i];
                        if (candidate !== type && !isTypeSubtypeOf(type, candidate))
                            return false;
                    }
                    return true;
                }
                function getCommonSupertype(types) {
                    return ts.forEach(types, function (t) { return isSupertypeOfEach(t, types) ? t : undefined; });
                }
                function reportNoCommonSupertypeError(types, errorLocation, errorMessageChainHead) {
                    // The downfallType/bestSupertypeDownfallType is the first type that caused a particular candidate
                    // to not be the common supertype. So if it weren't for this one downfallType (and possibly others),
                    // the type in question could have been the common supertype.
                    var bestSupertype;
                    var bestSupertypeDownfallType;
                    var bestSupertypeScore = 0;
                    for (var i = 0; i < types.length; i++) {
                        var score = 0;
                        var downfallType = undefined;
                        for (var j = 0; j < types.length; j++) {
                            if (isTypeSubtypeOf(types[j], types[i])) {
                                score++;
                            }
                            else if (!downfallType) {
                                downfallType = types[j];
                            }
                        }
                        ts.Debug.assert(!!downfallType, "If there is no common supertype, each type should have a downfallType");
                        if (score > bestSupertypeScore) {
                            bestSupertype = types[i];
                            bestSupertypeDownfallType = downfallType;
                            bestSupertypeScore = score;
                        }
                        // types.length - 1 is the maximum score, given that getCommonSupertype returned false
                        if (bestSupertypeScore === types.length - 1) {
                            break;
                        }
                    }
                    // In the following errors, the {1} slot is before the {0} slot because checkTypeSubtypeOf supplies the
                    // subtype as the first argument to the error
                    checkTypeSubtypeOf(bestSupertypeDownfallType, bestSupertype, errorLocation, ts.Diagnostics.Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0, errorMessageChainHead);
                }
                function isArrayType(type) {
                    return type.flags & 4096 /* Reference */ && type.target === globalArrayType;
                }
                function isArrayLikeType(type) {
                    // A type is array-like if it is not the undefined or null type and if it is assignable to any[]
                    return !(type.flags & (32 /* Undefined */ | 64 /* Null */)) && isTypeAssignableTo(type, anyArrayType);
                }
                function isTupleLikeType(type) {
                    return !!getPropertyOfType(type, "0");
                }
                /**
                 * Check if a Type was written as a tuple type literal.
                 * Prefer using isTupleLikeType() unless the use of `elementTypes` is required.
                 */
                function isTupleType(type) {
                    return (type.flags & 8192 /* Tuple */) && !!type.elementTypes;
                }
                function getWidenedTypeOfObjectLiteral(type) {
                    var properties = getPropertiesOfObjectType(type);
                    var members = {};
                    ts.forEach(properties, function (p) {
                        var propType = getTypeOfSymbol(p);
                        var widenedType = getWidenedType(propType);
                        if (propType !== widenedType) {
                            var symbol = createSymbol(p.flags | 67108864 /* Transient */, p.name);
                            symbol.declarations = p.declarations;
                            symbol.parent = p.parent;
                            symbol.type = widenedType;
                            symbol.target = p;
                            if (p.valueDeclaration)
                                symbol.valueDeclaration = p.valueDeclaration;
                            p = symbol;
                        }
                        members[p.name] = p;
                    });
                    var stringIndexType = getIndexTypeOfType(type, 0 /* String */);
                    var numberIndexType = getIndexTypeOfType(type, 1 /* Number */);
                    if (stringIndexType)
                        stringIndexType = getWidenedType(stringIndexType);
                    if (numberIndexType)
                        numberIndexType = getWidenedType(numberIndexType);
                    return createAnonymousType(type.symbol, members, emptyArray, emptyArray, stringIndexType, numberIndexType);
                }
                function getWidenedType(type) {
                    if (type.flags & 786432 /* RequiresWidening */) {
                        if (type.flags & (32 /* Undefined */ | 64 /* Null */)) {
                            return anyType;
                        }
                        if (type.flags & 131072 /* ObjectLiteral */) {
                            return getWidenedTypeOfObjectLiteral(type);
                        }
                        if (type.flags & 16384 /* Union */) {
                            return getUnionType(ts.map(type.types, getWidenedType));
                        }
                        if (isArrayType(type)) {
                            return createArrayType(getWidenedType(type.typeArguments[0]));
                        }
                    }
                    return type;
                }
                function reportWideningErrorsInType(type) {
                    if (type.flags & 16384 /* Union */) {
                        var errorReported = false;
                        ts.forEach(type.types, function (t) {
                            if (reportWideningErrorsInType(t)) {
                                errorReported = true;
                            }
                        });
                        return errorReported;
                    }
                    if (isArrayType(type)) {
                        return reportWideningErrorsInType(type.typeArguments[0]);
                    }
                    if (type.flags & 131072 /* ObjectLiteral */) {
                        var errorReported = false;
                        ts.forEach(getPropertiesOfObjectType(type), function (p) {
                            var t = getTypeOfSymbol(p);
                            if (t.flags & 262144 /* ContainsUndefinedOrNull */) {
                                if (!reportWideningErrorsInType(t)) {
                                    error(p.valueDeclaration, ts.Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(getWidenedType(t)));
                                }
                                errorReported = true;
                            }
                        });
                        return errorReported;
                    }
                    return false;
                }
                function reportImplicitAnyError(declaration, type) {
                    var typeAsString = typeToString(getWidenedType(type));
                    var diagnostic;
                    switch (declaration.kind) {
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                            diagnostic = ts.Diagnostics.Member_0_implicitly_has_an_1_type;
                            break;
                        case 129 /* Parameter */:
                            diagnostic = declaration.dotDotDotToken ?
                                ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type :
                                ts.Diagnostics.Parameter_0_implicitly_has_an_1_type;
                            break;
                        case 200 /* FunctionDeclaration */:
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                        case 162 /* FunctionExpression */:
                        case 163 /* ArrowFunction */:
                            if (!declaration.name) {
                                error(declaration, ts.Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString);
                                return;
                            }
                            diagnostic = ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type;
                            break;
                        default:
                            diagnostic = ts.Diagnostics.Variable_0_implicitly_has_an_1_type;
                    }
                    error(declaration, diagnostic, ts.declarationNameToString(declaration.name), typeAsString);
                }
                function reportErrorsFromWidening(declaration, type) {
                    if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & 262144 /* ContainsUndefinedOrNull */) {
                        // Report implicit any error within type if possible, otherwise report error on declaration
                        if (!reportWideningErrorsInType(type)) {
                            reportImplicitAnyError(declaration, type);
                        }
                    }
                }
                function forEachMatchingParameterType(source, target, callback) {
                    var sourceMax = source.parameters.length;
                    var targetMax = target.parameters.length;
                    var count;
                    if (source.hasRestParameter && target.hasRestParameter) {
                        count = sourceMax > targetMax ? sourceMax : targetMax;
                        sourceMax--;
                        targetMax--;
                    }
                    else if (source.hasRestParameter) {
                        sourceMax--;
                        count = targetMax;
                    }
                    else if (target.hasRestParameter) {
                        targetMax--;
                        count = sourceMax;
                    }
                    else {
                        count = sourceMax < targetMax ? sourceMax : targetMax;
                    }
                    for (var i = 0; i < count; i++) {
                        var s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source);
                        var t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target);
                        callback(s, t);
                    }
                }
                function createInferenceContext(typeParameters, inferUnionTypes) {
                    var inferences = [];
                    for (var _i = 0; _i < typeParameters.length; _i++) {
                        var unused = typeParameters[_i];
                        inferences.push({ primary: undefined, secondary: undefined, isFixed: false });
                    }
                    return {
                        typeParameters: typeParameters,
                        inferUnionTypes: inferUnionTypes,
                        inferences: inferences,
                        inferredTypes: new Array(typeParameters.length)
                    };
                }
                function inferTypes(context, source, target) {
                    var sourceStack;
                    var targetStack;
                    var depth = 0;
                    var inferiority = 0;
                    inferFromTypes(source, target);
                    function isInProcess(source, target) {
                        for (var i = 0; i < depth; i++) {
                            if (source === sourceStack[i] && target === targetStack[i]) {
                                return true;
                            }
                        }
                        return false;
                    }
                    function isWithinDepthLimit(type, stack) {
                        if (depth >= 5) {
                            var target_2 = type.target;
                            var count = 0;
                            for (var i = 0; i < depth; i++) {
                                var t = stack[i];
                                if (t.flags & 4096 /* Reference */ && t.target === target_2) {
                                    count++;
                                }
                            }
                            return count < 5;
                        }
                        return true;
                    }
                    function inferFromTypes(source, target) {
                        if (source === anyFunctionType) {
                            return;
                        }
                        if (target.flags & 512 /* TypeParameter */) {
                            // If target is a type parameter, make an inference
                            var typeParameters = context.typeParameters;
                            for (var i = 0; i < typeParameters.length; i++) {
                                if (target === typeParameters[i]) {
                                    var inferences = context.inferences[i];
                                    if (!inferences.isFixed) {
                                        // Any inferences that are made to a type parameter in a union type are inferior
                                        // to inferences made to a flat (non-union) type. This is because if we infer to
                                        // T | string[], we really don't know if we should be inferring to T or not (because
                                        // the correct constituent on the target side could be string[]). Therefore, we put
                                        // such inferior inferences into a secondary bucket, and only use them if the primary
                                        // bucket is empty.
                                        var candidates = inferiority ?
                                            inferences.secondary || (inferences.secondary = []) :
                                            inferences.primary || (inferences.primary = []);
                                        if (!ts.contains(candidates, source)) {
                                            candidates.push(source);
                                        }
                                    }
                                    return;
                                }
                            }
                        }
                        else if (source.flags & 4096 /* Reference */ && target.flags & 4096 /* Reference */ && source.target === target.target) {
                            // If source and target are references to the same generic type, infer from type arguments
                            var sourceTypes = source.typeArguments;
                            var targetTypes = target.typeArguments;
                            for (var i = 0; i < sourceTypes.length; i++) {
                                inferFromTypes(sourceTypes[i], targetTypes[i]);
                            }
                        }
                        else if (target.flags & 16384 /* Union */) {
                            var targetTypes = target.types;
                            var typeParameterCount = 0;
                            var typeParameter;
                            // First infer to each type in union that isn't a type parameter
                            for (var _i = 0; _i < targetTypes.length; _i++) {
                                var t = targetTypes[_i];
                                if (t.flags & 512 /* TypeParameter */ && ts.contains(context.typeParameters, t)) {
                                    typeParameter = t;
                                    typeParameterCount++;
                                }
                                else {
                                    inferFromTypes(source, t);
                                }
                            }
                            // If union contains a single naked type parameter, make a secondary inference to that type parameter
                            if (typeParameterCount === 1) {
                                inferiority++;
                                inferFromTypes(source, typeParameter);
                                inferiority--;
                            }
                        }
                        else if (source.flags & 16384 /* Union */) {
                            // Source is a union type, infer from each consituent type
                            var sourceTypes = source.types;
                            for (var _a = 0; _a < sourceTypes.length; _a++) {
                                var sourceType = sourceTypes[_a];
                                inferFromTypes(sourceType, target);
                            }
                        }
                        else if (source.flags & 48128 /* ObjectType */ && (target.flags & (4096 /* Reference */ | 8192 /* Tuple */) ||
                            (target.flags & 32768 /* Anonymous */) && target.symbol && target.symbol.flags & (8192 /* Method */ | 2048 /* TypeLiteral */))) {
                            // If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
                            if (!isInProcess(source, target) && isWithinDepthLimit(source, sourceStack) && isWithinDepthLimit(target, targetStack)) {
                                if (depth === 0) {
                                    sourceStack = [];
                                    targetStack = [];
                                }
                                sourceStack[depth] = source;
                                targetStack[depth] = target;
                                depth++;
                                inferFromProperties(source, target);
                                inferFromSignatures(source, target, 0 /* Call */);
                                inferFromSignatures(source, target, 1 /* Construct */);
                                inferFromIndexTypes(source, target, 0 /* String */, 0 /* String */);
                                inferFromIndexTypes(source, target, 1 /* Number */, 1 /* Number */);
                                inferFromIndexTypes(source, target, 0 /* String */, 1 /* Number */);
                                depth--;
                            }
                        }
                    }
                    function inferFromProperties(source, target) {
                        var properties = getPropertiesOfObjectType(target);
                        for (var _i = 0; _i < properties.length; _i++) {
                            var targetProp = properties[_i];
                            var sourceProp = getPropertyOfObjectType(source, targetProp.name);
                            if (sourceProp) {
                                inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
                            }
                        }
                    }
                    function inferFromSignatures(source, target, kind) {
                        var sourceSignatures = getSignaturesOfType(source, kind);
                        var targetSignatures = getSignaturesOfType(target, kind);
                        var sourceLen = sourceSignatures.length;
                        var targetLen = targetSignatures.length;
                        var len = sourceLen < targetLen ? sourceLen : targetLen;
                        for (var i = 0; i < len; i++) {
                            inferFromSignature(getErasedSignature(sourceSignatures[sourceLen - len + i]), getErasedSignature(targetSignatures[targetLen - len + i]));
                        }
                    }
                    function inferFromSignature(source, target) {
                        forEachMatchingParameterType(source, target, inferFromTypes);
                        inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
                    }
                    function inferFromIndexTypes(source, target, sourceKind, targetKind) {
                        var targetIndexType = getIndexTypeOfType(target, targetKind);
                        if (targetIndexType) {
                            var sourceIndexType = getIndexTypeOfType(source, sourceKind);
                            if (sourceIndexType) {
                                inferFromTypes(sourceIndexType, targetIndexType);
                            }
                        }
                    }
                }
                function getInferenceCandidates(context, index) {
                    var inferences = context.inferences[index];
                    return inferences.primary || inferences.secondary || emptyArray;
                }
                function getInferredType(context, index) {
                    var inferredType = context.inferredTypes[index];
                    var inferenceSucceeded;
                    if (!inferredType) {
                        var inferences = getInferenceCandidates(context, index);
                        if (inferences.length) {
                            // Infer widened union or supertype, or the unknown type for no common supertype
                            var unionOrSuperType = context.inferUnionTypes ? getUnionType(inferences) : getCommonSupertype(inferences);
                            inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType;
                            inferenceSucceeded = !!unionOrSuperType;
                        }
                        else {
                            // Infer the empty object type when no inferences were made. It is important to remember that
                            // in this case, inference still succeeds, meaning there is no error for not having inference
                            // candidates. An inference error only occurs when there are *conflicting* candidates, i.e.
                            // candidates with no common supertype.
                            inferredType = emptyObjectType;
                            inferenceSucceeded = true;
                        }
                        // Only do the constraint check if inference succeeded (to prevent cascading errors)
                        if (inferenceSucceeded) {
                            var constraint = getConstraintOfTypeParameter(context.typeParameters[index]);
                            inferredType = constraint && !isTypeAssignableTo(inferredType, constraint) ? constraint : inferredType;
                        }
                        else if (context.failedTypeParameterIndex === undefined || context.failedTypeParameterIndex > index) {
                            // If inference failed, it is necessary to record the index of the failed type parameter (the one we are on).
                            // It might be that inference has already failed on a later type parameter on a previous call to inferTypeArguments.
                            // So if this failure is on preceding type parameter, this type parameter is the new failure index.
                            context.failedTypeParameterIndex = index;
                        }
                        context.inferredTypes[index] = inferredType;
                    }
                    return inferredType;
                }
                function getInferredTypes(context) {
                    for (var i = 0; i < context.inferredTypes.length; i++) {
                        getInferredType(context, i);
                    }
                    return context.inferredTypes;
                }
                function hasAncestor(node, kind) {
                    return ts.getAncestor(node, kind) !== undefined;
                }
                // EXPRESSION TYPE CHECKING
                function getResolvedSymbol(node) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedSymbol) {
                        links.resolvedSymbol = (!ts.nodeIsMissing(node) && resolveName(node, node.text, 107455 /* Value */ | 1048576 /* ExportValue */, ts.Diagnostics.Cannot_find_name_0, node)) || unknownSymbol;
                    }
                    return links.resolvedSymbol;
                }
                function isInTypeQuery(node) {
                    // TypeScript 1.0 spec (April 2014): 3.6.3
                    // A type query consists of the keyword typeof followed by an expression.
                    // The expression is restricted to a single identifier or a sequence of identifiers separated by periods
                    while (node) {
                        switch (node.kind) {
                            case 144 /* TypeQuery */:
                                return true;
                            case 65 /* Identifier */:
                            case 126 /* QualifiedName */:
                                node = node.parent;
                                continue;
                            default:
                                return false;
                        }
                    }
                    ts.Debug.fail("should not get here");
                }
                // For a union type, remove all constituent types that are of the given type kind (when isOfTypeKind is true)
                // or not of the given type kind (when isOfTypeKind is false)
                function removeTypesFromUnionType(type, typeKind, isOfTypeKind, allowEmptyUnionResult) {
                    if (type.flags & 16384 /* Union */) {
                        var types = type.types;
                        if (ts.forEach(types, function (t) { return !!(t.flags & typeKind) === isOfTypeKind; })) {
                            // Above we checked if we have anything to remove, now use the opposite test to do the removal
                            var narrowedType = getUnionType(ts.filter(types, function (t) { return !(t.flags & typeKind) === isOfTypeKind; }));
                            if (allowEmptyUnionResult || narrowedType !== emptyObjectType) {
                                return narrowedType;
                            }
                        }
                    }
                    else if (allowEmptyUnionResult && !!(type.flags & typeKind) === isOfTypeKind) {
                        // Use getUnionType(emptyArray) instead of emptyObjectType in case the way empty union types
                        // are represented ever changes.
                        return getUnionType(emptyArray);
                    }
                    return type;
                }
                function hasInitializer(node) {
                    return !!(node.initializer || ts.isBindingPattern(node.parent) && hasInitializer(node.parent.parent));
                }
                // Check if a given variable is assigned within a given syntax node
                function isVariableAssignedWithin(symbol, node) {
                    var links = getNodeLinks(node);
                    if (links.assignmentChecks) {
                        var cachedResult = links.assignmentChecks[symbol.id];
                        if (cachedResult !== undefined) {
                            return cachedResult;
                        }
                    }
                    else {
                        links.assignmentChecks = {};
                    }
                    return links.assignmentChecks[symbol.id] = isAssignedIn(node);
                    function isAssignedInBinaryExpression(node) {
                        if (node.operatorToken.kind >= 53 /* FirstAssignment */ && node.operatorToken.kind <= 64 /* LastAssignment */) {
                            var n = node.left;
                            while (n.kind === 161 /* ParenthesizedExpression */) {
                                n = n.expression;
                            }
                            if (n.kind === 65 /* Identifier */ && getResolvedSymbol(n) === symbol) {
                                return true;
                            }
                        }
                        return ts.forEachChild(node, isAssignedIn);
                    }
                    function isAssignedInVariableDeclaration(node) {
                        if (!ts.isBindingPattern(node.name) && getSymbolOfNode(node) === symbol && hasInitializer(node)) {
                            return true;
                        }
                        return ts.forEachChild(node, isAssignedIn);
                    }
                    function isAssignedIn(node) {
                        switch (node.kind) {
                            case 169 /* BinaryExpression */:
                                return isAssignedInBinaryExpression(node);
                            case 198 /* VariableDeclaration */:
                            case 152 /* BindingElement */:
                                return isAssignedInVariableDeclaration(node);
                            case 150 /* ObjectBindingPattern */:
                            case 151 /* ArrayBindingPattern */:
                            case 153 /* ArrayLiteralExpression */:
                            case 154 /* ObjectLiteralExpression */:
                            case 155 /* PropertyAccessExpression */:
                            case 156 /* ElementAccessExpression */:
                            case 157 /* CallExpression */:
                            case 158 /* NewExpression */:
                            case 160 /* TypeAssertionExpression */:
                            case 161 /* ParenthesizedExpression */:
                            case 167 /* PrefixUnaryExpression */:
                            case 164 /* DeleteExpression */:
                            case 165 /* TypeOfExpression */:
                            case 166 /* VoidExpression */:
                            case 168 /* PostfixUnaryExpression */:
                            case 170 /* ConditionalExpression */:
                            case 173 /* SpreadElementExpression */:
                            case 179 /* Block */:
                            case 180 /* VariableStatement */:
                            case 182 /* ExpressionStatement */:
                            case 183 /* IfStatement */:
                            case 184 /* DoStatement */:
                            case 185 /* WhileStatement */:
                            case 186 /* ForStatement */:
                            case 187 /* ForInStatement */:
                            case 188 /* ForOfStatement */:
                            case 191 /* ReturnStatement */:
                            case 192 /* WithStatement */:
                            case 193 /* SwitchStatement */:
                            case 220 /* CaseClause */:
                            case 221 /* DefaultClause */:
                            case 194 /* LabeledStatement */:
                            case 195 /* ThrowStatement */:
                            case 196 /* TryStatement */:
                            case 223 /* CatchClause */:
                                return ts.forEachChild(node, isAssignedIn);
                        }
                        return false;
                    }
                }
                function resolveLocation(node) {
                    // Resolve location from top down towards node if it is a context sensitive expression
                    // That helps in making sure not assigning types as any when resolved out of order
                    var containerNodes = [];
                    for (var parent_3 = node.parent; parent_3; parent_3 = parent_3.parent) {
                        if ((ts.isExpression(parent_3) || ts.isObjectLiteralMethod(node)) &&
                            isContextSensitive(parent_3)) {
                            containerNodes.unshift(parent_3);
                        }
                    }
                    ts.forEach(containerNodes, function (node) { getTypeOfNode(node); });
                }
                function getSymbolAtLocation(node) {
                    resolveLocation(node);
                    return getSymbolInfo(node);
                }
                function getTypeAtLocation(node) {
                    resolveLocation(node);
                    return getTypeOfNode(node);
                }
                function getTypeOfSymbolAtLocation(symbol, node) {
                    resolveLocation(node);
                    // Get the narrowed type of symbol at given location instead of just getting
                    // the type of the symbol.
                    // eg.
                    // function foo(a: string | number) {
                    //     if (typeof a === "string") {
                    //         a/**/
                    //     }
                    // }
                    // getTypeOfSymbol for a would return type of parameter symbol string | number
                    // Unless we provide location /**/, checker wouldn't know how to narrow the type
                    // By using getNarrowedTypeOfSymbol would return string since it would be able to narrow
                    // it by typeguard in the if true condition
                    return getNarrowedTypeOfSymbol(symbol, node);
                }
                // Get the narrowed type of a given symbol at a given location
                function getNarrowedTypeOfSymbol(symbol, node) {
                    var type = getTypeOfSymbol(symbol);
                    // Only narrow when symbol is variable of type any or an object, union, or type parameter type
                    if (node && symbol.flags & 3 /* Variable */ && type.flags & (1 /* Any */ | 48128 /* ObjectType */ | 16384 /* Union */ | 512 /* TypeParameter */)) {
                        loop: while (node.parent) {
                            var child = node;
                            node = node.parent;
                            var narrowedType = type;
                            switch (node.kind) {
                                case 183 /* IfStatement */:
                                    // In a branch of an if statement, narrow based on controlling expression
                                    if (child !== node.expression) {
                                        narrowedType = narrowType(type, node.expression, child === node.thenStatement);
                                    }
                                    break;
                                case 170 /* ConditionalExpression */:
                                    // In a branch of a conditional expression, narrow based on controlling condition
                                    if (child !== node.condition) {
                                        narrowedType = narrowType(type, node.condition, child === node.whenTrue);
                                    }
                                    break;
                                case 169 /* BinaryExpression */:
                                    // In the right operand of an && or ||, narrow based on left operand
                                    if (child === node.right) {
                                        if (node.operatorToken.kind === 48 /* AmpersandAmpersandToken */) {
                                            narrowedType = narrowType(type, node.left, true);
                                        }
                                        else if (node.operatorToken.kind === 49 /* BarBarToken */) {
                                            narrowedType = narrowType(type, node.left, false);
                                        }
                                    }
                                    break;
                                case 227 /* SourceFile */:
                                case 205 /* ModuleDeclaration */:
                                case 200 /* FunctionDeclaration */:
                                case 134 /* MethodDeclaration */:
                                case 133 /* MethodSignature */:
                                case 136 /* GetAccessor */:
                                case 137 /* SetAccessor */:
                                case 135 /* Constructor */:
                                    // Stop at the first containing function or module declaration
                                    break loop;
                            }
                            // Use narrowed type if construct contains no assignments to variable
                            if (narrowedType !== type) {
                                if (isVariableAssignedWithin(symbol, node)) {
                                    break;
                                }
                                type = narrowedType;
                            }
                        }
                    }
                    return type;
                    function narrowTypeByEquality(type, expr, assumeTrue) {
                        // Check that we have 'typeof <symbol>' on the left and string literal on the right
                        if (expr.left.kind !== 165 /* TypeOfExpression */ || expr.right.kind !== 8 /* StringLiteral */) {
                            return type;
                        }
                        var left = expr.left;
                        var right = expr.right;
                        if (left.expression.kind !== 65 /* Identifier */ || getResolvedSymbol(left.expression) !== symbol) {
                            return type;
                        }
                        var typeInfo = primitiveTypeInfo[right.text];
                        if (expr.operatorToken.kind === 31 /* ExclamationEqualsEqualsToken */) {
                            assumeTrue = !assumeTrue;
                        }
                        if (assumeTrue) {
                            // Assumed result is true. If check was not for a primitive type, remove all primitive types
                            if (!typeInfo) {
                                return removeTypesFromUnionType(type, 258 /* StringLike */ | 132 /* NumberLike */ | 8 /* Boolean */ | 1048576 /* ESSymbol */, 
                                /*isOfTypeKind*/ true, false);
                            }
                            // Check was for a primitive type, return that primitive type if it is a subtype
                            if (isTypeSubtypeOf(typeInfo.type, type)) {
                                return typeInfo.type;
                            }
                            // Otherwise, remove all types that aren't of the primitive type kind. This can happen when the type is
                            // union of enum types and other types.
                            return removeTypesFromUnionType(type, typeInfo.flags, false, false);
                        }
                        else {
                            // Assumed result is false. If check was for a primitive type, remove that primitive type
                            if (typeInfo) {
                                return removeTypesFromUnionType(type, typeInfo.flags, true, false);
                            }
                            // Otherwise we don't have enough information to do anything.
                            return type;
                        }
                    }
                    function narrowTypeByAnd(type, expr, assumeTrue) {
                        if (assumeTrue) {
                            // The assumed result is true, therefore we narrow assuming each operand to be true.
                            return narrowType(narrowType(type, expr.left, true), expr.right, true);
                        }
                        else {
                            // The assumed result is false. This means either the first operand was false, or the first operand was true
                            // and the second operand was false. We narrow with those assumptions and union the two resulting types.
                            return getUnionType([
                                narrowType(type, expr.left, false),
                                narrowType(narrowType(type, expr.left, true), expr.right, false)
                            ]);
                        }
                    }
                    function narrowTypeByOr(type, expr, assumeTrue) {
                        if (assumeTrue) {
                            // The assumed result is true. This means either the first operand was true, or the first operand was false
                            // and the second operand was true. We narrow with those assumptions and union the two resulting types.
                            return getUnionType([
                                narrowType(type, expr.left, true),
                                narrowType(narrowType(type, expr.left, false), expr.right, true)
                            ]);
                        }
                        else {
                            // The assumed result is false, therefore we narrow assuming each operand to be false.
                            return narrowType(narrowType(type, expr.left, false), expr.right, false);
                        }
                    }
                    function narrowTypeByInstanceof(type, expr, assumeTrue) {
                        // Check that type is not any, assumed result is true, and we have variable symbol on the left
                        if (type.flags & 1 /* Any */ || !assumeTrue || expr.left.kind !== 65 /* Identifier */ || getResolvedSymbol(expr.left) !== symbol) {
                            return type;
                        }
                        // Check that right operand is a function type with a prototype property
                        var rightType = checkExpression(expr.right);
                        if (!isTypeSubtypeOf(rightType, globalFunctionType)) {
                            return type;
                        }
                        // Target type is type of prototype property
                        var prototypeProperty = getPropertyOfType(rightType, "prototype");
                        if (!prototypeProperty) {
                            return type;
                        }
                        var targetType = getTypeOfSymbol(prototypeProperty);
                        // Narrow to target type if it is a subtype of current type
                        if (isTypeSubtypeOf(targetType, type)) {
                            return targetType;
                        }
                        // If current type is a union type, remove all constituents that aren't subtypes of target type
                        if (type.flags & 16384 /* Union */) {
                            return getUnionType(ts.filter(type.types, function (t) { return isTypeSubtypeOf(t, targetType); }));
                        }
                        return type;
                    }
                    // Narrow the given type based on the given expression having the assumed boolean value. The returned type
                    // will be a subtype or the same type as the argument.
                    function narrowType(type, expr, assumeTrue) {
                        switch (expr.kind) {
                            case 161 /* ParenthesizedExpression */:
                                return narrowType(type, expr.expression, assumeTrue);
                            case 169 /* BinaryExpression */:
                                var operator = expr.operatorToken.kind;
                                if (operator === 30 /* EqualsEqualsEqualsToken */ || operator === 31 /* ExclamationEqualsEqualsToken */) {
                                    return narrowTypeByEquality(type, expr, assumeTrue);
                                }
                                else if (operator === 48 /* AmpersandAmpersandToken */) {
                                    return narrowTypeByAnd(type, expr, assumeTrue);
                                }
                                else if (operator === 49 /* BarBarToken */) {
                                    return narrowTypeByOr(type, expr, assumeTrue);
                                }
                                else if (operator === 87 /* InstanceOfKeyword */) {
                                    return narrowTypeByInstanceof(type, expr, assumeTrue);
                                }
                                break;
                            case 167 /* PrefixUnaryExpression */:
                                if (expr.operator === 46 /* ExclamationToken */) {
                                    return narrowType(type, expr.operand, !assumeTrue);
                                }
                                break;
                        }
                        return type;
                    }
                }
                function checkIdentifier(node) {
                    var symbol = getResolvedSymbol(node);
                    // As noted in ECMAScript 6 language spec, arrow functions never have an arguments objects.
                    // Although in down-level emit of arrow function, we emit it using function expression which means that
                    // arguments objects will be bound to the inner object; emitting arrow function natively in ES6, arguments objects
                    // will be bound to non-arrow function that contain this arrow function. This results in inconsistent behavior.
                    // To avoid that we will give an error to users if they use arguments objects in arrow function so that they
                    // can explicitly bound arguments objects
                    if (symbol === argumentsSymbol && ts.getContainingFunction(node).kind === 163 /* ArrowFunction */ && languageVersion < 2 /* ES6 */) {
                        error(node, ts.Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression);
                    }
                    if (symbol.flags & 8388608 /* Alias */ && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) {
                        markAliasSymbolAsReferenced(symbol);
                    }
                    checkCollisionWithCapturedSuperVariable(node, node);
                    checkCollisionWithCapturedThisVariable(node, node);
                    checkBlockScopedBindingCapturedInLoop(node, symbol);
                    return getNarrowedTypeOfSymbol(getExportSymbolOfValueSymbolIfExported(symbol), node);
                }
                function isInsideFunction(node, threshold) {
                    var current = node;
                    while (current && current !== threshold) {
                        if (ts.isFunctionLike(current)) {
                            return true;
                        }
                        current = current.parent;
                    }
                    return false;
                }
                function checkBlockScopedBindingCapturedInLoop(node, symbol) {
                    if (languageVersion >= 2 /* ES6 */ ||
                        (symbol.flags & 2 /* BlockScopedVariable */) === 0 ||
                        symbol.valueDeclaration.parent.kind === 223 /* CatchClause */) {
                        return;
                    }
                    // - check if binding is used in some function
                    // (stop the walk when reaching container of binding declaration)
                    // - if first check succeeded - check if variable is declared inside the loop
                    // nesting structure:
                    // (variable declaration or binding element) -> variable declaration list -> container
                    var container = symbol.valueDeclaration;
                    while (container.kind !== 199 /* VariableDeclarationList */) {
                        container = container.parent;
                    }
                    // get the parent of variable declaration list
                    container = container.parent;
                    if (container.kind === 180 /* VariableStatement */) {
                        // if parent is variable statement - get its parent
                        container = container.parent;
                    }
                    var inFunction = isInsideFunction(node.parent, container);
                    var current = container;
                    while (current && !ts.nodeStartsNewLexicalEnvironment(current)) {
                        if (isIterationStatement(current, false)) {
                            if (inFunction) {
                                grammarErrorOnFirstToken(current, ts.Diagnostics.Loop_contains_block_scoped_variable_0_referenced_by_a_function_in_the_loop_This_is_only_supported_in_ECMAScript_6_or_higher, ts.declarationNameToString(node));
                            }
                            // mark value declaration so during emit they can have a special handling
                            getNodeLinks(symbol.valueDeclaration).flags |= 256 /* BlockScopedBindingInLoop */;
                            break;
                        }
                        current = current.parent;
                    }
                }
                function captureLexicalThis(node, container) {
                    var classNode = container.parent && container.parent.kind === 201 /* ClassDeclaration */ ? container.parent : undefined;
                    getNodeLinks(node).flags |= 2 /* LexicalThis */;
                    if (container.kind === 132 /* PropertyDeclaration */ || container.kind === 135 /* Constructor */) {
                        getNodeLinks(classNode).flags |= 4 /* CaptureThis */;
                    }
                    else {
                        getNodeLinks(container).flags |= 4 /* CaptureThis */;
                    }
                }
                function checkThisExpression(node) {
                    // Stop at the first arrow function so that we can
                    // tell whether 'this' needs to be captured.
                    var container = ts.getThisContainer(node, true);
                    var needToCaptureLexicalThis = false;
                    // Now skip arrow functions to get the "real" owner of 'this'.
                    if (container.kind === 163 /* ArrowFunction */) {
                        container = ts.getThisContainer(container, false);
                        // When targeting es6, arrow function lexically bind "this" so we do not need to do the work of binding "this" in emitted code
                        needToCaptureLexicalThis = (languageVersion < 2 /* ES6 */);
                    }
                    switch (container.kind) {
                        case 205 /* ModuleDeclaration */:
                            error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_module_body);
                            // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks
                            break;
                        case 204 /* EnumDeclaration */:
                            error(node, ts.Diagnostics.this_cannot_be_referenced_in_current_location);
                            // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks
                            break;
                        case 135 /* Constructor */:
                            if (isInConstructorArgumentInitializer(node, container)) {
                                error(node, ts.Diagnostics.this_cannot_be_referenced_in_constructor_arguments);
                            }
                            break;
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                            if (container.flags & 128 /* Static */) {
                                error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_static_property_initializer);
                            }
                            break;
                        case 127 /* ComputedPropertyName */:
                            error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_computed_property_name);
                            break;
                    }
                    if (needToCaptureLexicalThis) {
                        captureLexicalThis(node, container);
                    }
                    var classNode = container.parent && container.parent.kind === 201 /* ClassDeclaration */ ? container.parent : undefined;
                    if (classNode) {
                        var symbol = getSymbolOfNode(classNode);
                        return container.flags & 128 /* Static */ ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol);
                    }
                    return anyType;
                }
                function isInConstructorArgumentInitializer(node, constructorDecl) {
                    for (var n = node; n && n !== constructorDecl; n = n.parent) {
                        if (n.kind === 129 /* Parameter */) {
                            return true;
                        }
                    }
                    return false;
                }
                function checkSuperExpression(node) {
                    var isCallExpression = node.parent.kind === 157 /* CallExpression */ && node.parent.expression === node;
                    var enclosingClass = ts.getAncestor(node, 201 /* ClassDeclaration */);
                    var baseClass;
                    if (enclosingClass && ts.getClassExtendsHeritageClauseElement(enclosingClass)) {
                        var classType = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClass));
                        var baseTypes = getBaseTypes(classType);
                        baseClass = baseTypes.length && baseTypes[0];
                    }
                    if (!baseClass) {
                        error(node, ts.Diagnostics.super_can_only_be_referenced_in_a_derived_class);
                        return unknownType;
                    }
                    var container = ts.getSuperContainer(node, true);
                    if (container) {
                        var canUseSuperExpression = false;
                        var needToCaptureLexicalThis;
                        if (isCallExpression) {
                            // TS 1.0 SPEC (April 2014): 4.8.1
                            // Super calls are only permitted in constructors of derived classes
                            canUseSuperExpression = container.kind === 135 /* Constructor */;
                        }
                        else {
                            // TS 1.0 SPEC (April 2014)
                            // 'super' property access is allowed
                            // - In a constructor, instance member function, instance member accessor, or instance member variable initializer where this references a derived class instance
                            // - In a static member function or static member accessor
                            // super property access might appear in arrow functions with arbitrary deep nesting
                            needToCaptureLexicalThis = false;
                            while (container && container.kind === 163 /* ArrowFunction */) {
                                container = ts.getSuperContainer(container, true);
                                needToCaptureLexicalThis = languageVersion < 2 /* ES6 */;
                            }
                            // topmost container must be something that is directly nested in the class declaration
                            if (container && container.parent && container.parent.kind === 201 /* ClassDeclaration */) {
                                if (container.flags & 128 /* Static */) {
                                    canUseSuperExpression =
                                        container.kind === 134 /* MethodDeclaration */ ||
                                            container.kind === 133 /* MethodSignature */ ||
                                            container.kind === 136 /* GetAccessor */ ||
                                            container.kind === 137 /* SetAccessor */;
                                }
                                else {
                                    canUseSuperExpression =
                                        container.kind === 134 /* MethodDeclaration */ ||
                                            container.kind === 133 /* MethodSignature */ ||
                                            container.kind === 136 /* GetAccessor */ ||
                                            container.kind === 137 /* SetAccessor */ ||
                                            container.kind === 132 /* PropertyDeclaration */ ||
                                            container.kind === 131 /* PropertySignature */ ||
                                            container.kind === 135 /* Constructor */;
                                }
                            }
                        }
                        if (canUseSuperExpression) {
                            var returnType;
                            if ((container.flags & 128 /* Static */) || isCallExpression) {
                                getNodeLinks(node).flags |= 32 /* SuperStatic */;
                                returnType = getTypeOfSymbol(baseClass.symbol);
                            }
                            else {
                                getNodeLinks(node).flags |= 16 /* SuperInstance */;
                                returnType = baseClass;
                            }
                            if (container.kind === 135 /* Constructor */ && isInConstructorArgumentInitializer(node, container)) {
                                // issue custom error message for super property access in constructor arguments (to be aligned with old compiler)
                                error(node, ts.Diagnostics.super_cannot_be_referenced_in_constructor_arguments);
                                returnType = unknownType;
                            }
                            if (!isCallExpression && needToCaptureLexicalThis) {
                                // call expressions are allowed only in constructors so they should always capture correct 'this'
                                // super property access expressions can also appear in arrow functions -
                                // in this case they should also use correct lexical this
                                captureLexicalThis(node.parent, container);
                            }
                            return returnType;
                        }
                    }
                    if (container && container.kind === 127 /* ComputedPropertyName */) {
                        error(node, ts.Diagnostics.super_cannot_be_referenced_in_a_computed_property_name);
                    }
                    else if (isCallExpression) {
                        error(node, ts.Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors);
                    }
                    else {
                        error(node, ts.Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class);
                    }
                    return unknownType;
                }
                // Return contextual type of parameter or undefined if no contextual type is available
                function getContextuallyTypedParameterType(parameter) {
                    if (isFunctionExpressionOrArrowFunction(parameter.parent)) {
                        var func = parameter.parent;
                        if (isContextSensitive(func)) {
                            var contextualSignature = getContextualSignature(func);
                            if (contextualSignature) {
                                var funcHasRestParameters = ts.hasRestParameters(func);
                                var len = func.parameters.length - (funcHasRestParameters ? 1 : 0);
                                var indexOfParameter = ts.indexOf(func.parameters, parameter);
                                if (indexOfParameter < len) {
                                    return getTypeAtPosition(contextualSignature, indexOfParameter);
                                }
                                // If last parameter is contextually rest parameter get its type
                                if (indexOfParameter === (func.parameters.length - 1) &&
                                    funcHasRestParameters && contextualSignature.hasRestParameter && func.parameters.length >= contextualSignature.parameters.length) {
                                    return getTypeOfSymbol(contextualSignature.parameters[contextualSignature.parameters.length - 1]);
                                }
                            }
                        }
                    }
                    return undefined;
                }
                // In a variable, parameter or property declaration with a type annotation, the contextual type of an initializer
                // expression is the type of the variable, parameter or property. Otherwise, in a parameter declaration of a
                // contextually typed function expression, the contextual type of an initializer expression is the contextual type
                // of the parameter. Otherwise, in a variable or parameter declaration with a binding pattern name, the contextual
                // type of an initializer expression is the type implied by the binding pattern.
                function getContextualTypeForInitializerExpression(node) {
                    var declaration = node.parent;
                    if (node === declaration.initializer) {
                        if (declaration.type) {
                            return getTypeFromTypeNode(declaration.type);
                        }
                        if (declaration.kind === 129 /* Parameter */) {
                            var type = getContextuallyTypedParameterType(declaration);
                            if (type) {
                                return type;
                            }
                        }
                        if (ts.isBindingPattern(declaration.name)) {
                            return getTypeFromBindingPattern(declaration.name);
                        }
                    }
                    return undefined;
                }
                function getContextualTypeForReturnExpression(node) {
                    var func = ts.getContainingFunction(node);
                    if (func) {
                        // If the containing function has a return type annotation, is a constructor, or is a get accessor whose
                        // corresponding set accessor has a type annotation, return statements in the function are contextually typed
                        if (func.type || func.kind === 135 /* Constructor */ || func.kind === 136 /* GetAccessor */ && getSetAccessorTypeAnnotationNode(ts.getDeclarationOfKind(func.symbol, 137 /* SetAccessor */))) {
                            return getReturnTypeOfSignature(getSignatureFromDeclaration(func));
                        }
                        // Otherwise, if the containing function is contextually typed by a function type with exactly one call signature
                        // and that call signature is non-generic, return statements are contextually typed by the return type of the signature
                        var signature = getContextualSignatureForFunctionLikeDeclaration(func);
                        if (signature) {
                            return getReturnTypeOfSignature(signature);
                        }
                    }
                    return undefined;
                }
                // In a typed function call, an argument or substitution expression is contextually typed by the type of the corresponding parameter.
                function getContextualTypeForArgument(callTarget, arg) {
                    var args = getEffectiveCallArguments(callTarget);
                    var argIndex = ts.indexOf(args, arg);
                    if (argIndex >= 0) {
                        var signature = getResolvedSignature(callTarget);
                        return getTypeAtPosition(signature, argIndex);
                    }
                    return undefined;
                }
                function getContextualTypeForSubstitutionExpression(template, substitutionExpression) {
                    if (template.parent.kind === 159 /* TaggedTemplateExpression */) {
                        return getContextualTypeForArgument(template.parent, substitutionExpression);
                    }
                    return undefined;
                }
                function getContextualTypeForBinaryOperand(node) {
                    var binaryExpression = node.parent;
                    var operator = binaryExpression.operatorToken.kind;
                    if (operator >= 53 /* FirstAssignment */ && operator <= 64 /* LastAssignment */) {
                        // In an assignment expression, the right operand is contextually typed by the type of the left operand.
                        if (node === binaryExpression.right) {
                            return checkExpression(binaryExpression.left);
                        }
                    }
                    else if (operator === 49 /* BarBarToken */) {
                        // When an || expression has a contextual type, the operands are contextually typed by that type. When an ||
                        // expression has no contextual type, the right operand is contextually typed by the type of the left operand.
                        var type = getContextualType(binaryExpression);
                        if (!type && node === binaryExpression.right) {
                            type = checkExpression(binaryExpression.left);
                        }
                        return type;
                    }
                    return undefined;
                }
                // Apply a mapping function to a contextual type and return the resulting type. If the contextual type
                // is a union type, the mapping function is applied to each constituent type and a union of the resulting
                // types is returned.
                function applyToContextualType(type, mapper) {
                    if (!(type.flags & 16384 /* Union */)) {
                        return mapper(type);
                    }
                    var types = type.types;
                    var mappedType;
                    var mappedTypes;
                    for (var _i = 0; _i < types.length; _i++) {
                        var current = types[_i];
                        var t = mapper(current);
                        if (t) {
                            if (!mappedType) {
                                mappedType = t;
                            }
                            else if (!mappedTypes) {
                                mappedTypes = [mappedType, t];
                            }
                            else {
                                mappedTypes.push(t);
                            }
                        }
                    }
                    return mappedTypes ? getUnionType(mappedTypes) : mappedType;
                }
                function getTypeOfPropertyOfContextualType(type, name) {
                    return applyToContextualType(type, function (t) {
                        var prop = getPropertyOfObjectType(t, name);
                        return prop ? getTypeOfSymbol(prop) : undefined;
                    });
                }
                function getIndexTypeOfContextualType(type, kind) {
                    return applyToContextualType(type, function (t) { return getIndexTypeOfObjectOrUnionType(t, kind); });
                }
                // Return true if the given contextual type is a tuple-like type
                function contextualTypeIsTupleLikeType(type) {
                    return !!(type.flags & 16384 /* Union */ ? ts.forEach(type.types, isTupleLikeType) : isTupleLikeType(type));
                }
                // Return true if the given contextual type provides an index signature of the given kind
                function contextualTypeHasIndexSignature(type, kind) {
                    return !!(type.flags & 16384 /* Union */ ? ts.forEach(type.types, function (t) { return getIndexTypeOfObjectOrUnionType(t, kind); }) : getIndexTypeOfObjectOrUnionType(type, kind));
                }
                // In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of
                // the matching property in T, if one exists. Otherwise, it is the type of the numeric index signature in T, if one
                // exists. Otherwise, it is the type of the string index signature in T, if one exists.
                function getContextualTypeForObjectLiteralMethod(node) {
                    ts.Debug.assert(ts.isObjectLiteralMethod(node));
                    if (isInsideWithStatementBody(node)) {
                        // We cannot answer semantic questions within a with block, do not proceed any further
                        return undefined;
                    }
                    return getContextualTypeForObjectLiteralElement(node);
                }
                function getContextualTypeForObjectLiteralElement(element) {
                    var objectLiteral = element.parent;
                    var type = getContextualType(objectLiteral);
                    if (type) {
                        if (!ts.hasDynamicName(element)) {
                            // For a (non-symbol) computed property, there is no reason to look up the name
                            // in the type. It will just be "__computed", which does not appear in any
                            // SymbolTable.
                            var symbolName = getSymbolOfNode(element).name;
                            var propertyType = getTypeOfPropertyOfContextualType(type, symbolName);
                            if (propertyType) {
                                return propertyType;
                            }
                        }
                        return isNumericName(element.name) && getIndexTypeOfContextualType(type, 1 /* Number */) ||
                            getIndexTypeOfContextualType(type, 0 /* String */);
                    }
                    return undefined;
                }
                // In an array literal contextually typed by a type T, the contextual type of an element expression at index N is
                // the type of the property with the numeric name N in T, if one exists. Otherwise, if T has a numeric index signature,
                // it is the type of the numeric index signature in T. Otherwise, in ES6 and higher, the contextual type is the iterated
                // type of T.
                function getContextualTypeForElementExpression(node) {
                    var arrayLiteral = node.parent;
                    var type = getContextualType(arrayLiteral);
                    if (type) {
                        var index = ts.indexOf(arrayLiteral.elements, node);
                        return getTypeOfPropertyOfContextualType(type, "" + index)
                            || getIndexTypeOfContextualType(type, 1 /* Number */)
                            || (languageVersion >= 2 /* ES6 */ ? checkIteratedType(type, undefined) : undefined);
                    }
                    return undefined;
                }
                // In a contextually typed conditional expression, the true/false expressions are contextually typed by the same type.
                function getContextualTypeForConditionalOperand(node) {
                    var conditional = node.parent;
                    return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined;
                }
                // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily
                // be "pushed" onto a node using the contextualType property.
                function getContextualType(node) {
                    if (isInsideWithStatementBody(node)) {
                        // We cannot answer semantic questions within a with block, do not proceed any further
                        return undefined;
                    }
                    if (node.contextualType) {
                        return node.contextualType;
                    }
                    var parent = node.parent;
                    switch (parent.kind) {
                        case 198 /* VariableDeclaration */:
                        case 129 /* Parameter */:
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                        case 152 /* BindingElement */:
                            return getContextualTypeForInitializerExpression(node);
                        case 163 /* ArrowFunction */:
                        case 191 /* ReturnStatement */:
                            return getContextualTypeForReturnExpression(node);
                        case 157 /* CallExpression */:
                        case 158 /* NewExpression */:
                            return getContextualTypeForArgument(parent, node);
                        case 160 /* TypeAssertionExpression */:
                            return getTypeFromTypeNode(parent.type);
                        case 169 /* BinaryExpression */:
                            return getContextualTypeForBinaryOperand(node);
                        case 224 /* PropertyAssignment */:
                            return getContextualTypeForObjectLiteralElement(parent);
                        case 153 /* ArrayLiteralExpression */:
                            return getContextualTypeForElementExpression(node);
                        case 170 /* ConditionalExpression */:
                            return getContextualTypeForConditionalOperand(node);
                        case 176 /* TemplateSpan */:
                            ts.Debug.assert(parent.parent.kind === 171 /* TemplateExpression */);
                            return getContextualTypeForSubstitutionExpression(parent.parent, node);
                        case 161 /* ParenthesizedExpression */:
                            return getContextualType(parent);
                    }
                    return undefined;
                }
                // If the given type is an object or union type, if that type has a single signature, and if
                // that signature is non-generic, return the signature. Otherwise return undefined.
                function getNonGenericSignature(type) {
                    var signatures = getSignaturesOfObjectOrUnionType(type, 0 /* Call */);
                    if (signatures.length === 1) {
                        var signature = signatures[0];
                        if (!signature.typeParameters) {
                            return signature;
                        }
                    }
                }
                function isFunctionExpressionOrArrowFunction(node) {
                    return node.kind === 162 /* FunctionExpression */ || node.kind === 163 /* ArrowFunction */;
                }
                function getContextualSignatureForFunctionLikeDeclaration(node) {
                    // Only function expressions and arrow functions are contextually typed.
                    return isFunctionExpressionOrArrowFunction(node) ? getContextualSignature(node) : undefined;
                }
                // Return the contextual signature for a given expression node. A contextual type provides a
                // contextual signature if it has a single call signature and if that call signature is non-generic.
                // If the contextual type is a union type, get the signature from each type possible and if they are
                // all identical ignoring their return type, the result is same signature but with return type as
                // union type of return types from these signatures
                function getContextualSignature(node) {
                    ts.Debug.assert(node.kind !== 134 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node));
                    var type = ts.isObjectLiteralMethod(node)
                        ? getContextualTypeForObjectLiteralMethod(node)
                        : getContextualType(node);
                    if (!type) {
                        return undefined;
                    }
                    if (!(type.flags & 16384 /* Union */)) {
                        return getNonGenericSignature(type);
                    }
                    var signatureList;
                    var types = type.types;
                    for (var _i = 0; _i < types.length; _i++) {
                        var current = types[_i];
                        // The signature set of all constituent type with call signatures should match
                        // So number of signatures allowed is either 0 or 1
                        if (signatureList &&
                            getSignaturesOfObjectOrUnionType(current, 0 /* Call */).length > 1) {
                            return undefined;
                        }
                        var signature = getNonGenericSignature(current);
                        if (signature) {
                            if (!signatureList) {
                                // This signature will contribute to contextual union signature
                                signatureList = [signature];
                            }
                            else if (!compareSignatures(signatureList[0], signature, false, compareTypes)) {
                                // Signatures aren't identical, do not use
                                return undefined;
                            }
                            else {
                                // Use this signature for contextual union signature
                                signatureList.push(signature);
                            }
                        }
                    }
                    // Result is union of signatures collected (return type is union of return types of this signature set)
                    var result;
                    if (signatureList) {
                        result = cloneSignature(signatureList[0]);
                        // Clear resolved return type we possibly got from cloneSignature
                        result.resolvedReturnType = undefined;
                        result.unionSignatures = signatureList;
                    }
                    return result;
                }
                // Presence of a contextual type mapper indicates inferential typing, except the identityMapper object is
                // used as a special marker for other purposes.
                function isInferentialContext(mapper) {
                    return mapper && mapper !== identityMapper;
                }
                // A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property
                // assignment in an object literal that is an assignment target, or if it is parented by an array literal that is
                // an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ p: a}] = xxx'.
                function isAssignmentTarget(node) {
                    var parent = node.parent;
                    if (parent.kind === 169 /* BinaryExpression */ && parent.operatorToken.kind === 53 /* EqualsToken */ && parent.left === node) {
                        return true;
                    }
                    if (parent.kind === 224 /* PropertyAssignment */) {
                        return isAssignmentTarget(parent.parent);
                    }
                    if (parent.kind === 153 /* ArrayLiteralExpression */) {
                        return isAssignmentTarget(parent);
                    }
                    return false;
                }
                function checkSpreadElementExpression(node, contextualMapper) {
                    // It is usually not safe to call checkExpressionCached if we can be contextually typing.
                    // You can tell that we are contextually typing because of the contextualMapper parameter.
                    // While it is true that a spread element can have a contextual type, it does not do anything
                    // with this type. It is neither affected by it, nor does it propagate it to its operand.
                    // So the fact that contextualMapper is passed is not important, because the operand of a spread
                    // element is not contextually typed.
                    var arrayOrIterableType = checkExpressionCached(node.expression, contextualMapper);
                    return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, false);
                }
                function checkArrayLiteral(node, contextualMapper) {
                    var elements = node.elements;
                    if (!elements.length) {
                        return createArrayType(undefinedType);
                    }
                    var hasSpreadElement = false;
                    var elementTypes = [];
                    var inDestructuringPattern = isAssignmentTarget(node);
                    for (var _i = 0; _i < elements.length; _i++) {
                        var e = elements[_i];
                        if (inDestructuringPattern && e.kind === 173 /* SpreadElementExpression */) {
                            // Given the following situation:
                            //    var c: {};
                            //    [...c] = ["", 0];
                            //
                            // c is represented in the tree as a spread element in an array literal.
                            // But c really functions as a rest element, and its purpose is to provide
                            // a contextual type for the right hand side of the assignment. Therefore,
                            // instead of calling checkExpression on "...c", which will give an error 
                            // if c is not iterable/array-like, we need to act as if we are trying to
                            // get the contextual element type from it. So we do something similar to
                            // getContextualTypeForElementExpression, which will crucially not error
                            // if there is no index type / iterated type.
                            var restArrayType = checkExpression(e.expression, contextualMapper);
                            var restElementType = getIndexTypeOfType(restArrayType, 1 /* Number */) ||
                                (languageVersion >= 2 /* ES6 */ ? checkIteratedType(restArrayType, undefined) : undefined);
                            if (restElementType) {
                                elementTypes.push(restElementType);
                            }
                        }
                        else {
                            var type = checkExpression(e, contextualMapper);
                            elementTypes.push(type);
                        }
                        hasSpreadElement = hasSpreadElement || e.kind === 173 /* SpreadElementExpression */;
                    }
                    if (!hasSpreadElement) {
                        var contextualType = getContextualType(node);
                        if (contextualType && contextualTypeIsTupleLikeType(contextualType) || inDestructuringPattern) {
                            return createTupleType(elementTypes);
                        }
                    }
                    return createArrayType(getUnionType(elementTypes));
                }
                function isNumericName(name) {
                    return name.kind === 127 /* ComputedPropertyName */ ? isNumericComputedName(name) : isNumericLiteralName(name.text);
                }
                function isNumericComputedName(name) {
                    // It seems odd to consider an expression of type Any to result in a numeric name,
                    // but this behavior is consistent with checkIndexedAccess
                    return allConstituentTypesHaveKind(checkComputedPropertyName(name), 1 /* Any */ | 132 /* NumberLike */);
                }
                function isNumericLiteralName(name) {
                    // The intent of numeric names is that
                    //     - they are names with text in a numeric form, and that
                    //     - setting properties/indexing with them is always equivalent to doing so with the numeric literal 'numLit',
                    //         acquired by applying the abstract 'ToNumber' operation on the name's text.
                    //
                    // The subtlety is in the latter portion, as we cannot reliably say that anything that looks like a numeric literal is a numeric name.
                    // In fact, it is the case that the text of the name must be equal to 'ToString(numLit)' for this to hold.
                    //
                    // Consider the property name '"0xF00D"'. When one indexes with '0xF00D', they are actually indexing with the value of 'ToString(0xF00D)'
                    // according to the ECMAScript specification, so it is actually as if the user indexed with the string '"61453"'.
                    // Thus, the text of all numeric literals equivalent to '61543' such as '0xF00D', '0xf00D', '0170015', etc. are not valid numeric names
                    // because their 'ToString' representation is not equal to their original text.
                    // This is motivated by ECMA-262 sections 9.3.1, 9.8.1, 11.1.5, and 11.2.1.
                    //
                    // Here, we test whether 'ToString(ToNumber(name))' is exactly equal to 'name'.
                    // The '+' prefix operator is equivalent here to applying the abstract ToNumber operation.
                    // Applying the 'toString()' method on a number gives us the abstract ToString operation on a number.
                    //
                    // Note that this accepts the values 'Infinity', '-Infinity', and 'NaN', and that this is intentional.
                    // This is desired behavior, because when indexing with them as numeric entities, you are indexing
                    // with the strings '"Infinity"', '"-Infinity"', and '"NaN"' respectively.
                    return (+name).toString() === name;
                }
                function checkComputedPropertyName(node) {
                    var links = getNodeLinks(node.expression);
                    if (!links.resolvedType) {
                        links.resolvedType = checkExpression(node.expression);
                        // This will allow types number, string, symbol or any. It will also allow enums, the unknown
                        // type, and any union of these types (like string | number).
                        if (!allConstituentTypesHaveKind(links.resolvedType, 1 /* Any */ | 132 /* NumberLike */ | 258 /* StringLike */ | 1048576 /* ESSymbol */)) {
                            error(node, ts.Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any);
                        }
                        else {
                            checkThatExpressionIsProperSymbolReference(node.expression, links.resolvedType, true);
                        }
                    }
                    return links.resolvedType;
                }
                function checkObjectLiteral(node, contextualMapper) {
                    // Grammar checking
                    checkGrammarObjectLiteralExpression(node);
                    var propertiesTable = {};
                    var propertiesArray = [];
                    var contextualType = getContextualType(node);
                    var typeFlags;
                    for (var _i = 0, _a = node.properties; _i < _a.length; _i++) {
                        var memberDecl = _a[_i];
                        var member = memberDecl.symbol;
                        if (memberDecl.kind === 224 /* PropertyAssignment */ ||
                            memberDecl.kind === 225 /* ShorthandPropertyAssignment */ ||
                            ts.isObjectLiteralMethod(memberDecl)) {
                            var type = void 0;
                            if (memberDecl.kind === 224 /* PropertyAssignment */) {
                                type = checkPropertyAssignment(memberDecl, contextualMapper);
                            }
                            else if (memberDecl.kind === 134 /* MethodDeclaration */) {
                                type = checkObjectLiteralMethod(memberDecl, contextualMapper);
                            }
                            else {
                                ts.Debug.assert(memberDecl.kind === 225 /* ShorthandPropertyAssignment */);
                                type = checkExpression(memberDecl.name, contextualMapper);
                            }
                            typeFlags |= type.flags;
                            var prop = createSymbol(4 /* Property */ | 67108864 /* Transient */ | member.flags, member.name);
                            prop.declarations = member.declarations;
                            prop.parent = member.parent;
                            if (member.valueDeclaration) {
                                prop.valueDeclaration = member.valueDeclaration;
                            }
                            prop.type = type;
                            prop.target = member;
                            member = prop;
                        }
                        else {
                            // TypeScript 1.0 spec (April 2014)
                            // A get accessor declaration is processed in the same manner as
                            // an ordinary function declaration(section 6.1) with no parameters.
                            // A set accessor declaration is processed in the same manner
                            // as an ordinary function declaration with a single parameter and a Void return type.
                            ts.Debug.assert(memberDecl.kind === 136 /* GetAccessor */ || memberDecl.kind === 137 /* SetAccessor */);
                            checkAccessorDeclaration(memberDecl);
                        }
                        if (!ts.hasDynamicName(memberDecl)) {
                            propertiesTable[member.name] = member;
                        }
                        propertiesArray.push(member);
                    }
                    var stringIndexType = getIndexType(0 /* String */);
                    var numberIndexType = getIndexType(1 /* Number */);
                    var result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType);
                    result.flags |= 131072 /* ObjectLiteral */ | 524288 /* ContainsObjectLiteral */ | (typeFlags & 262144 /* ContainsUndefinedOrNull */);
                    return result;
                    function getIndexType(kind) {
                        if (contextualType && contextualTypeHasIndexSignature(contextualType, kind)) {
                            var propTypes = [];
                            for (var i = 0; i < propertiesArray.length; i++) {
                                var propertyDecl = node.properties[i];
                                if (kind === 0 /* String */ || isNumericName(propertyDecl.name)) {
                                    // Do not call getSymbolOfNode(propertyDecl), as that will get the
                                    // original symbol for the node. We actually want to get the symbol
                                    // created by checkObjectLiteral, since that will be appropriately
                                    // contextually typed and resolved.
                                    var type = getTypeOfSymbol(propertiesArray[i]);
                                    if (!ts.contains(propTypes, type)) {
                                        propTypes.push(type);
                                    }
                                }
                            }
                            var result_1 = propTypes.length ? getUnionType(propTypes) : undefinedType;
                            typeFlags |= result_1.flags;
                            return result_1;
                        }
                        return undefined;
                    }
                }
                // If a symbol is a synthesized symbol with no value declaration, we assume it is a property. Example of this are the synthesized
                // '.prototype' property as well as synthesized tuple index properties.
                function getDeclarationKindFromSymbol(s) {
                    return s.valueDeclaration ? s.valueDeclaration.kind : 132 /* PropertyDeclaration */;
                }
                function getDeclarationFlagsFromSymbol(s) {
                    return s.valueDeclaration ? ts.getCombinedNodeFlags(s.valueDeclaration) : s.flags & 134217728 /* Prototype */ ? 16 /* Public */ | 128 /* Static */ : 0;
                }
                function checkClassPropertyAccess(node, left, type, prop) {
                    var flags = getDeclarationFlagsFromSymbol(prop);
                    // Public properties are always accessible
                    if (!(flags & (32 /* Private */ | 64 /* Protected */))) {
                        return;
                    }
                    // Property is known to be private or protected at this point
                    // Get the declaring and enclosing class instance types
                    var enclosingClassDeclaration = ts.getAncestor(node, 201 /* ClassDeclaration */);
                    var enclosingClass = enclosingClassDeclaration ? getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined;
                    var declaringClass = getDeclaredTypeOfSymbol(prop.parent);
                    // Private property is accessible if declaring and enclosing class are the same
                    if (flags & 32 /* Private */) {
                        if (declaringClass !== enclosingClass) {
                            error(node, ts.Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(declaringClass));
                        }
                        return;
                    }
                    // Property is known to be protected at this point
                    // All protected properties of a supertype are accessible in a super access
                    if (left.kind === 91 /* SuperKeyword */) {
                        return;
                    }
                    // A protected property is accessible in the declaring class and classes derived from it
                    if (!enclosingClass || !hasBaseType(enclosingClass, declaringClass)) {
                        error(node, ts.Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(declaringClass));
                        return;
                    }
                    // No further restrictions for static properties
                    if (flags & 128 /* Static */) {
                        return;
                    }
                    // An instance property must be accessed through an instance of the enclosing class
                    if (!(getTargetType(type).flags & (1024 /* Class */ | 2048 /* Interface */) && hasBaseType(type, enclosingClass))) {
                        error(node, ts.Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass));
                    }
                }
                function checkPropertyAccessExpression(node) {
                    return checkPropertyAccessExpressionOrQualifiedName(node, node.expression, node.name);
                }
                function checkQualifiedName(node) {
                    return checkPropertyAccessExpressionOrQualifiedName(node, node.left, node.right);
                }
                function checkPropertyAccessExpressionOrQualifiedName(node, left, right) {
                    var type = checkExpressionOrQualifiedName(left);
                    if (type === unknownType)
                        return type;
                    if (type !== anyType) {
                        var apparentType = getApparentType(getWidenedType(type));
                        if (apparentType === unknownType) {
                            // handle cases when type is Type parameter with invalid constraint
                            return unknownType;
                        }
                        var prop = getPropertyOfType(apparentType, right.text);
                        if (!prop) {
                            if (right.text) {
                                error(right, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.declarationNameToString(right), typeToString(type));
                            }
                            return unknownType;
                        }
                        getNodeLinks(node).resolvedSymbol = prop;
                        if (prop.parent && prop.parent.flags & 32 /* Class */) {
                            // TS 1.0 spec (April 2014): 4.8.2
                            // - In a constructor, instance member function, instance member accessor, or
                            //   instance member variable initializer where this references a derived class instance,
                            //   a super property access is permitted and must specify a public instance member function of the base class.
                            // - In a static member function or static member accessor
                            //   where this references the constructor function object of a derived class,
                            //   a super property access is permitted and must specify a public static member function of the base class.
                            if (left.kind === 91 /* SuperKeyword */ && getDeclarationKindFromSymbol(prop) !== 134 /* MethodDeclaration */) {
                                error(right, ts.Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword);
                            }
                            else {
                                checkClassPropertyAccess(node, left, type, prop);
                            }
                        }
                        return getTypeOfSymbol(prop);
                    }
                    return anyType;
                }
                function isValidPropertyAccess(node, propertyName) {
                    var left = node.kind === 155 /* PropertyAccessExpression */
                        ? node.expression
                        : node.left;
                    var type = checkExpressionOrQualifiedName(left);
                    if (type !== unknownType && type !== anyType) {
                        var prop = getPropertyOfType(getWidenedType(type), propertyName);
                        if (prop && prop.parent && prop.parent.flags & 32 /* Class */) {
                            if (left.kind === 91 /* SuperKeyword */ && getDeclarationKindFromSymbol(prop) !== 134 /* MethodDeclaration */) {
                                return false;
                            }
                            else {
                                var modificationCount = diagnostics.getModificationCount();
                                checkClassPropertyAccess(node, left, type, prop);
                                return diagnostics.getModificationCount() === modificationCount;
                            }
                        }
                    }
                    return true;
                }
                function checkIndexedAccess(node) {
                    // Grammar checking
                    if (!node.argumentExpression) {
                        var sourceFile = getSourceFile(node);
                        if (node.parent.kind === 158 /* NewExpression */ && node.parent.expression === node) {
                            var start = ts.skipTrivia(sourceFile.text, node.expression.end);
                            var end = node.end;
                            grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead);
                        }
                        else {
                            var start = node.end - "]".length;
                            var end = node.end;
                            grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.Expression_expected);
                        }
                    }
                    // Obtain base constraint such that we can bail out if the constraint is an unknown type
                    var objectType = getApparentType(checkExpression(node.expression));
                    var indexType = node.argumentExpression ? checkExpression(node.argumentExpression) : unknownType;
                    if (objectType === unknownType) {
                        return unknownType;
                    }
                    var isConstEnum = isConstEnumObjectType(objectType);
                    if (isConstEnum &&
                        (!node.argumentExpression || node.argumentExpression.kind !== 8 /* StringLiteral */)) {
                        error(node.argumentExpression, ts.Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal);
                        return unknownType;
                    }
                    // TypeScript 1.0 spec (April 2014): 4.10 Property Access
                    // - If IndexExpr is a string literal or a numeric literal and ObjExpr's apparent type has a property with the name
                    //    given by that literal(converted to its string representation in the case of a numeric literal), the property access is of the type of that property.
                    // - Otherwise, if ObjExpr's apparent type has a numeric index signature and IndexExpr is of type Any, the Number primitive type, or an enum type,
                    //    the property access is of the type of that index signature.
                    // - Otherwise, if ObjExpr's apparent type has a string index signature and IndexExpr is of type Any, the String or Number primitive type, or an enum type,
                    //    the property access is of the type of that index signature.
                    // - Otherwise, if IndexExpr is of type Any, the String or Number primitive type, or an enum type, the property access is of type Any.
                    // See if we can index as a property.
                    if (node.argumentExpression) {
                        var name_6 = getPropertyNameForIndexedAccess(node.argumentExpression, indexType);
                        if (name_6 !== undefined) {
                            var prop = getPropertyOfType(objectType, name_6);
                            if (prop) {
                                getNodeLinks(node).resolvedSymbol = prop;
                                return getTypeOfSymbol(prop);
                            }
                            else if (isConstEnum) {
                                error(node.argumentExpression, ts.Diagnostics.Property_0_does_not_exist_on_const_enum_1, name_6, symbolToString(objectType.symbol));
                                return unknownType;
                            }
                        }
                    }
                    // Check for compatible indexer types.
                    if (allConstituentTypesHaveKind(indexType, 1 /* Any */ | 258 /* StringLike */ | 132 /* NumberLike */ | 1048576 /* ESSymbol */)) {
                        // Try to use a number indexer.
                        if (allConstituentTypesHaveKind(indexType, 1 /* Any */ | 132 /* NumberLike */)) {
                            var numberIndexType = getIndexTypeOfType(objectType, 1 /* Number */);
                            if (numberIndexType) {
                                return numberIndexType;
                            }
                        }
                        // Try to use string indexing.
                        var stringIndexType = getIndexTypeOfType(objectType, 0 /* String */);
                        if (stringIndexType) {
                            return stringIndexType;
                        }
                        // Fall back to any.
                        if (compilerOptions.noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && objectType !== anyType) {
                            error(node, ts.Diagnostics.Index_signature_of_object_type_implicitly_has_an_any_type);
                        }
                        return anyType;
                    }
                    // REVIEW: Users should know the type that was actually used.
                    error(node, ts.Diagnostics.An_index_expression_argument_must_be_of_type_string_number_symbol_or_any);
                    return unknownType;
                }
                /**
                 * If indexArgumentExpression is a string literal or number literal, returns its text.
                 * If indexArgumentExpression is a well known symbol, returns the property name corresponding
                 *    to this symbol, as long as it is a proper symbol reference.
                 * Otherwise, returns undefined.
                 */
                function getPropertyNameForIndexedAccess(indexArgumentExpression, indexArgumentType) {
                    if (indexArgumentExpression.kind === 8 /* StringLiteral */ || indexArgumentExpression.kind === 7 /* NumericLiteral */) {
                        return indexArgumentExpression.text;
                    }
                    if (checkThatExpressionIsProperSymbolReference(indexArgumentExpression, indexArgumentType, false)) {
                        var rightHandSideName = indexArgumentExpression.name.text;
                        return ts.getPropertyNameForKnownSymbolName(rightHandSideName);
                    }
                    return undefined;
                }
                /**
                 * A proper symbol reference requires the following:
                 *   1. The property access denotes a property that exists
                 *   2. The expression is of the form Symbol.<identifier>
                 *   3. The property access is of the primitive type symbol.
                 *   4. Symbol in this context resolves to the global Symbol object
                 */
                function checkThatExpressionIsProperSymbolReference(expression, expressionType, reportError) {
                    if (expressionType === unknownType) {
                        // There is already an error, so no need to report one.
                        return false;
                    }
                    if (!ts.isWellKnownSymbolSyntactically(expression)) {
                        return false;
                    }
                    // Make sure the property type is the primitive symbol type
                    if ((expressionType.flags & 1048576 /* ESSymbol */) === 0) {
                        if (reportError) {
                            error(expression, ts.Diagnostics.A_computed_property_name_of_the_form_0_must_be_of_type_symbol, ts.getTextOfNode(expression));
                        }
                        return false;
                    }
                    // The name is Symbol.<someName>, so make sure Symbol actually resolves to the
                    // global Symbol object
                    var leftHandSide = expression.expression;
                    var leftHandSideSymbol = getResolvedSymbol(leftHandSide);
                    if (!leftHandSideSymbol) {
                        return false;
                    }
                    var globalESSymbol = getGlobalESSymbolConstructorSymbol();
                    if (!globalESSymbol) {
                        // Already errored when we tried to look up the symbol
                        return false;
                    }
                    if (leftHandSideSymbol !== globalESSymbol) {
                        if (reportError) {
                            error(leftHandSide, ts.Diagnostics.Symbol_reference_does_not_refer_to_the_global_Symbol_constructor_object);
                        }
                        return false;
                    }
                    return true;
                }
                function resolveUntypedCall(node) {
                    if (node.kind === 159 /* TaggedTemplateExpression */) {
                        checkExpression(node.template);
                    }
                    else {
                        ts.forEach(node.arguments, function (argument) {
                            checkExpression(argument);
                        });
                    }
                    return anySignature;
                }
                function resolveErrorCall(node) {
                    resolveUntypedCall(node);
                    return unknownSignature;
                }
                // Re-order candidate signatures into the result array. Assumes the result array to be empty.
                // The candidate list orders groups in reverse, but within a group signatures are kept in declaration order
                // A nit here is that we reorder only signatures that belong to the same symbol,
                // so order how inherited signatures are processed is still preserved.
                // interface A { (x: string): void }
                // interface B extends A { (x: 'foo'): string }
                // let b: B;
                // b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void]
                function reorderCandidates(signatures, result) {
                    var lastParent;
                    var lastSymbol;
                    var cutoffIndex = 0;
                    var index;
                    var specializedIndex = -1;
                    var spliceIndex;
                    ts.Debug.assert(!result.length);
                    for (var _i = 0; _i < signatures.length; _i++) {
                        var signature = signatures[_i];
                        var symbol = signature.declaration && getSymbolOfNode(signature.declaration);
                        var parent_4 = signature.declaration && signature.declaration.parent;
                        if (!lastSymbol || symbol === lastSymbol) {
                            if (lastParent && parent_4 === lastParent) {
                                index++;
                            }
                            else {
                                lastParent = parent_4;
                                index = cutoffIndex;
                            }
                        }
                        else {
                            // current declaration belongs to a different symbol
                            // set cutoffIndex so re-orderings in the future won't change result set from 0 to cutoffIndex
                            index = cutoffIndex = result.length;
                            lastParent = parent_4;
                        }
                        lastSymbol = symbol;
                        // specialized signatures always need to be placed before non-specialized signatures regardless
                        // of the cutoff position; see GH#1133
                        if (signature.hasStringLiterals) {
                            specializedIndex++;
                            spliceIndex = specializedIndex;
                            // The cutoff index always needs to be greater than or equal to the specialized signature index
                            // in order to prevent non-specialized signatures from being added before a specialized
                            // signature.
                            cutoffIndex++;
                        }
                        else {
                            spliceIndex = index;
                        }
                        result.splice(spliceIndex, 0, signature);
                    }
                }
                function getSpreadArgumentIndex(args) {
                    for (var i = 0; i < args.length; i++) {
                        if (args[i].kind === 173 /* SpreadElementExpression */) {
                            return i;
                        }
                    }
                    return -1;
                }
                function hasCorrectArity(node, args, signature) {
                    var adjustedArgCount; // Apparent number of arguments we will have in this call
                    var typeArguments; // Type arguments (undefined if none)
                    var callIsIncomplete; // In incomplete call we want to be lenient when we have too few arguments
                    if (node.kind === 159 /* TaggedTemplateExpression */) {
                        var tagExpression = node;
                        // Even if the call is incomplete, we'll have a missing expression as our last argument,
                        // so we can say the count is just the arg list length
                        adjustedArgCount = args.length;
                        typeArguments = undefined;
                        if (tagExpression.template.kind === 171 /* TemplateExpression */) {
                            // If a tagged template expression lacks a tail literal, the call is incomplete.
                            // Specifically, a template only can end in a TemplateTail or a Missing literal.
                            var templateExpression = tagExpression.template;
                            var lastSpan = ts.lastOrUndefined(templateExpression.templateSpans);
                            ts.Debug.assert(lastSpan !== undefined); // we should always have at least one span.
                            callIsIncomplete = ts.nodeIsMissing(lastSpan.literal) || !!lastSpan.literal.isUnterminated;
                        }
                        else {
                            // If the template didn't end in a backtick, or its beginning occurred right prior to EOF,
                            // then this might actually turn out to be a TemplateHead in the future;
                            // so we consider the call to be incomplete.
                            var templateLiteral = tagExpression.template;
                            ts.Debug.assert(templateLiteral.kind === 10 /* NoSubstitutionTemplateLiteral */);
                            callIsIncomplete = !!templateLiteral.isUnterminated;
                        }
                    }
                    else {
                        var callExpression = node;
                        if (!callExpression.arguments) {
                            // This only happens when we have something of the form: 'new C'
                            ts.Debug.assert(callExpression.kind === 158 /* NewExpression */);
                            return signature.minArgumentCount === 0;
                        }
                        // For IDE scenarios we may have an incomplete call, so a trailing comma is tantamount to adding another argument.
                        adjustedArgCount = callExpression.arguments.hasTrailingComma ? args.length + 1 : args.length;
                        // If we are missing the close paren, the call is incomplete.
                        callIsIncomplete = callExpression.arguments.end === callExpression.end;
                        typeArguments = callExpression.typeArguments;
                    }
                    // If the user supplied type arguments, but the number of type arguments does not match
                    // the declared number of type parameters, the call has an incorrect arity.
                    var hasRightNumberOfTypeArgs = !typeArguments ||
                        (signature.typeParameters && typeArguments.length === signature.typeParameters.length);
                    if (!hasRightNumberOfTypeArgs) {
                        return false;
                    }
                    // If spread arguments are present, check that they correspond to a rest parameter. If so, no
                    // further checking is necessary.
                    var spreadArgIndex = getSpreadArgumentIndex(args);
                    if (spreadArgIndex >= 0) {
                        return signature.hasRestParameter && spreadArgIndex >= signature.parameters.length - 1;
                    }
                    // Too many arguments implies incorrect arity.
                    if (!signature.hasRestParameter && adjustedArgCount > signature.parameters.length) {
                        return false;
                    }
                    // If the call is incomplete, we should skip the lower bound check.
                    var hasEnoughArguments = adjustedArgCount >= signature.minArgumentCount;
                    return callIsIncomplete || hasEnoughArguments;
                }
                // If type has a single call signature and no other members, return that signature. Otherwise, return undefined.
                function getSingleCallSignature(type) {
                    if (type.flags & 48128 /* ObjectType */) {
                        var resolved = resolveObjectOrUnionTypeMembers(type);
                        if (resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0 &&
                            resolved.properties.length === 0 && !resolved.stringIndexType && !resolved.numberIndexType) {
                            return resolved.callSignatures[0];
                        }
                    }
                    return undefined;
                }
                // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec)
                function instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper) {
                    var context = createInferenceContext(signature.typeParameters, true);
                    forEachMatchingParameterType(contextualSignature, signature, function (source, target) {
                        // Type parameters from outer context referenced by source type are fixed by instantiation of the source type
                        inferTypes(context, instantiateType(source, contextualMapper), target);
                    });
                    return getSignatureInstantiation(signature, getInferredTypes(context));
                }
                function inferTypeArguments(signature, args, excludeArgument, context) {
                    var typeParameters = signature.typeParameters;
                    var inferenceMapper = createInferenceMapper(context);
                    // Clear out all the inference results from the last time inferTypeArguments was called on this context
                    for (var i = 0; i < typeParameters.length; i++) {
                        // As an optimization, we don't have to clear (and later recompute) inferred types
                        // for type parameters that have already been fixed on the previous call to inferTypeArguments.
                        // It would be just as correct to reset all of them. But then we'd be repeating the same work
                        // for the type parameters that were fixed, namely the work done by getInferredType.
                        if (!context.inferences[i].isFixed) {
                            context.inferredTypes[i] = undefined;
                        }
                    }
                    // On this call to inferTypeArguments, we may get more inferences for certain type parameters that were not
                    // fixed last time. This means that a type parameter that failed inference last time may succeed this time,
                    // or vice versa. Therefore, the failedTypeParameterIndex is useless if it points to an unfixed type parameter,
                    // because it may change. So here we reset it. However, getInferredType will not revisit any type parameters
                    // that were previously fixed. So if a fixed type parameter failed previously, it will fail again because
                    // it will contain the exact same set of inferences. So if we reset the index from a fixed type parameter,
                    // we will lose information that we won't recover this time around.
                    if (context.failedTypeParameterIndex !== undefined && !context.inferences[context.failedTypeParameterIndex].isFixed) {
                        context.failedTypeParameterIndex = undefined;
                    }
                    // We perform two passes over the arguments. In the first pass we infer from all arguments, but use
                    // wildcards for all context sensitive function expressions.
                    for (var i = 0; i < args.length; i++) {
                        var arg = args[i];
                        if (arg.kind !== 175 /* OmittedExpression */) {
                            var paramType = getTypeAtPosition(signature, i);
                            var argType = void 0;
                            if (i === 0 && args[i].parent.kind === 159 /* TaggedTemplateExpression */) {
                                argType = globalTemplateStringsArrayType;
                            }
                            else {
                                // For context sensitive arguments we pass the identityMapper, which is a signal to treat all
                                // context sensitive function expressions as wildcards
                                var mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : inferenceMapper;
                                argType = checkExpressionWithContextualType(arg, paramType, mapper);
                            }
                            inferTypes(context, argType, paramType);
                        }
                    }
                    // In the second pass we visit only context sensitive arguments, and only those that aren't excluded, this
                    // time treating function expressions normally (which may cause previously inferred type arguments to be fixed
                    // as we construct types for contextually typed parameters)
                    if (excludeArgument) {
                        for (var i = 0; i < args.length; i++) {
                            // No need to check for omitted args and template expressions, their exlusion value is always undefined
                            if (excludeArgument[i] === false) {
                                var arg = args[i];
                                var paramType = getTypeAtPosition(signature, i);
                                inferTypes(context, checkExpressionWithContextualType(arg, paramType, inferenceMapper), paramType);
                            }
                        }
                    }
                    getInferredTypes(context);
                }
                function checkTypeArguments(signature, typeArguments, typeArgumentResultTypes, reportErrors) {
                    var typeParameters = signature.typeParameters;
                    var typeArgumentsAreAssignable = true;
                    for (var i = 0; i < typeParameters.length; i++) {
                        var typeArgNode = typeArguments[i];
                        var typeArgument = getTypeFromTypeNode(typeArgNode);
                        // Do not push on this array! It has a preallocated length
                        typeArgumentResultTypes[i] = typeArgument;
                        if (typeArgumentsAreAssignable /* so far */) {
                            var constraint = getConstraintOfTypeParameter(typeParameters[i]);
                            if (constraint) {
                                typeArgumentsAreAssignable = checkTypeAssignableTo(typeArgument, constraint, reportErrors ? typeArgNode : undefined, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
                            }
                        }
                    }
                    return typeArgumentsAreAssignable;
                }
                function checkApplicableSignature(node, args, signature, relation, excludeArgument, reportErrors) {
                    for (var i = 0; i < args.length; i++) {
                        var arg = args[i];
                        if (arg.kind !== 175 /* OmittedExpression */) {
                            // Check spread elements against rest type (from arity check we know spread argument corresponds to a rest parameter)
                            var paramType = getTypeAtPosition(signature, i);
                            // A tagged template expression provides a special first argument, and string literals get string literal types
                            // unless we're reporting errors
                            var argType = i === 0 && node.kind === 159 /* TaggedTemplateExpression */
                                ? globalTemplateStringsArrayType
                                : arg.kind === 8 /* StringLiteral */ && !reportErrors
                                    ? getStringLiteralType(arg)
                                    : checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
                            // Use argument expression as error location when reporting errors
                            if (!checkTypeRelatedTo(argType, paramType, relation, reportErrors ? arg : undefined, ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1)) {
                                return false;
                            }
                        }
                    }
                    return true;
                }
                /**
                 * Returns the effective arguments for an expression that works like a function invocation.
                 *
                 * If 'node' is a CallExpression or a NewExpression, then its argument list is returned.
                 * If 'node' is a TaggedTemplateExpression, a new argument list is constructed from the substitution
                 *    expressions, where the first element of the list is the template for error reporting purposes.
                 */
                function getEffectiveCallArguments(node) {
                    var args;
                    if (node.kind === 159 /* TaggedTemplateExpression */) {
                        var template = node.template;
                        args = [template];
                        if (template.kind === 171 /* TemplateExpression */) {
                            ts.forEach(template.templateSpans, function (span) {
                                args.push(span.expression);
                            });
                        }
                    }
                    else {
                        args = node.arguments || emptyArray;
                    }
                    return args;
                }
                /**
                 * In a 'super' call, type arguments are not provided within the CallExpression node itself.
                 * Instead, they must be fetched from the class declaration's base type node.
                 *
                 * If 'node' is a 'super' call (e.g. super(...), new super(...)), then we attempt to fetch
                 * the type arguments off the containing class's first heritage clause (if one exists). Note that if
                 * type arguments are supplied on the 'super' call, they are ignored (though this is syntactically incorrect).
                 *
                 * In all other cases, the call's explicit type arguments are returned.
                 */
                function getEffectiveTypeArguments(callExpression) {
                    if (callExpression.expression.kind === 91 /* SuperKeyword */) {
                        var containingClass = ts.getAncestor(callExpression, 201 /* ClassDeclaration */);
                        var baseClassTypeNode = containingClass && ts.getClassExtendsHeritageClauseElement(containingClass);
                        return baseClassTypeNode && baseClassTypeNode.typeArguments;
                    }
                    else {
                        // Ordinary case - simple function invocation.
                        return callExpression.typeArguments;
                    }
                }
                function resolveCall(node, signatures, candidatesOutArray) {
                    var isTaggedTemplate = node.kind === 159 /* TaggedTemplateExpression */;
                    var typeArguments;
                    if (!isTaggedTemplate) {
                        typeArguments = getEffectiveTypeArguments(node);
                        // We already perform checking on the type arguments on the class declaration itself.
                        if (node.expression.kind !== 91 /* SuperKeyword */) {
                            ts.forEach(typeArguments, checkSourceElement);
                        }
                    }
                    var candidates = candidatesOutArray || [];
                    // reorderCandidates fills up the candidates array directly
                    reorderCandidates(signatures, candidates);
                    if (!candidates.length) {
                        error(node, ts.Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
                        return resolveErrorCall(node);
                    }
                    var args = getEffectiveCallArguments(node);
                    // The following applies to any value of 'excludeArgument[i]':
                    //    - true:      the argument at 'i' is susceptible to a one-time permanent contextual typing.
                    //    - undefined: the argument at 'i' is *not* susceptible to permanent contextual typing.
                    //    - false:     the argument at 'i' *was* and *has been* permanently contextually typed.
                    //
                    // The idea is that we will perform type argument inference & assignability checking once
                    // without using the susceptible parameters that are functions, and once more for each of those
                    // parameters, contextually typing each as we go along.
                    //
                    // For a tagged template, then the first argument be 'undefined' if necessary
                    // because it represents a TemplateStringsArray.
                    var excludeArgument;
                    for (var i = isTaggedTemplate ? 1 : 0; i < args.length; i++) {
                        if (isContextSensitive(args[i])) {
                            if (!excludeArgument) {
                                excludeArgument = new Array(args.length);
                            }
                            excludeArgument[i] = true;
                        }
                    }
                    // The following variables are captured and modified by calls to chooseOverload.
                    // If overload resolution or type argument inference fails, we want to report the
                    // best error possible. The best error is one which says that an argument was not
                    // assignable to a parameter. This implies that everything else about the overload
                    // was fine. So if there is any overload that is only incorrect because of an
                    // argument, we will report an error on that one.
                    //
                    //     function foo(s: string) {}
                    //     function foo(n: number) {} // Report argument error on this overload
                    //     function foo() {}
                    //     foo(true);
                    //
                    // If none of the overloads even made it that far, there are two possibilities.
                    // There was a problem with type arguments for some overload, in which case
                    // report an error on that. Or none of the overloads even had correct arity,
                    // in which case give an arity error.
                    //
                    //     function foo<T>(x: T, y: T) {} // Report type argument inference error
                    //     function foo() {}
                    //     foo(0, true);
                    //
                    var candidateForArgumentError;
                    var candidateForTypeArgumentError;
                    var resultOfFailedInference;
                    var result;
                    // Section 4.12.1:
                    // if the candidate list contains one or more signatures for which the type of each argument
                    // expression is a subtype of each corresponding parameter type, the return type of the first
                    // of those signatures becomes the return type of the function call.
                    // Otherwise, the return type of the first signature in the candidate list becomes the return
                    // type of the function call.
                    //
                    // Whether the call is an error is determined by assignability of the arguments. The subtype pass
                    // is just important for choosing the best signature. So in the case where there is only one
                    // signature, the subtype pass is useless. So skipping it is an optimization.
                    if (candidates.length > 1) {
                        result = chooseOverload(candidates, subtypeRelation);
                    }
                    if (!result) {
                        // Reinitialize these pointers for round two
                        candidateForArgumentError = undefined;
                        candidateForTypeArgumentError = undefined;
                        resultOfFailedInference = undefined;
                        result = chooseOverload(candidates, assignableRelation);
                    }
                    if (result) {
                        return result;
                    }
                    // No signatures were applicable. Now report errors based on the last applicable signature with
                    // no arguments excluded from assignability checks.
                    // If candidate is undefined, it means that no candidates had a suitable arity. In that case,
                    // skip the checkApplicableSignature check.
                    if (candidateForArgumentError) {
                        // excludeArgument is undefined, in this case also equivalent to [undefined, undefined, ...]
                        // The importance of excludeArgument is to prevent us from typing function expression parameters
                        // in arguments too early. If possible, we'd like to only type them once we know the correct
                        // overload. However, this matters for the case where the call is correct. When the call is
                        // an error, we don't need to exclude any arguments, although it would cause no harm to do so.
                        checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, undefined, true);
                    }
                    else if (candidateForTypeArgumentError) {
                        if (!isTaggedTemplate && node.typeArguments) {
                            checkTypeArguments(candidateForTypeArgumentError, node.typeArguments, [], true);
                        }
                        else {
                            ts.Debug.assert(resultOfFailedInference.failedTypeParameterIndex >= 0);
                            var failedTypeParameter = candidateForTypeArgumentError.typeParameters[resultOfFailedInference.failedTypeParameterIndex];
                            var inferenceCandidates = getInferenceCandidates(resultOfFailedInference, resultOfFailedInference.failedTypeParameterIndex);
                            var diagnosticChainHead = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly, typeToString(failedTypeParameter));
                            reportNoCommonSupertypeError(inferenceCandidates, node.expression || node.tag, diagnosticChainHead);
                        }
                    }
                    else {
                        error(node, ts.Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
                    }
                    // No signature was applicable. We have already reported the errors for the invalid signature.
                    // If this is a type resolution session, e.g. Language Service, try to get better information that anySignature.
                    // Pick the first candidate that matches the arity. This way we can get a contextual type for cases like:
                    //  declare function f(a: { xa: number; xb: number; });
                    //  f({ |
                    if (!produceDiagnostics) {
                        for (var _i = 0; _i < candidates.length; _i++) {
                            var candidate = candidates[_i];
                            if (hasCorrectArity(node, args, candidate)) {
                                return candidate;
                            }
                        }
                    }
                    return resolveErrorCall(node);
                    function chooseOverload(candidates, relation) {
                        for (var _i = 0; _i < candidates.length; _i++) {
                            var originalCandidate = candidates[_i];
                            if (!hasCorrectArity(node, args, originalCandidate)) {
                                continue;
                            }
                            var candidate = void 0;
                            var typeArgumentsAreValid = void 0;
                            var inferenceContext = originalCandidate.typeParameters
                                ? createInferenceContext(originalCandidate.typeParameters, false)
                                : undefined;
                            while (true) {
                                candidate = originalCandidate;
                                if (candidate.typeParameters) {
                                    var typeArgumentTypes = void 0;
                                    if (typeArguments) {
                                        typeArgumentTypes = new Array(candidate.typeParameters.length);
                                        typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, false);
                                    }
                                    else {
                                        inferTypeArguments(candidate, args, excludeArgument, inferenceContext);
                                        typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined;
                                        typeArgumentTypes = inferenceContext.inferredTypes;
                                    }
                                    if (!typeArgumentsAreValid) {
                                        break;
                                    }
                                    candidate = getSignatureInstantiation(candidate, typeArgumentTypes);
                                }
                                if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, false)) {
                                    break;
                                }
                                var index = excludeArgument ? ts.indexOf(excludeArgument, true) : -1;
                                if (index < 0) {
                                    return candidate;
                                }
                                excludeArgument[index] = false;
                            }
                            // A post-mortem of this iteration of the loop. The signature was not applicable,
                            // so we want to track it as a candidate for reporting an error. If the candidate
                            // had no type parameters, or had no issues related to type arguments, we can
                            // report an error based on the arguments. If there was an issue with type
                            // arguments, then we can only report an error based on the type arguments.
                            if (originalCandidate.typeParameters) {
                                var instantiatedCandidate = candidate;
                                if (typeArgumentsAreValid) {
                                    candidateForArgumentError = instantiatedCandidate;
                                }
                                else {
                                    candidateForTypeArgumentError = originalCandidate;
                                    if (!typeArguments) {
                                        resultOfFailedInference = inferenceContext;
                                    }
                                }
                            }
                            else {
                                ts.Debug.assert(originalCandidate === candidate);
                                candidateForArgumentError = originalCandidate;
                            }
                        }
                        return undefined;
                    }
                }
                function resolveCallExpression(node, candidatesOutArray) {
                    if (node.expression.kind === 91 /* SuperKeyword */) {
                        var superType = checkSuperExpression(node.expression);
                        if (superType !== unknownType) {
                            return resolveCall(node, getSignaturesOfType(superType, 1 /* Construct */), candidatesOutArray);
                        }
                        return resolveUntypedCall(node);
                    }
                    var funcType = checkExpression(node.expression);
                    var apparentType = getApparentType(funcType);
                    if (apparentType === unknownType) {
                        // Another error has already been reported
                        return resolveErrorCall(node);
                    }
                    // Technically, this signatures list may be incomplete. We are taking the apparent type,
                    // but we are not including call signatures that may have been added to the Object or
                    // Function interface, since they have none by default. This is a bit of a leap of faith
                    // that the user will not add any.
                    var callSignatures = getSignaturesOfType(apparentType, 0 /* Call */);
                    var constructSignatures = getSignaturesOfType(apparentType, 1 /* Construct */);
                    // TS 1.0 spec: 4.12
                    // If FuncExpr is of type Any, or of an object type that has no call or construct signatures
                    // but is a subtype of the Function interface, the call is an untyped function call. In an
                    // untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual
                    // types are provided for the argument expressions, and the result is always of type Any.
                    // We exclude union types because we may have a union of function types that happen to have
                    // no common signatures.
                    if (funcType === anyType || (!callSignatures.length && !constructSignatures.length && !(funcType.flags & 16384 /* Union */) && isTypeAssignableTo(funcType, globalFunctionType))) {
                        if (node.typeArguments) {
                            error(node, ts.Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
                        }
                        return resolveUntypedCall(node);
                    }
                    // If FuncExpr's apparent type(section 3.8.1) is a function type, the call is a typed function call.
                    // TypeScript employs overload resolution in typed function calls in order to support functions
                    // with multiple call signatures.
                    if (!callSignatures.length) {
                        if (constructSignatures.length) {
                            error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType));
                        }
                        else {
                            error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature);
                        }
                        return resolveErrorCall(node);
                    }
                    return resolveCall(node, callSignatures, candidatesOutArray);
                }
                function resolveNewExpression(node, candidatesOutArray) {
                    if (node.arguments && languageVersion < 2 /* ES6 */) {
                        var spreadIndex = getSpreadArgumentIndex(node.arguments);
                        if (spreadIndex >= 0) {
                            error(node.arguments[spreadIndex], ts.Diagnostics.Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_6_and_higher);
                        }
                    }
                    var expressionType = checkExpression(node.expression);
                    // TS 1.0 spec: 4.11
                    // If ConstructExpr is of type Any, Args can be any argument
                    // list and the result of the operation is of type Any.
                    if (expressionType === anyType) {
                        if (node.typeArguments) {
                            error(node, ts.Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
                        }
                        return resolveUntypedCall(node);
                    }
                    // If ConstructExpr's apparent type(section 3.8.1) is an object type with one or
                    // more construct signatures, the expression is processed in the same manner as a
                    // function call, but using the construct signatures as the initial set of candidate
                    // signatures for overload resolution.The result type of the function call becomes
                    // the result type of the operation.
                    expressionType = getApparentType(expressionType);
                    if (expressionType === unknownType) {
                        // Another error has already been reported
                        return resolveErrorCall(node);
                    }
                    // Technically, this signatures list may be incomplete. We are taking the apparent type,
                    // but we are not including construct signatures that may have been added to the Object or
                    // Function interface, since they have none by default. This is a bit of a leap of faith
                    // that the user will not add any.
                    var constructSignatures = getSignaturesOfType(expressionType, 1 /* Construct */);
                    if (constructSignatures.length) {
                        return resolveCall(node, constructSignatures, candidatesOutArray);
                    }
                    // If ConstructExpr's apparent type is an object type with no construct signatures but
                    // one or more call signatures, the expression is processed as a function call. A compile-time
                    // error occurs if the result of the function call is not Void. The type of the result of the
                    // operation is Any.
                    var callSignatures = getSignaturesOfType(expressionType, 0 /* Call */);
                    if (callSignatures.length) {
                        var signature = resolveCall(node, callSignatures, candidatesOutArray);
                        if (getReturnTypeOfSignature(signature) !== voidType) {
                            error(node, ts.Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
                        }
                        return signature;
                    }
                    error(node, ts.Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature);
                    return resolveErrorCall(node);
                }
                function resolveTaggedTemplateExpression(node, candidatesOutArray) {
                    var tagType = checkExpression(node.tag);
                    var apparentType = getApparentType(tagType);
                    if (apparentType === unknownType) {
                        // Another error has already been reported
                        return resolveErrorCall(node);
                    }
                    var callSignatures = getSignaturesOfType(apparentType, 0 /* Call */);
                    if (tagType === anyType || (!callSignatures.length && !(tagType.flags & 16384 /* Union */) && isTypeAssignableTo(tagType, globalFunctionType))) {
                        return resolveUntypedCall(node);
                    }
                    if (!callSignatures.length) {
                        error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature);
                        return resolveErrorCall(node);
                    }
                    return resolveCall(node, callSignatures, candidatesOutArray);
                }
                // candidatesOutArray is passed by signature help in the language service, and collectCandidates
                // must fill it up with the appropriate candidate signatures
                function getResolvedSignature(node, candidatesOutArray) {
                    var links = getNodeLinks(node);
                    // If getResolvedSignature has already been called, we will have cached the resolvedSignature.
                    // However, it is possible that either candidatesOutArray was not passed in the first time,
                    // or that a different candidatesOutArray was passed in. Therefore, we need to redo the work
                    // to correctly fill the candidatesOutArray.
                    if (!links.resolvedSignature || candidatesOutArray) {
                        links.resolvedSignature = anySignature;
                        if (node.kind === 157 /* CallExpression */) {
                            links.resolvedSignature = resolveCallExpression(node, candidatesOutArray);
                        }
                        else if (node.kind === 158 /* NewExpression */) {
                            links.resolvedSignature = resolveNewExpression(node, candidatesOutArray);
                        }
                        else if (node.kind === 159 /* TaggedTemplateExpression */) {
                            links.resolvedSignature = resolveTaggedTemplateExpression(node, candidatesOutArray);
                        }
                        else {
                            ts.Debug.fail("Branch in 'getResolvedSignature' should be unreachable.");
                        }
                    }
                    return links.resolvedSignature;
                }
                function checkCallExpression(node) {
                    // Grammar checking; stop grammar-checking if checkGrammarTypeArguments return true
                    checkGrammarTypeArguments(node, node.typeArguments) || checkGrammarArguments(node, node.arguments);
                    var signature = getResolvedSignature(node);
                    if (node.expression.kind === 91 /* SuperKeyword */) {
                        return voidType;
                    }
                    if (node.kind === 158 /* NewExpression */) {
                        var declaration = signature.declaration;
                        if (declaration &&
                            declaration.kind !== 135 /* Constructor */ &&
                            declaration.kind !== 139 /* ConstructSignature */ &&
                            declaration.kind !== 143 /* ConstructorType */) {
                            // When resolved signature is a call signature (and not a construct signature) the result type is any
                            if (compilerOptions.noImplicitAny) {
                                error(node, ts.Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type);
                            }
                            return anyType;
                        }
                    }
                    return getReturnTypeOfSignature(signature);
                }
                function checkTaggedTemplateExpression(node) {
                    return getReturnTypeOfSignature(getResolvedSignature(node));
                }
                function checkTypeAssertion(node) {
                    var exprType = checkExpression(node.expression);
                    var targetType = getTypeFromTypeNode(node.type);
                    if (produceDiagnostics && targetType !== unknownType) {
                        var widenedType = getWidenedType(exprType);
                        if (!(isTypeAssignableTo(targetType, widenedType))) {
                            checkTypeAssignableTo(exprType, targetType, node, ts.Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
                        }
                    }
                    return targetType;
                }
                function getTypeAtPosition(signature, pos) {
                    return signature.hasRestParameter ?
                        pos < signature.parameters.length - 1 ? getTypeOfSymbol(signature.parameters[pos]) : getRestTypeOfSignature(signature) :
                        pos < signature.parameters.length ? getTypeOfSymbol(signature.parameters[pos]) : anyType;
                }
                function assignContextualParameterTypes(signature, context, mapper) {
                    var len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
                    for (var i = 0; i < len; i++) {
                        var parameter = signature.parameters[i];
                        var links = getSymbolLinks(parameter);
                        links.type = instantiateType(getTypeAtPosition(context, i), mapper);
                    }
                    if (signature.hasRestParameter && context.hasRestParameter && signature.parameters.length >= context.parameters.length) {
                        var parameter = signature.parameters[signature.parameters.length - 1];
                        var links = getSymbolLinks(parameter);
                        links.type = instantiateType(getTypeOfSymbol(context.parameters[context.parameters.length - 1]), mapper);
                    }
                }
                function getReturnTypeFromBody(func, contextualMapper) {
                    var contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func);
                    if (!func.body) {
                        return unknownType;
                    }
                    var type;
                    if (func.body.kind !== 179 /* Block */) {
                        type = checkExpressionCached(func.body, contextualMapper);
                    }
                    else {
                        // Aggregate the types of expressions within all the return statements.
                        var types = checkAndAggregateReturnExpressionTypes(func.body, contextualMapper);
                        if (types.length === 0) {
                            return voidType;
                        }
                        // When return statements are contextually typed we allow the return type to be a union type. Otherwise we require the
                        // return expressions to have a best common supertype.
                        type = contextualSignature ? getUnionType(types) : getCommonSupertype(types);
                        if (!type) {
                            error(func, ts.Diagnostics.No_best_common_type_exists_among_return_expressions);
                            return unknownType;
                        }
                    }
                    if (!contextualSignature) {
                        reportErrorsFromWidening(func, type);
                    }
                    return getWidenedType(type);
                }
                /// Returns a set of types relating to every return expression relating to a function block.
                function checkAndAggregateReturnExpressionTypes(body, contextualMapper) {
                    var aggregatedTypes = [];
                    ts.forEachReturnStatement(body, function (returnStatement) {
                        var expr = returnStatement.expression;
                        if (expr) {
                            var type = checkExpressionCached(expr, contextualMapper);
                            if (!ts.contains(aggregatedTypes, type)) {
                                aggregatedTypes.push(type);
                            }
                        }
                    });
                    return aggregatedTypes;
                }
                function bodyContainsAReturnStatement(funcBody) {
                    return ts.forEachReturnStatement(funcBody, function (returnStatement) {
                        return true;
                    });
                }
                function bodyContainsSingleThrowStatement(body) {
                    return (body.statements.length === 1) && (body.statements[0].kind === 195 /* ThrowStatement */);
                }
                // TypeScript Specification 1.0 (6.3) - July 2014
                // An explicitly typed function whose return type isn't the Void or the Any type
                // must have at least one return statement somewhere in its body.
                // An exception to this rule is if the function implementation consists of a single 'throw' statement.
                function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(func, returnType) {
                    if (!produceDiagnostics) {
                        return;
                    }
                    // Functions that return 'void' or 'any' don't need any return expressions.
                    if (returnType === voidType || returnType === anyType) {
                        return;
                    }
                    // If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check.
                    if (ts.nodeIsMissing(func.body) || func.body.kind !== 179 /* Block */) {
                        return;
                    }
                    var bodyBlock = func.body;
                    // Ensure the body has at least one return expression.
                    if (bodyContainsAReturnStatement(bodyBlock)) {
                        return;
                    }
                    // If there are no return expressions, then we need to check if
                    // the function body consists solely of a throw statement;
                    // this is to make an exception for unimplemented functions.
                    if (bodyContainsSingleThrowStatement(bodyBlock)) {
                        return;
                    }
                    // This function does not conform to the specification.
                    error(func.type, ts.Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement);
                }
                function checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper) {
                    ts.Debug.assert(node.kind !== 134 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node));
                    // Grammar checking
                    var hasGrammarError = checkGrammarDeclarationNameInStrictMode(node) || checkGrammarFunctionLikeDeclaration(node);
                    if (!hasGrammarError && node.kind === 162 /* FunctionExpression */) {
                        checkGrammarFunctionName(node.name) || checkGrammarForGenerator(node);
                    }
                    // The identityMapper object is used to indicate that function expressions are wildcards
                    if (contextualMapper === identityMapper && isContextSensitive(node)) {
                        return anyFunctionType;
                    }
                    var links = getNodeLinks(node);
                    var type = getTypeOfSymbol(node.symbol);
                    // Check if function expression is contextually typed and assign parameter types if so
                    if (!(links.flags & 64 /* ContextChecked */)) {
                        var contextualSignature = getContextualSignature(node);
                        // If a type check is started at a function expression that is an argument of a function call, obtaining the
                        // contextual type may recursively get back to here during overload resolution of the call. If so, we will have
                        // already assigned contextual types.
                        if (!(links.flags & 64 /* ContextChecked */)) {
                            links.flags |= 64 /* ContextChecked */;
                            if (contextualSignature) {
                                var signature = getSignaturesOfType(type, 0 /* Call */)[0];
                                if (isContextSensitive(node)) {
                                    assignContextualParameterTypes(signature, contextualSignature, contextualMapper || identityMapper);
                                }
                                if (!node.type) {
                                    signature.resolvedReturnType = resolvingType;
                                    var returnType = getReturnTypeFromBody(node, contextualMapper);
                                    if (signature.resolvedReturnType === resolvingType) {
                                        signature.resolvedReturnType = returnType;
                                    }
                                }
                            }
                            checkSignatureDeclaration(node);
                        }
                    }
                    if (produceDiagnostics && node.kind !== 134 /* MethodDeclaration */ && node.kind !== 133 /* MethodSignature */) {
                        checkCollisionWithCapturedSuperVariable(node, node.name);
                        checkCollisionWithCapturedThisVariable(node, node.name);
                    }
                    return type;
                }
                function checkFunctionExpressionOrObjectLiteralMethodBody(node) {
                    ts.Debug.assert(node.kind !== 134 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node));
                    if (node.type && !node.asteriskToken) {
                        checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
                    }
                    if (node.body) {
                        if (node.body.kind === 179 /* Block */) {
                            checkSourceElement(node.body);
                        }
                        else {
                            var exprType = checkExpression(node.body);
                            if (node.type) {
                                checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, undefined);
                            }
                            checkFunctionExpressionBodies(node.body);
                        }
                    }
                }
                function checkArithmeticOperandType(operand, type, diagnostic) {
                    if (!allConstituentTypesHaveKind(type, 1 /* Any */ | 132 /* NumberLike */)) {
                        error(operand, diagnostic);
                        return false;
                    }
                    return true;
                }
                function checkReferenceExpression(n, invalidReferenceMessage, constantVariableMessage) {
                    function findSymbol(n) {
                        var symbol = getNodeLinks(n).resolvedSymbol;
                        // Because we got the symbol from the resolvedSymbol property, it might be of kind
                        // SymbolFlags.ExportValue. In this case it is necessary to get the actual export
                        // symbol, which will have the correct flags set on it.
                        return symbol && getExportSymbolOfValueSymbolIfExported(symbol);
                    }
                    function isReferenceOrErrorExpression(n) {
                        // TypeScript 1.0 spec (April 2014):
                        // Expressions are classified as values or references.
                        // References are the subset of expressions that are permitted as the target of an assignment.
                        // Specifically, references are combinations of identifiers(section 4.3), parentheses(section 4.7),
                        // and property accesses(section 4.10).
                        // All other expression constructs described in this chapter are classified as values.
                        switch (n.kind) {
                            case 65 /* Identifier */: {
                                var symbol = findSymbol(n);
                                // TypeScript 1.0 spec (April 2014): 4.3
                                // An identifier expression that references a variable or parameter is classified as a reference.
                                // An identifier expression that references any other kind of entity is classified as a value(and therefore cannot be the target of an assignment).
                                return !symbol || symbol === unknownSymbol || symbol === argumentsSymbol || (symbol.flags & 3 /* Variable */) !== 0;
                            }
                            case 155 /* PropertyAccessExpression */: {
                                var symbol = findSymbol(n);
                                // TypeScript 1.0 spec (April 2014): 4.10
                                // A property access expression is always classified as a reference.
                                // NOTE (not in spec): assignment to enum members should not be allowed
                                return !symbol || symbol === unknownSymbol || (symbol.flags & ~8 /* EnumMember */) !== 0;
                            }
                            case 156 /* ElementAccessExpression */:
                                //  old compiler doesn't check indexed assess
                                return true;
                            case 161 /* ParenthesizedExpression */:
                                return isReferenceOrErrorExpression(n.expression);
                            default:
                                return false;
                        }
                    }
                    function isConstVariableReference(n) {
                        switch (n.kind) {
                            case 65 /* Identifier */:
                            case 155 /* PropertyAccessExpression */: {
                                var symbol = findSymbol(n);
                                return symbol && (symbol.flags & 3 /* Variable */) !== 0 && (getDeclarationFlagsFromSymbol(symbol) & 8192 /* Const */) !== 0;
                            }
                            case 156 /* ElementAccessExpression */: {
                                var index = n.argumentExpression;
                                var symbol = findSymbol(n.expression);
                                if (symbol && index && index.kind === 8 /* StringLiteral */) {
                                    var name_7 = index.text;
                                    var prop = getPropertyOfType(getTypeOfSymbol(symbol), name_7);
                                    return prop && (prop.flags & 3 /* Variable */) !== 0 && (getDeclarationFlagsFromSymbol(prop) & 8192 /* Const */) !== 0;
                                }
                                return false;
                            }
                            case 161 /* ParenthesizedExpression */:
                                return isConstVariableReference(n.expression);
                            default:
                                return false;
                        }
                    }
                    if (!isReferenceOrErrorExpression(n)) {
                        error(n, invalidReferenceMessage);
                        return false;
                    }
                    if (isConstVariableReference(n)) {
                        error(n, constantVariableMessage);
                        return false;
                    }
                    return true;
                }
                function checkDeleteExpression(node) {
                    // Grammar checking
                    if (node.parserContextFlags & 1 /* StrictMode */ && node.expression.kind === 65 /* Identifier */) {
                        // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its
                        // UnaryExpression is a direct reference to a variable, function argument, or function name
                        grammarErrorOnNode(node.expression, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode);
                    }
                    var operandType = checkExpression(node.expression);
                    return booleanType;
                }
                function checkTypeOfExpression(node) {
                    var operandType = checkExpression(node.expression);
                    return stringType;
                }
                function checkVoidExpression(node) {
                    var operandType = checkExpression(node.expression);
                    return undefinedType;
                }
                function checkPrefixUnaryExpression(node) {
                    // Grammar checking
                    // The identifier eval or arguments may not appear as the LeftHandSideExpression of an
                    // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
                    // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator
                    if ((node.operator === 38 /* PlusPlusToken */ || node.operator === 39 /* MinusMinusToken */)) {
                        checkGrammarEvalOrArgumentsInStrictMode(node, node.operand);
                    }
                    var operandType = checkExpression(node.operand);
                    switch (node.operator) {
                        case 33 /* PlusToken */:
                        case 34 /* MinusToken */:
                        case 47 /* TildeToken */:
                            if (someConstituentTypeHasKind(operandType, 1048576 /* ESSymbol */)) {
                                error(node.operand, ts.Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, ts.tokenToString(node.operator));
                            }
                            return numberType;
                        case 46 /* ExclamationToken */:
                            return booleanType;
                        case 38 /* PlusPlusToken */:
                        case 39 /* MinusMinusToken */:
                            var ok = checkArithmeticOperandType(node.operand, operandType, ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
                            if (ok) {
                                // run check only if former checks succeeded to avoid reporting cascading errors
                                checkReferenceExpression(node.operand, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant);
                            }
                            return numberType;
                    }
                    return unknownType;
                }
                function checkPostfixUnaryExpression(node) {
                    // Grammar checking
                    // The identifier eval or arguments may not appear as the LeftHandSideExpression of an
                    // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
                    // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator.
                    checkGrammarEvalOrArgumentsInStrictMode(node, node.operand);
                    var operandType = checkExpression(node.operand);
                    var ok = checkArithmeticOperandType(node.operand, operandType, ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
                    if (ok) {
                        // run check only if former checks succeeded to avoid reporting cascading errors
                        checkReferenceExpression(node.operand, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant);
                    }
                    return numberType;
                }
                // Just like isTypeOfKind below, except that it returns true if *any* constituent
                // has this kind.
                function someConstituentTypeHasKind(type, kind) {
                    if (type.flags & kind) {
                        return true;
                    }
                    if (type.flags & 16384 /* Union */) {
                        var types = type.types;
                        for (var _i = 0; _i < types.length; _i++) {
                            var current = types[_i];
                            if (current.flags & kind) {
                                return true;
                            }
                        }
                        return false;
                    }
                    return false;
                }
                // Return true if type has the given flags, or is a union type composed of types that all have those flags.
                function allConstituentTypesHaveKind(type, kind) {
                    if (type.flags & kind) {
                        return true;
                    }
                    if (type.flags & 16384 /* Union */) {
                        var types = type.types;
                        for (var _i = 0; _i < types.length; _i++) {
                            var current = types[_i];
                            if (!(current.flags & kind)) {
                                return false;
                            }
                        }
                        return true;
                    }
                    return false;
                }
                function isConstEnumObjectType(type) {
                    return type.flags & (48128 /* ObjectType */ | 32768 /* Anonymous */) && type.symbol && isConstEnumSymbol(type.symbol);
                }
                function isConstEnumSymbol(symbol) {
                    return (symbol.flags & 128 /* ConstEnum */) !== 0;
                }
                function checkInstanceOfExpression(node, leftType, rightType) {
                    // TypeScript 1.0 spec (April 2014): 4.15.4
                    // The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type,
                    // and the right operand to be of type Any or a subtype of the 'Function' interface type.
                    // The result is always of the Boolean primitive type.
                    // NOTE: do not raise error if leftType is unknown as related error was already reported
                    if (allConstituentTypesHaveKind(leftType, 1049086 /* Primitive */)) {
                        error(node.left, ts.Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
                    }
                    // NOTE: do not raise error if right is unknown as related error was already reported
                    if (!(rightType.flags & 1 /* Any */ || isTypeSubtypeOf(rightType, globalFunctionType))) {
                        error(node.right, ts.Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type);
                    }
                    return booleanType;
                }
                function checkInExpression(node, leftType, rightType) {
                    // TypeScript 1.0 spec (April 2014): 4.15.5
                    // The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type,
                    // and the right operand to be of type Any, an object type, or a type parameter type.
                    // The result is always of the Boolean primitive type.
                    if (!allConstituentTypesHaveKind(leftType, 1 /* Any */ | 258 /* StringLike */ | 132 /* NumberLike */ | 1048576 /* ESSymbol */)) {
                        error(node.left, ts.Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol);
                    }
                    if (!allConstituentTypesHaveKind(rightType, 1 /* Any */ | 48128 /* ObjectType */ | 512 /* TypeParameter */)) {
                        error(node.right, ts.Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
                    }
                    return booleanType;
                }
                function checkObjectLiteralAssignment(node, sourceType, contextualMapper) {
                    var properties = node.properties;
                    for (var _i = 0; _i < properties.length; _i++) {
                        var p = properties[_i];
                        if (p.kind === 224 /* PropertyAssignment */ || p.kind === 225 /* ShorthandPropertyAssignment */) {
                            // TODO(andersh): Computed property support
                            var name_8 = p.name;
                            var type = sourceType.flags & 1 /* Any */ ? sourceType :
                                getTypeOfPropertyOfType(sourceType, name_8.text) ||
                                    isNumericLiteralName(name_8.text) && getIndexTypeOfType(sourceType, 1 /* Number */) ||
                                    getIndexTypeOfType(sourceType, 0 /* String */);
                            if (type) {
                                checkDestructuringAssignment(p.initializer || name_8, type);
                            }
                            else {
                                error(name_8, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(sourceType), ts.declarationNameToString(name_8));
                            }
                        }
                        else {
                            error(p, ts.Diagnostics.Property_assignment_expected);
                        }
                    }
                    return sourceType;
                }
                function checkArrayLiteralAssignment(node, sourceType, contextualMapper) {
                    // This elementType will be used if the specific property corresponding to this index is not
                    // present (aka the tuple element property). This call also checks that the parentType is in
                    // fact an iterable or array (depending on target language).
                    var elementType = checkIteratedTypeOrElementType(sourceType, node, false) || unknownType;
                    var elements = node.elements;
                    for (var i = 0; i < elements.length; i++) {
                        var e = elements[i];
                        if (e.kind !== 175 /* OmittedExpression */) {
                            if (e.kind !== 173 /* SpreadElementExpression */) {
                                var propName = "" + i;
                                var type = sourceType.flags & 1 /* Any */ ? sourceType :
                                    isTupleLikeType(sourceType)
                                        ? getTypeOfPropertyOfType(sourceType, propName)
                                        : elementType;
                                if (type) {
                                    checkDestructuringAssignment(e, type, contextualMapper);
                                }
                                else {
                                    if (isTupleType(sourceType)) {
                                        error(e, ts.Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), sourceType.elementTypes.length, elements.length);
                                    }
                                    else {
                                        error(e, ts.Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName);
                                    }
                                }
                            }
                            else {
                                if (i < elements.length - 1) {
                                    error(e, ts.Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
                                }
                                else {
                                    var restExpression = e.expression;
                                    if (restExpression.kind === 169 /* BinaryExpression */ && restExpression.operatorToken.kind === 53 /* EqualsToken */) {
                                        error(restExpression.operatorToken, ts.Diagnostics.A_rest_element_cannot_have_an_initializer);
                                    }
                                    else {
                                        checkDestructuringAssignment(restExpression, createArrayType(elementType), contextualMapper);
                                    }
                                }
                            }
                        }
                    }
                    return sourceType;
                }
                function checkDestructuringAssignment(target, sourceType, contextualMapper) {
                    if (target.kind === 169 /* BinaryExpression */ && target.operatorToken.kind === 53 /* EqualsToken */) {
                        checkBinaryExpression(target, contextualMapper);
                        target = target.left;
                    }
                    if (target.kind === 154 /* ObjectLiteralExpression */) {
                        return checkObjectLiteralAssignment(target, sourceType, contextualMapper);
                    }
                    if (target.kind === 153 /* ArrayLiteralExpression */) {
                        return checkArrayLiteralAssignment(target, sourceType, contextualMapper);
                    }
                    return checkReferenceAssignment(target, sourceType, contextualMapper);
                }
                function checkReferenceAssignment(target, sourceType, contextualMapper) {
                    var targetType = checkExpression(target, contextualMapper);
                    if (checkReferenceExpression(target, ts.Diagnostics.Invalid_left_hand_side_of_assignment_expression, ts.Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant)) {
                        checkTypeAssignableTo(sourceType, targetType, target, undefined);
                    }
                    return sourceType;
                }
                function checkBinaryExpression(node, contextualMapper) {
                    // Grammar checking
                    if (ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) {
                        // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an
                        // Assignment operator(11.13) or of a PostfixExpression(11.3)
                        checkGrammarEvalOrArgumentsInStrictMode(node, node.left);
                    }
                    var operator = node.operatorToken.kind;
                    if (operator === 53 /* EqualsToken */ && (node.left.kind === 154 /* ObjectLiteralExpression */ || node.left.kind === 153 /* ArrayLiteralExpression */)) {
                        return checkDestructuringAssignment(node.left, checkExpression(node.right, contextualMapper), contextualMapper);
                    }
                    var leftType = checkExpression(node.left, contextualMapper);
                    var rightType = checkExpression(node.right, contextualMapper);
                    switch (operator) {
                        case 35 /* AsteriskToken */:
                        case 56 /* AsteriskEqualsToken */:
                        case 36 /* SlashToken */:
                        case 57 /* SlashEqualsToken */:
                        case 37 /* PercentToken */:
                        case 58 /* PercentEqualsToken */:
                        case 34 /* MinusToken */:
                        case 55 /* MinusEqualsToken */:
                        case 40 /* LessThanLessThanToken */:
                        case 59 /* LessThanLessThanEqualsToken */:
                        case 41 /* GreaterThanGreaterThanToken */:
                        case 60 /* GreaterThanGreaterThanEqualsToken */:
                        case 42 /* GreaterThanGreaterThanGreaterThanToken */:
                        case 61 /* GreaterThanGreaterThanGreaterThanEqualsToken */:
                        case 44 /* BarToken */:
                        case 63 /* BarEqualsToken */:
                        case 45 /* CaretToken */:
                        case 64 /* CaretEqualsToken */:
                        case 43 /* AmpersandToken */:
                        case 62 /* AmpersandEqualsToken */:
                            // TypeScript 1.0 spec (April 2014): 4.15.1
                            // These operators require their operands to be of type Any, the Number primitive type,
                            // or an enum type. Operands of an enum type are treated
                            // as having the primitive type Number. If one operand is the null or undefined value,
                            // it is treated as having the type of the other operand.
                            // The result is always of the Number primitive type.
                            if (leftType.flags & (32 /* Undefined */ | 64 /* Null */))
                                leftType = rightType;
                            if (rightType.flags & (32 /* Undefined */ | 64 /* Null */))
                                rightType = leftType;
                            var suggestedOperator;
                            // if a user tries to apply a bitwise operator to 2 boolean operands
                            // try and return them a helpful suggestion
                            if ((leftType.flags & 8 /* Boolean */) &&
                                (rightType.flags & 8 /* Boolean */) &&
                                (suggestedOperator = getSuggestedBooleanOperator(node.operatorToken.kind)) !== undefined) {
                                error(node, ts.Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, ts.tokenToString(node.operatorToken.kind), ts.tokenToString(suggestedOperator));
                            }
                            else {
                                // otherwise just check each operand separately and report errors as normal
                                var leftOk = checkArithmeticOperandType(node.left, leftType, ts.Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type);
                                var rightOk = checkArithmeticOperandType(node.right, rightType, ts.Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type);
                                if (leftOk && rightOk) {
                                    checkAssignmentOperator(numberType);
                                }
                            }
                            return numberType;
                        case 33 /* PlusToken */:
                        case 54 /* PlusEqualsToken */:
                            // TypeScript 1.0 spec (April 2014): 4.15.2
                            // The binary + operator requires both operands to be of the Number primitive type or an enum type,
                            // or at least one of the operands to be of type Any or the String primitive type.
                            // If one operand is the null or undefined value, it is treated as having the type of the other operand.
                            if (leftType.flags & (32 /* Undefined */ | 64 /* Null */))
                                leftType = rightType;
                            if (rightType.flags & (32 /* Undefined */ | 64 /* Null */))
                                rightType = leftType;
                            var resultType;
                            if (allConstituentTypesHaveKind(leftType, 132 /* NumberLike */) && allConstituentTypesHaveKind(rightType, 132 /* NumberLike */)) {
                                // Operands of an enum type are treated as having the primitive type Number.
                                // If both operands are of the Number primitive type, the result is of the Number primitive type.
                                resultType = numberType;
                            }
                            else {
                                if (allConstituentTypesHaveKind(leftType, 258 /* StringLike */) || allConstituentTypesHaveKind(rightType, 258 /* StringLike */)) {
                                    // If one or both operands are of the String primitive type, the result is of the String primitive type.
                                    resultType = stringType;
                                }
                                else if (leftType.flags & 1 /* Any */ || rightType.flags & 1 /* Any */) {
                                    // Otherwise, the result is of type Any.
                                    // NOTE: unknown type here denotes error type. Old compiler treated this case as any type so do we.
                                    resultType = anyType;
                                }
                                // Symbols are not allowed at all in arithmetic expressions
                                if (resultType && !checkForDisallowedESSymbolOperand(operator)) {
                                    return resultType;
                                }
                            }
                            if (!resultType) {
                                reportOperatorError();
                                return anyType;
                            }
                            if (operator === 54 /* PlusEqualsToken */) {
                                checkAssignmentOperator(resultType);
                            }
                            return resultType;
                        case 24 /* LessThanToken */:
                        case 25 /* GreaterThanToken */:
                        case 26 /* LessThanEqualsToken */:
                        case 27 /* GreaterThanEqualsToken */:
                            if (!checkForDisallowedESSymbolOperand(operator)) {
                                return booleanType;
                            }
                        // Fall through
                        case 28 /* EqualsEqualsToken */:
                        case 29 /* ExclamationEqualsToken */:
                        case 30 /* EqualsEqualsEqualsToken */:
                        case 31 /* ExclamationEqualsEqualsToken */:
                            if (!isTypeAssignableTo(leftType, rightType) && !isTypeAssignableTo(rightType, leftType)) {
                                reportOperatorError();
                            }
                            return booleanType;
                        case 87 /* InstanceOfKeyword */:
                            return checkInstanceOfExpression(node, leftType, rightType);
                        case 86 /* InKeyword */:
                            return checkInExpression(node, leftType, rightType);
                        case 48 /* AmpersandAmpersandToken */:
                            return rightType;
                        case 49 /* BarBarToken */:
                            return getUnionType([leftType, rightType]);
                        case 53 /* EqualsToken */:
                            checkAssignmentOperator(rightType);
                            return rightType;
                        case 23 /* CommaToken */:
                            return rightType;
                    }
                    // Return true if there was no error, false if there was an error.
                    function checkForDisallowedESSymbolOperand(operator) {
                        var offendingSymbolOperand = someConstituentTypeHasKind(leftType, 1048576 /* ESSymbol */) ? node.left :
                            someConstituentTypeHasKind(rightType, 1048576 /* ESSymbol */) ? node.right :
                                undefined;
                        if (offendingSymbolOperand) {
                            error(offendingSymbolOperand, ts.Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, ts.tokenToString(operator));
                            return false;
                        }
                        return true;
                    }
                    function getSuggestedBooleanOperator(operator) {
                        switch (operator) {
                            case 44 /* BarToken */:
                            case 63 /* BarEqualsToken */:
                                return 49 /* BarBarToken */;
                            case 45 /* CaretToken */:
                            case 64 /* CaretEqualsToken */:
                                return 31 /* ExclamationEqualsEqualsToken */;
                            case 43 /* AmpersandToken */:
                            case 62 /* AmpersandEqualsToken */:
                                return 48 /* AmpersandAmpersandToken */;
                            default:
                                return undefined;
                        }
                    }
                    function checkAssignmentOperator(valueType) {
                        if (produceDiagnostics && operator >= 53 /* FirstAssignment */ && operator <= 64 /* LastAssignment */) {
                            // TypeScript 1.0 spec (April 2014): 4.17
                            // An assignment of the form
                            //    VarExpr = ValueExpr
                            // requires VarExpr to be classified as a reference
                            // A compound assignment furthermore requires VarExpr to be classified as a reference (section 4.1)
                            // and the type of the non - compound operation to be assignable to the type of VarExpr.
                            var ok = checkReferenceExpression(node.left, ts.Diagnostics.Invalid_left_hand_side_of_assignment_expression, ts.Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant);
                            // Use default messages
                            if (ok) {
                                // to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported
                                checkTypeAssignableTo(valueType, leftType, node.left, undefined);
                            }
                        }
                    }
                    function reportOperatorError() {
                        error(node, ts.Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2, ts.tokenToString(node.operatorToken.kind), typeToString(leftType), typeToString(rightType));
                    }
                }
                function checkYieldExpression(node) {
                    // Grammar checking
                    if (!(node.parserContextFlags & 4 /* Yield */)) {
                        grammarErrorOnFirstToken(node, ts.Diagnostics.yield_expression_must_be_contained_within_a_generator_declaration);
                    }
                    else {
                        grammarErrorOnFirstToken(node, ts.Diagnostics.yield_expressions_are_not_currently_supported);
                    }
                }
                function checkConditionalExpression(node, contextualMapper) {
                    checkExpression(node.condition);
                    var type1 = checkExpression(node.whenTrue, contextualMapper);
                    var type2 = checkExpression(node.whenFalse, contextualMapper);
                    return getUnionType([type1, type2]);
                }
                function checkTemplateExpression(node) {
                    // We just want to check each expressions, but we are unconcerned with
                    // the type of each expression, as any value may be coerced into a string.
                    // It is worth asking whether this is what we really want though.
                    // A place where we actually *are* concerned with the expressions' types are
                    // in tagged templates.
                    ts.forEach(node.templateSpans, function (templateSpan) {
                        checkExpression(templateSpan.expression);
                    });
                    return stringType;
                }
                function checkExpressionWithContextualType(node, contextualType, contextualMapper) {
                    var saveContextualType = node.contextualType;
                    node.contextualType = contextualType;
                    var result = checkExpression(node, contextualMapper);
                    node.contextualType = saveContextualType;
                    return result;
                }
                function checkExpressionCached(node, contextualMapper) {
                    var links = getNodeLinks(node);
                    if (!links.resolvedType) {
                        links.resolvedType = checkExpression(node, contextualMapper);
                    }
                    return links.resolvedType;
                }
                function checkPropertyAssignment(node, contextualMapper) {
                    // Do not use hasDynamicName here, because that returns false for well known symbols.
                    // We want to perform checkComputedPropertyName for all computed properties, including
                    // well known symbols.
                    if (node.name.kind === 127 /* ComputedPropertyName */) {
                        checkComputedPropertyName(node.name);
                    }
                    return checkExpression(node.initializer, contextualMapper);
                }
                function checkObjectLiteralMethod(node, contextualMapper) {
                    // Grammar checking
                    checkGrammarMethod(node);
                    // Do not use hasDynamicName here, because that returns false for well known symbols.
                    // We want to perform checkComputedPropertyName for all computed properties, including
                    // well known symbols.
                    if (node.name.kind === 127 /* ComputedPropertyName */) {
                        checkComputedPropertyName(node.name);
                    }
                    var uninstantiatedType = checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper);
                    return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, contextualMapper);
                }
                function instantiateTypeWithSingleGenericCallSignature(node, type, contextualMapper) {
                    if (contextualMapper && contextualMapper !== identityMapper) {
                        var signature = getSingleCallSignature(type);
                        if (signature && signature.typeParameters) {
                            var contextualType = getContextualType(node);
                            if (contextualType) {
                                var contextualSignature = getSingleCallSignature(contextualType);
                                if (contextualSignature && !contextualSignature.typeParameters) {
                                    return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper));
                                }
                            }
                        }
                    }
                    return type;
                }
                function checkExpression(node, contextualMapper) {
                    checkGrammarIdentifierInStrictMode(node);
                    return checkExpressionOrQualifiedName(node, contextualMapper);
                }
                // Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When
                // contextualMapper is not undefined and not equal to the identityMapper function object it indicates that the
                // expression is being inferentially typed (section 4.12.2 in spec) and provides the type mapper to use in
                // conjunction with the generic contextual type. When contextualMapper is equal to the identityMapper function
                // object, it serves as an indicator that all contained function and arrow expressions should be considered to
                // have the wildcard function type; this form of type check is used during overload resolution to exclude
                // contextually typed function and arrow expressions in the initial phase.
                function checkExpressionOrQualifiedName(node, contextualMapper) {
                    var type;
                    if (node.kind == 126 /* QualifiedName */) {
                        type = checkQualifiedName(node);
                    }
                    else {
                        var uninstantiatedType = checkExpressionWorker(node, contextualMapper);
                        type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, contextualMapper);
                    }
                    if (isConstEnumObjectType(type)) {
                        // enum object type for const enums are only permitted in:
                        // - 'left' in property access
                        // - 'object' in indexed access
                        // - target in rhs of import statement
                        var ok = (node.parent.kind === 155 /* PropertyAccessExpression */ && node.parent.expression === node) ||
                            (node.parent.kind === 156 /* ElementAccessExpression */ && node.parent.expression === node) ||
                            ((node.kind === 65 /* Identifier */ || node.kind === 126 /* QualifiedName */) && isInRightSideOfImportOrExportAssignment(node));
                        if (!ok) {
                            error(node, ts.Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment);
                        }
                    }
                    return type;
                }
                function checkNumericLiteral(node) {
                    // Grammar checking
                    checkGrammarNumericLiteral(node);
                    return numberType;
                }
                function checkExpressionWorker(node, contextualMapper) {
                    switch (node.kind) {
                        case 65 /* Identifier */:
                            return checkIdentifier(node);
                        case 93 /* ThisKeyword */:
                            return checkThisExpression(node);
                        case 91 /* SuperKeyword */:
                            return checkSuperExpression(node);
                        case 89 /* NullKeyword */:
                            return nullType;
                        case 95 /* TrueKeyword */:
                        case 80 /* FalseKeyword */:
                            return booleanType;
                        case 7 /* NumericLiteral */:
                            return checkNumericLiteral(node);
                        case 171 /* TemplateExpression */:
                            return checkTemplateExpression(node);
                        case 8 /* StringLiteral */:
                        case 10 /* NoSubstitutionTemplateLiteral */:
                            return stringType;
                        case 9 /* RegularExpressionLiteral */:
                            return globalRegExpType;
                        case 153 /* ArrayLiteralExpression */:
                            return checkArrayLiteral(node, contextualMapper);
                        case 154 /* ObjectLiteralExpression */:
                            return checkObjectLiteral(node, contextualMapper);
                        case 155 /* PropertyAccessExpression */:
                            return checkPropertyAccessExpression(node);
                        case 156 /* ElementAccessExpression */:
                            return checkIndexedAccess(node);
                        case 157 /* CallExpression */:
                        case 158 /* NewExpression */:
                            return checkCallExpression(node);
                        case 159 /* TaggedTemplateExpression */:
                            return checkTaggedTemplateExpression(node);
                        case 160 /* TypeAssertionExpression */:
                            return checkTypeAssertion(node);
                        case 161 /* ParenthesizedExpression */:
                            return checkExpression(node.expression, contextualMapper);
                        case 174 /* ClassExpression */:
                            return checkClassExpression(node);
                        case 162 /* FunctionExpression */:
                        case 163 /* ArrowFunction */:
                            return checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper);
                        case 165 /* TypeOfExpression */:
                            return checkTypeOfExpression(node);
                        case 164 /* DeleteExpression */:
                            return checkDeleteExpression(node);
                        case 166 /* VoidExpression */:
                            return checkVoidExpression(node);
                        case 167 /* PrefixUnaryExpression */:
                            return checkPrefixUnaryExpression(node);
                        case 168 /* PostfixUnaryExpression */:
                            return checkPostfixUnaryExpression(node);
                        case 169 /* BinaryExpression */:
                            return checkBinaryExpression(node, contextualMapper);
                        case 170 /* ConditionalExpression */:
                            return checkConditionalExpression(node, contextualMapper);
                        case 173 /* SpreadElementExpression */:
                            return checkSpreadElementExpression(node, contextualMapper);
                        case 175 /* OmittedExpression */:
                            return undefinedType;
                        case 172 /* YieldExpression */:
                            checkYieldExpression(node);
                            return unknownType;
                    }
                    return unknownType;
                }
                // DECLARATION AND STATEMENT TYPE CHECKING
                function checkTypeParameter(node) {
                    checkGrammarDeclarationNameInStrictMode(node);
                    // Grammar Checking
                    if (node.expression) {
                        grammarErrorOnFirstToken(node.expression, ts.Diagnostics.Type_expected);
                    }
                    checkSourceElement(node.constraint);
                    if (produceDiagnostics) {
                        checkTypeParameterHasIllegalReferencesInConstraint(node);
                        checkTypeNameIsReserved(node.name, ts.Diagnostics.Type_parameter_name_cannot_be_0);
                    }
                    // TODO: Check multiple declarations are identical
                }
                function checkParameter(node) {
                    // Grammar checking
                    // It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the
                    // Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code
                    // or if its FunctionBody is strict code(11.1.5).
                    // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a
                    // strict mode FunctionLikeDeclaration or FunctionExpression(13.1)
                    // Grammar checking
                    checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarEvalOrArgumentsInStrictMode(node, node.name);
                    checkVariableLikeDeclaration(node);
                    var func = ts.getContainingFunction(node);
                    if (node.flags & 112 /* AccessibilityModifier */) {
                        func = ts.getContainingFunction(node);
                        if (!(func.kind === 135 /* Constructor */ && ts.nodeIsPresent(func.body))) {
                            error(node, ts.Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
                        }
                    }
                    if (node.questionToken && ts.isBindingPattern(node.name) && func.body) {
                        error(node, ts.Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature);
                    }
                    // Only check rest parameter type if it's not a binding pattern. Since binding patterns are
                    // not allowed in a rest parameter, we already have an error from checkGrammarParameterList.
                    if (node.dotDotDotToken && !ts.isBindingPattern(node.name) && !isArrayType(getTypeOfSymbol(node.symbol))) {
                        error(node, ts.Diagnostics.A_rest_parameter_must_be_of_an_array_type);
                    }
                }
                function checkSignatureDeclaration(node) {
                    // Grammar checking
                    if (node.kind === 140 /* IndexSignature */) {
                        checkGrammarIndexSignature(node);
                    }
                    else if (node.kind === 142 /* FunctionType */ || node.kind === 200 /* FunctionDeclaration */ || node.kind === 143 /* ConstructorType */ ||
                        node.kind === 138 /* CallSignature */ || node.kind === 135 /* Constructor */ ||
                        node.kind === 139 /* ConstructSignature */) {
                        checkGrammarFunctionLikeDeclaration(node);
                    }
                    checkTypeParameters(node.typeParameters);
                    ts.forEach(node.parameters, checkParameter);
                    if (node.type) {
                        checkSourceElement(node.type);
                    }
                    if (produceDiagnostics) {
                        checkCollisionWithArgumentsInGeneratedCode(node);
                        if (compilerOptions.noImplicitAny && !node.type) {
                            switch (node.kind) {
                                case 139 /* ConstructSignature */:
                                    error(node, ts.Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
                                    break;
                                case 138 /* CallSignature */:
                                    error(node, ts.Diagnostics.Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
                                    break;
                            }
                        }
                    }
                    checkSpecializedSignatureDeclaration(node);
                }
                function checkTypeForDuplicateIndexSignatures(node) {
                    if (node.kind === 202 /* InterfaceDeclaration */) {
                        var nodeSymbol = getSymbolOfNode(node);
                        // in case of merging interface declaration it is possible that we'll enter this check procedure several times for every declaration
                        // to prevent this run check only for the first declaration of a given kind
                        if (nodeSymbol.declarations.length > 0 && nodeSymbol.declarations[0] !== node) {
                            return;
                        }
                    }
                    // TypeScript 1.0 spec (April 2014)
                    // 3.7.4: An object type can contain at most one string index signature and one numeric index signature.
                    // 8.5: A class declaration can have at most one string index member declaration and one numeric index member declaration
                    var indexSymbol = getIndexSymbol(getSymbolOfNode(node));
                    if (indexSymbol) {
                        var seenNumericIndexer = false;
                        var seenStringIndexer = false;
                        for (var _i = 0, _a = indexSymbol.declarations; _i < _a.length; _i++) {
                            var decl = _a[_i];
                            var declaration = decl;
                            if (declaration.parameters.length === 1 && declaration.parameters[0].type) {
                                switch (declaration.parameters[0].type.kind) {
                                    case 121 /* StringKeyword */:
                                        if (!seenStringIndexer) {
                                            seenStringIndexer = true;
                                        }
                                        else {
                                            error(declaration, ts.Diagnostics.Duplicate_string_index_signature);
                                        }
                                        break;
                                    case 119 /* NumberKeyword */:
                                        if (!seenNumericIndexer) {
                                            seenNumericIndexer = true;
                                        }
                                        else {
                                            error(declaration, ts.Diagnostics.Duplicate_number_index_signature);
                                        }
                                        break;
                                }
                            }
                        }
                    }
                }
                function checkPropertyDeclaration(node) {
                    // Grammar checking
                    checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarProperty(node) || checkGrammarComputedPropertyName(node.name);
                    checkVariableLikeDeclaration(node);
                }
                function checkMethodDeclaration(node) {
                    // Grammar checking
                    checkGrammarMethod(node) || checkGrammarComputedPropertyName(node.name);
                    // Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration
                    checkFunctionLikeDeclaration(node);
                }
                function checkConstructorDeclaration(node) {
                    // Grammar check on signature of constructor and modifier of the constructor is done in checkSignatureDeclaration function.
                    checkSignatureDeclaration(node);
                    // Grammar check for checking only related to constructoDeclaration
                    checkGrammarConstructorTypeParameters(node) || checkGrammarConstructorTypeAnnotation(node);
                    checkSourceElement(node.body);
                    var symbol = getSymbolOfNode(node);
                    var firstDeclaration = ts.getDeclarationOfKind(symbol, node.kind);
                    // Only type check the symbol once
                    if (node === firstDeclaration) {
                        checkFunctionOrConstructorSymbol(symbol);
                    }
                    // exit early in the case of signature - super checks are not relevant to them
                    if (ts.nodeIsMissing(node.body)) {
                        return;
                    }
                    if (!produceDiagnostics) {
                        return;
                    }
                    function isSuperCallExpression(n) {
                        return n.kind === 157 /* CallExpression */ && n.expression.kind === 91 /* SuperKeyword */;
                    }
                    function containsSuperCall(n) {
                        if (isSuperCallExpression(n)) {
                            return true;
                        }
                        switch (n.kind) {
                            case 162 /* FunctionExpression */:
                            case 200 /* FunctionDeclaration */:
                            case 163 /* ArrowFunction */:
                            case 154 /* ObjectLiteralExpression */: return false;
                            default: return ts.forEachChild(n, containsSuperCall);
                        }
                    }
                    function markThisReferencesAsErrors(n) {
                        if (n.kind === 93 /* ThisKeyword */) {
                            error(n, ts.Diagnostics.this_cannot_be_referenced_in_current_location);
                        }
                        else if (n.kind !== 162 /* FunctionExpression */ && n.kind !== 200 /* FunctionDeclaration */) {
                            ts.forEachChild(n, markThisReferencesAsErrors);
                        }
                    }
                    function isInstancePropertyWithInitializer(n) {
                        return n.kind === 132 /* PropertyDeclaration */ &&
                            !(n.flags & 128 /* Static */) &&
                            !!n.initializer;
                    }
                    // TS 1.0 spec (April 2014): 8.3.2
                    // Constructors of classes with no extends clause may not contain super calls, whereas
                    // constructors of derived classes must contain at least one super call somewhere in their function body.
                    if (ts.getClassExtendsHeritageClauseElement(node.parent)) {
                        if (containsSuperCall(node.body)) {
                            // The first statement in the body of a constructor must be a super call if both of the following are true:
                            // - The containing class is a derived class.
                            // - The constructor declares parameter properties
                            //   or the containing class declares instance member variables with initializers.
                            var superCallShouldBeFirst = ts.forEach(node.parent.members, isInstancePropertyWithInitializer) ||
                                ts.forEach(node.parameters, function (p) { return p.flags & (16 /* Public */ | 32 /* Private */ | 64 /* Protected */); });
                            if (superCallShouldBeFirst) {
                                var statements = node.body.statements;
                                if (!statements.length || statements[0].kind !== 182 /* ExpressionStatement */ || !isSuperCallExpression(statements[0].expression)) {
                                    error(node, ts.Diagnostics.A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties);
                                }
                                else {
                                    // In such a required super call, it is a compile-time error for argument expressions to reference this.
                                    markThisReferencesAsErrors(statements[0].expression);
                                }
                            }
                        }
                        else {
                            error(node, ts.Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call);
                        }
                    }
                }
                function checkAccessorDeclaration(node) {
                    if (produceDiagnostics) {
                        // Grammar checking accessors
                        checkGrammarFunctionLikeDeclaration(node) || checkGrammarAccessor(node) || checkGrammarComputedPropertyName(node.name);
                        if (node.kind === 136 /* GetAccessor */) {
                            if (!ts.isInAmbientContext(node) && ts.nodeIsPresent(node.body) && !(bodyContainsAReturnStatement(node.body) || bodyContainsSingleThrowStatement(node.body))) {
                                error(node.name, ts.Diagnostics.A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement);
                            }
                        }
                        if (!ts.hasDynamicName(node)) {
                            // TypeScript 1.0 spec (April 2014): 8.4.3
                            // Accessors for the same member name must specify the same accessibility.
                            var otherKind = node.kind === 136 /* GetAccessor */ ? 137 /* SetAccessor */ : 136 /* GetAccessor */;
                            var otherAccessor = ts.getDeclarationOfKind(node.symbol, otherKind);
                            if (otherAccessor) {
                                if (((node.flags & 112 /* AccessibilityModifier */) !== (otherAccessor.flags & 112 /* AccessibilityModifier */))) {
                                    error(node.name, ts.Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility);
                                }
                                var currentAccessorType = getAnnotatedAccessorType(node);
                                var otherAccessorType = getAnnotatedAccessorType(otherAccessor);
                                // TypeScript 1.0 spec (April 2014): 4.5
                                // If both accessors include type annotations, the specified types must be identical.
                                if (currentAccessorType && otherAccessorType) {
                                    if (!isTypeIdenticalTo(currentAccessorType, otherAccessorType)) {
                                        error(node, ts.Diagnostics.get_and_set_accessor_must_have_the_same_type);
                                    }
                                }
                            }
                        }
                        checkAndStoreTypeOfAccessors(getSymbolOfNode(node));
                    }
                    checkFunctionLikeDeclaration(node);
                }
                function checkMissingDeclaration(node) {
                    checkDecorators(node);
                }
                function checkTypeReferenceNode(node) {
                    checkGrammarTypeReferenceInStrictMode(node.typeName);
                    return checkTypeReferenceOrHeritageClauseElement(node);
                }
                function checkHeritageClauseElement(node) {
                    checkGrammarHeritageClauseElementInStrictMode(node.expression);
                    return checkTypeReferenceOrHeritageClauseElement(node);
                }
                function checkTypeReferenceOrHeritageClauseElement(node) {
                    // Grammar checking
                    checkGrammarTypeArguments(node, node.typeArguments);
                    var type = getTypeFromTypeReferenceOrHeritageClauseElement(node);
                    if (type !== unknownType && node.typeArguments) {
                        // Do type argument local checks only if referenced type is successfully resolved
                        var len = node.typeArguments.length;
                        for (var i = 0; i < len; i++) {
                            checkSourceElement(node.typeArguments[i]);
                            var constraint = getConstraintOfTypeParameter(type.target.typeParameters[i]);
                            if (produceDiagnostics && constraint) {
                                var typeArgument = type.typeArguments[i];
                                checkTypeAssignableTo(typeArgument, constraint, node, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
                            }
                        }
                    }
                }
                function checkTypeQuery(node) {
                    getTypeFromTypeQueryNode(node);
                }
                function checkTypeLiteral(node) {
                    ts.forEach(node.members, checkSourceElement);
                    if (produceDiagnostics) {
                        var type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
                        checkIndexConstraints(type);
                        checkTypeForDuplicateIndexSignatures(node);
                    }
                }
                function checkArrayType(node) {
                    checkSourceElement(node.elementType);
                }
                function checkTupleType(node) {
                    // Grammar checking
                    var hasErrorFromDisallowedTrailingComma = checkGrammarForDisallowedTrailingComma(node.elementTypes);
                    if (!hasErrorFromDisallowedTrailingComma && node.elementTypes.length === 0) {
                        grammarErrorOnNode(node, ts.Diagnostics.A_tuple_type_element_list_cannot_be_empty);
                    }
                    ts.forEach(node.elementTypes, checkSourceElement);
                }
                function checkUnionType(node) {
                    ts.forEach(node.types, checkSourceElement);
                }
                function isPrivateWithinAmbient(node) {
                    return (node.flags & 32 /* Private */) && ts.isInAmbientContext(node);
                }
                function checkSpecializedSignatureDeclaration(signatureDeclarationNode) {
                    if (!produceDiagnostics) {
                        return;
                    }
                    var signature = getSignatureFromDeclaration(signatureDeclarationNode);
                    if (!signature.hasStringLiterals) {
                        return;
                    }
                    // TypeScript 1.0 spec (April 2014): 3.7.2.2
                    // Specialized signatures are not permitted in conjunction with a function body
                    if (ts.nodeIsPresent(signatureDeclarationNode.body)) {
                        error(signatureDeclarationNode, ts.Diagnostics.A_signature_with_an_implementation_cannot_use_a_string_literal_type);
                        return;
                    }
                    // TypeScript 1.0 spec (April 2014): 3.7.2.4
                    // Every specialized call or construct signature in an object type must be assignable
                    // to at least one non-specialized call or construct signature in the same object type
                    var signaturesToCheck;
                    // Unnamed (call\construct) signatures in interfaces are inherited and not shadowed so examining just node symbol won't give complete answer.
                    // Use declaring type to obtain full list of signatures.
                    if (!signatureDeclarationNode.name && signatureDeclarationNode.parent && signatureDeclarationNode.parent.kind === 202 /* InterfaceDeclaration */) {
                        ts.Debug.assert(signatureDeclarationNode.kind === 138 /* CallSignature */ || signatureDeclarationNode.kind === 139 /* ConstructSignature */);
                        var signatureKind = signatureDeclarationNode.kind === 138 /* CallSignature */ ? 0 /* Call */ : 1 /* Construct */;
                        var containingSymbol = getSymbolOfNode(signatureDeclarationNode.parent);
                        var containingType = getDeclaredTypeOfSymbol(containingSymbol);
                        signaturesToCheck = getSignaturesOfType(containingType, signatureKind);
                    }
                    else {
                        signaturesToCheck = getSignaturesOfSymbol(getSymbolOfNode(signatureDeclarationNode));
                    }
                    for (var _i = 0; _i < signaturesToCheck.length; _i++) {
                        var otherSignature = signaturesToCheck[_i];
                        if (!otherSignature.hasStringLiterals && isSignatureAssignableTo(signature, otherSignature)) {
                            return;
                        }
                    }
                    error(signatureDeclarationNode, ts.Diagnostics.Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature);
                }
                function getEffectiveDeclarationFlags(n, flagsToCheck) {
                    var flags = ts.getCombinedNodeFlags(n);
                    if (n.parent.kind !== 202 /* InterfaceDeclaration */ && ts.isInAmbientContext(n)) {
                        if (!(flags & 2 /* Ambient */)) {
                            // It is nested in an ambient context, which means it is automatically exported
                            flags |= 1 /* Export */;
                        }
                        flags |= 2 /* Ambient */;
                    }
                    return flags & flagsToCheck;
                }
                function checkFunctionOrConstructorSymbol(symbol) {
                    if (!produceDiagnostics) {
                        return;
                    }
                    function getCanonicalOverload(overloads, implementation) {
                        // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration
                        // Error on all deviations from this canonical set of flags
                        // The caveat is that if some overloads are defined in lib.d.ts, we don't want to
                        // report the errors on those. To achieve this, we will say that the implementation is
                        // the canonical signature only if it is in the same container as the first overload
                        var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent;
                        return implementationSharesContainerWithFirstOverload ? implementation : overloads[0];
                    }
                    function checkFlagAgreementBetweenOverloads(overloads, implementation, flagsToCheck, someOverloadFlags, allOverloadFlags) {
                        // Error if some overloads have a flag that is not shared by all overloads. To find the
                        // deviations, we XOR someOverloadFlags with allOverloadFlags
                        var someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags;
                        if (someButNotAllOverloadFlags !== 0) {
                            var canonicalFlags = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck);
                            ts.forEach(overloads, function (o) {
                                var deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags;
                                if (deviation & 1 /* Export */) {
                                    error(o.name, ts.Diagnostics.Overload_signatures_must_all_be_exported_or_not_exported);
                                }
                                else if (deviation & 2 /* Ambient */) {
                                    error(o.name, ts.Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient);
                                }
                                else if (deviation & (32 /* Private */ | 64 /* Protected */)) {
                                    error(o.name, ts.Diagnostics.Overload_signatures_must_all_be_public_private_or_protected);
                                }
                            });
                        }
                    }
                    function checkQuestionTokenAgreementBetweenOverloads(overloads, implementation, someHaveQuestionToken, allHaveQuestionToken) {
                        if (someHaveQuestionToken !== allHaveQuestionToken) {
                            var canonicalHasQuestionToken = ts.hasQuestionToken(getCanonicalOverload(overloads, implementation));
                            ts.forEach(overloads, function (o) {
                                var deviation = ts.hasQuestionToken(o) !== canonicalHasQuestionToken;
                                if (deviation) {
                                    error(o.name, ts.Diagnostics.Overload_signatures_must_all_be_optional_or_required);
                                }
                            });
                        }
                    }
                    var flagsToCheck = 1 /* Export */ | 2 /* Ambient */ | 32 /* Private */ | 64 /* Protected */;
                    var someNodeFlags = 0;
                    var allNodeFlags = flagsToCheck;
                    var someHaveQuestionToken = false;
                    var allHaveQuestionToken = true;
                    var hasOverloads = false;
                    var bodyDeclaration;
                    var lastSeenNonAmbientDeclaration;
                    var previousDeclaration;
                    var declarations = symbol.declarations;
                    var isConstructor = (symbol.flags & 16384 /* Constructor */) !== 0;
                    function reportImplementationExpectedError(node) {
                        if (node.name && ts.nodeIsMissing(node.name)) {
                            return;
                        }
                        var seen = false;
                        var subsequentNode = ts.forEachChild(node.parent, function (c) {
                            if (seen) {
                                return c;
                            }
                            else {
                                seen = c === node;
                            }
                        });
                        if (subsequentNode) {
                            if (subsequentNode.kind === node.kind) {
                                var errorNode_1 = subsequentNode.name || subsequentNode;
                                // TODO(jfreeman): These are methods, so handle computed name case
                                if (node.name && subsequentNode.name && node.name.text === subsequentNode.name.text) {
                                    // the only situation when this is possible (same kind\same name but different symbol) - mixed static and instance class members
                                    ts.Debug.assert(node.kind === 134 /* MethodDeclaration */ || node.kind === 133 /* MethodSignature */);
                                    ts.Debug.assert((node.flags & 128 /* Static */) !== (subsequentNode.flags & 128 /* Static */));
                                    var diagnostic = node.flags & 128 /* Static */ ? ts.Diagnostics.Function_overload_must_be_static : ts.Diagnostics.Function_overload_must_not_be_static;
                                    error(errorNode_1, diagnostic);
                                    return;
                                }
                                else if (ts.nodeIsPresent(subsequentNode.body)) {
                                    error(errorNode_1, ts.Diagnostics.Function_implementation_name_must_be_0, ts.declarationNameToString(node.name));
                                    return;
                                }
                            }
                        }
                        var errorNode = node.name || node;
                        if (isConstructor) {
                            error(errorNode, ts.Diagnostics.Constructor_implementation_is_missing);
                        }
                        else {
                            error(errorNode, ts.Diagnostics.Function_implementation_is_missing_or_not_immediately_following_the_declaration);
                        }
                    }
                    // when checking exported function declarations across modules check only duplicate implementations
                    // names and consistency of modifiers are verified when we check local symbol
                    var isExportSymbolInsideModule = symbol.parent && symbol.parent.flags & 1536 /* Module */;
                    var duplicateFunctionDeclaration = false;
                    var multipleConstructorImplementation = false;
                    for (var _i = 0; _i < declarations.length; _i++) {
                        var current = declarations[_i];
                        var node = current;
                        var inAmbientContext = ts.isInAmbientContext(node);
                        var inAmbientContextOrInterface = node.parent.kind === 202 /* InterfaceDeclaration */ || node.parent.kind === 145 /* TypeLiteral */ || inAmbientContext;
                        if (inAmbientContextOrInterface) {
                            // check if declarations are consecutive only if they are non-ambient
                            // 1. ambient declarations can be interleaved
                            // i.e. this is legal
                            //     declare function foo();
                            //     declare function bar();
                            //     declare function foo();
                            // 2. mixing ambient and non-ambient declarations is a separate error that will be reported - do not want to report an extra one
                            previousDeclaration = undefined;
                        }
                        if (node.kind === 200 /* FunctionDeclaration */ || node.kind === 134 /* MethodDeclaration */ || node.kind === 133 /* MethodSignature */ || node.kind === 135 /* Constructor */) {
                            var currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck);
                            someNodeFlags |= currentNodeFlags;
                            allNodeFlags &= currentNodeFlags;
                            someHaveQuestionToken = someHaveQuestionToken || ts.hasQuestionToken(node);
                            allHaveQuestionToken = allHaveQuestionToken && ts.hasQuestionToken(node);
                            if (ts.nodeIsPresent(node.body) && bodyDeclaration) {
                                if (isConstructor) {
                                    multipleConstructorImplementation = true;
                                }
                                else {
                                    duplicateFunctionDeclaration = true;
                                }
                            }
                            else if (!isExportSymbolInsideModule && previousDeclaration && previousDeclaration.parent === node.parent && previousDeclaration.end !== node.pos) {
                                reportImplementationExpectedError(previousDeclaration);
                            }
                            if (ts.nodeIsPresent(node.body)) {
                                if (!bodyDeclaration) {
                                    bodyDeclaration = node;
                                }
                            }
                            else {
                                hasOverloads = true;
                            }
                            previousDeclaration = node;
                            if (!inAmbientContextOrInterface) {
                                lastSeenNonAmbientDeclaration = node;
                            }
                        }
                    }
                    if (multipleConstructorImplementation) {
                        ts.forEach(declarations, function (declaration) {
                            error(declaration, ts.Diagnostics.Multiple_constructor_implementations_are_not_allowed);
                        });
                    }
                    if (duplicateFunctionDeclaration) {
                        ts.forEach(declarations, function (declaration) {
                            error(declaration.name, ts.Diagnostics.Duplicate_function_implementation);
                        });
                    }
                    if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body) {
                        reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
                    }
                    if (hasOverloads) {
                        checkFlagAgreementBetweenOverloads(declarations, bodyDeclaration, flagsToCheck, someNodeFlags, allNodeFlags);
                        checkQuestionTokenAgreementBetweenOverloads(declarations, bodyDeclaration, someHaveQuestionToken, allHaveQuestionToken);
                        if (bodyDeclaration) {
                            var signatures = getSignaturesOfSymbol(symbol);
                            var bodySignature = getSignatureFromDeclaration(bodyDeclaration);
                            // If the implementation signature has string literals, we will have reported an error in
                            // checkSpecializedSignatureDeclaration
                            if (!bodySignature.hasStringLiterals) {
                                // TypeScript 1.0 spec (April 2014): 6.1
                                // If a function declaration includes overloads, the overloads determine the call
                                // signatures of the type given to the function object
                                // and the function implementation signature must be assignable to that type
                                //
                                // TypeScript 1.0 spec (April 2014): 3.8.4
                                // Note that specialized call and construct signatures (section 3.7.2.4) are not significant when determining assignment compatibility
                                // Consider checking against specialized signatures too. Not doing so creates a type hole:
                                //
                                // function g(x: "hi", y: boolean);
                                // function g(x: string, y: {});
                                // function g(x: string, y: string) { }
                                //
                                // The implementation is completely unrelated to the specialized signature, yet we do not check this.
                                for (var _a = 0; _a < signatures.length; _a++) {
                                    var signature = signatures[_a];
                                    if (!signature.hasStringLiterals && !isSignatureAssignableTo(bodySignature, signature)) {
                                        error(signature.declaration, ts.Diagnostics.Overload_signature_is_not_compatible_with_function_implementation);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                function checkExportsOnMergedDeclarations(node) {
                    if (!produceDiagnostics) {
                        return;
                    }
                    // Exports should be checked only if enclosing module contains both exported and non exported declarations.
                    // In case if all declarations are non-exported check is unnecessary.
                    // if localSymbol is defined on node then node itself is exported - check is required
                    var symbol = node.localSymbol;
                    if (!symbol) {
                        // local symbol is undefined => this declaration is non-exported.
                        // however symbol might contain other declarations that are exported
                        symbol = getSymbolOfNode(node);
                        if (!(symbol.flags & 7340032 /* Export */)) {
                            // this is a pure local symbol (all declarations are non-exported) - no need to check anything
                            return;
                        }
                    }
                    // run the check only for the first declaration in the list
                    if (ts.getDeclarationOfKind(symbol, node.kind) !== node) {
                        return;
                    }
                    // we use SymbolFlags.ExportValue, SymbolFlags.ExportType and SymbolFlags.ExportNamespace
                    // to denote disjoint declarationSpaces (without making new enum type).
                    var exportedDeclarationSpaces = 0;
                    var nonExportedDeclarationSpaces = 0;
                    ts.forEach(symbol.declarations, function (d) {
                        var declarationSpaces = getDeclarationSpaces(d);
                        if (getEffectiveDeclarationFlags(d, 1 /* Export */)) {
                            exportedDeclarationSpaces |= declarationSpaces;
                        }
                        else {
                            nonExportedDeclarationSpaces |= declarationSpaces;
                        }
                    });
                    var commonDeclarationSpace = exportedDeclarationSpaces & nonExportedDeclarationSpaces;
                    if (commonDeclarationSpace) {
                        // declaration spaces for exported and non-exported declarations intersect
                        ts.forEach(symbol.declarations, function (d) {
                            if (getDeclarationSpaces(d) & commonDeclarationSpace) {
                                error(d.name, ts.Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, ts.declarationNameToString(d.name));
                            }
                        });
                    }
                    function getDeclarationSpaces(d) {
                        switch (d.kind) {
                            case 202 /* InterfaceDeclaration */:
                                return 2097152 /* ExportType */;
                            case 205 /* ModuleDeclaration */:
                                return d.name.kind === 8 /* StringLiteral */ || ts.getModuleInstanceState(d) !== 0 /* NonInstantiated */
                                    ? 4194304 /* ExportNamespace */ | 1048576 /* ExportValue */
                                    : 4194304 /* ExportNamespace */;
                            case 201 /* ClassDeclaration */:
                            case 204 /* EnumDeclaration */:
                                return 2097152 /* ExportType */ | 1048576 /* ExportValue */;
                            case 208 /* ImportEqualsDeclaration */:
                                var result = 0;
                                var target = resolveAlias(getSymbolOfNode(d));
                                ts.forEach(target.declarations, function (d) { result |= getDeclarationSpaces(d); });
                                return result;
                            default:
                                return 1048576 /* ExportValue */;
                        }
                    }
                }
                /** Check a decorator */
                function checkDecorator(node) {
                    var expression = node.expression;
                    var exprType = checkExpression(expression);
                    switch (node.parent.kind) {
                        case 201 /* ClassDeclaration */:
                            var classSymbol = getSymbolOfNode(node.parent);
                            var classConstructorType = getTypeOfSymbol(classSymbol);
                            var classDecoratorType = instantiateSingleCallFunctionType(getGlobalClassDecoratorType(), [classConstructorType]);
                            checkTypeAssignableTo(exprType, classDecoratorType, node);
                            break;
                        case 132 /* PropertyDeclaration */:
                            checkTypeAssignableTo(exprType, getGlobalPropertyDecoratorType(), node);
                            break;
                        case 134 /* MethodDeclaration */:
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                            var methodType = getTypeOfNode(node.parent);
                            var methodDecoratorType = instantiateSingleCallFunctionType(getGlobalMethodDecoratorType(), [methodType]);
                            checkTypeAssignableTo(exprType, methodDecoratorType, node);
                            break;
                        case 129 /* Parameter */:
                            checkTypeAssignableTo(exprType, getGlobalParameterDecoratorType(), node);
                            break;
                    }
                }
                /** Checks a type reference node as an expression. */
                function checkTypeNodeAsExpression(node) {
                    // When we are emitting type metadata for decorators, we need to try to check the type
                    // as if it were an expression so that we can emit the type in a value position when we 
                    // serialize the type metadata.
                    if (node && node.kind === 141 /* TypeReference */) {
                        var type = getTypeFromTypeNode(node);
                        var shouldCheckIfUnknownType = type === unknownType && compilerOptions.separateCompilation;
                        if (!type || (!shouldCheckIfUnknownType && type.flags & (1048703 /* Intrinsic */ | 132 /* NumberLike */ | 258 /* StringLike */))) {
                            return;
                        }
                        if (shouldCheckIfUnknownType || type.symbol.valueDeclaration) {
                            checkExpressionOrQualifiedName(node.typeName);
                        }
                    }
                }
                /**
                  * Checks the type annotation of an accessor declaration or property declaration as
                  * an expression if it is a type reference to a type with a value declaration.
                  */
                function checkTypeAnnotationAsExpression(node) {
                    switch (node.kind) {
                        case 132 /* PropertyDeclaration */:
                            checkTypeNodeAsExpression(node.type);
                            break;
                        case 129 /* Parameter */:
                            checkTypeNodeAsExpression(node.type);
                            break;
                        case 134 /* MethodDeclaration */:
                            checkTypeNodeAsExpression(node.type);
                            break;
                        case 136 /* GetAccessor */:
                            checkTypeNodeAsExpression(node.type);
                            break;
                        case 137 /* SetAccessor */:
                            checkTypeNodeAsExpression(getSetAccessorTypeAnnotationNode(node));
                            break;
                    }
                }
                /** Checks the type annotation of the parameters of a function/method or the constructor of a class as expressions */
                function checkParameterTypeAnnotationsAsExpressions(node) {
                    // ensure all type annotations with a value declaration are checked as an expression
                    for (var _i = 0, _a = node.parameters; _i < _a.length; _i++) {
                        var parameter = _a[_i];
                        checkTypeAnnotationAsExpression(parameter);
                    }
                }
                /** Check the decorators of a node */
                function checkDecorators(node) {
                    if (!node.decorators) {
                        return;
                    }
                    // skip this check for nodes that cannot have decorators. These should have already had an error reported by
                    // checkGrammarDecorators.
                    if (!ts.nodeCanBeDecorated(node)) {
                        return;
                    }
                    if (compilerOptions.emitDecoratorMetadata) {
                        // we only need to perform these checks if we are emitting serialized type metadata for the target of a decorator.
                        switch (node.kind) {
                            case 201 /* ClassDeclaration */:
                                var constructor = ts.getFirstConstructorWithBody(node);
                                if (constructor) {
                                    checkParameterTypeAnnotationsAsExpressions(constructor);
                                }
                                break;
                            case 134 /* MethodDeclaration */:
                                checkParameterTypeAnnotationsAsExpressions(node);
                            // fall-through
                            case 137 /* SetAccessor */:
                            case 136 /* GetAccessor */:
                            case 132 /* PropertyDeclaration */:
                            case 129 /* Parameter */:
                                checkTypeAnnotationAsExpression(node);
                                break;
                        }
                    }
                    emitDecorate = true;
                    if (node.kind === 129 /* Parameter */) {
                        emitParam = true;
                    }
                    ts.forEach(node.decorators, checkDecorator);
                }
                function checkFunctionDeclaration(node) {
                    if (produceDiagnostics) {
                        checkFunctionLikeDeclaration(node) ||
                            checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) ||
                            checkGrammarFunctionName(node.name) ||
                            checkGrammarForGenerator(node);
                        checkCollisionWithCapturedSuperVariable(node, node.name);
                        checkCollisionWithCapturedThisVariable(node, node.name);
                        checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
                    }
                }
                function checkFunctionLikeDeclaration(node) {
                    checkGrammarDeclarationNameInStrictMode(node);
                    checkDecorators(node);
                    checkSignatureDeclaration(node);
                    // Do not use hasDynamicName here, because that returns false for well known symbols.
                    // We want to perform checkComputedPropertyName for all computed properties, including
                    // well known symbols.
                    if (node.name && node.name.kind === 127 /* ComputedPropertyName */) {
                        // This check will account for methods in class/interface declarations,
                        // as well as accessors in classes/object literals
                        checkComputedPropertyName(node.name);
                    }
                    if (!ts.hasDynamicName(node)) {
                        // first we want to check the local symbol that contain this declaration
                        // - if node.localSymbol !== undefined - this is current declaration is exported and localSymbol points to the local symbol
                        // - if node.localSymbol === undefined - this node is non-exported so we can just pick the result of getSymbolOfNode
                        var symbol = getSymbolOfNode(node);
                        var localSymbol = node.localSymbol || symbol;
                        var firstDeclaration = ts.getDeclarationOfKind(localSymbol, node.kind);
                        // Only type check the symbol once
                        if (node === firstDeclaration) {
                            checkFunctionOrConstructorSymbol(localSymbol);
                        }
                        if (symbol.parent) {
                            // run check once for the first declaration
                            if (ts.getDeclarationOfKind(symbol, node.kind) === node) {
                                // run check on export symbol to check that modifiers agree across all exported declarations
                                checkFunctionOrConstructorSymbol(symbol);
                            }
                        }
                    }
                    checkSourceElement(node.body);
                    if (node.type && !isAccessor(node.kind) && !node.asteriskToken) {
                        checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
                    }
                    // Report an implicit any error if there is no body, no explicit return type, and node is not a private method
                    // in an ambient context
                    if (compilerOptions.noImplicitAny && ts.nodeIsMissing(node.body) && !node.type && !isPrivateWithinAmbient(node)) {
                        reportImplicitAnyError(node, anyType);
                    }
                }
                function checkBlock(node) {
                    // Grammar checking for SyntaxKind.Block
                    if (node.kind === 179 /* Block */) {
                        checkGrammarStatementInAmbientContext(node);
                    }
                    ts.forEach(node.statements, checkSourceElement);
                    if (ts.isFunctionBlock(node) || node.kind === 206 /* ModuleBlock */) {
                        checkFunctionExpressionBodies(node);
                    }
                }
                function checkCollisionWithArgumentsInGeneratedCode(node) {
                    // no rest parameters \ declaration context \ overload - no codegen impact
                    if (!ts.hasRestParameters(node) || ts.isInAmbientContext(node) || ts.nodeIsMissing(node.body)) {
                        return;
                    }
                    ts.forEach(node.parameters, function (p) {
                        if (p.name && !ts.isBindingPattern(p.name) && p.name.text === argumentsSymbol.name) {
                            error(p, ts.Diagnostics.Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters);
                        }
                    });
                }
                function needCollisionCheckForIdentifier(node, identifier, name) {
                    if (!(identifier && identifier.text === name)) {
                        return false;
                    }
                    if (node.kind === 132 /* PropertyDeclaration */ ||
                        node.kind === 131 /* PropertySignature */ ||
                        node.kind === 134 /* MethodDeclaration */ ||
                        node.kind === 133 /* MethodSignature */ ||
                        node.kind === 136 /* GetAccessor */ ||
                        node.kind === 137 /* SetAccessor */) {
                        // it is ok to have member named '_super' or '_this' - member access is always qualified
                        return false;
                    }
                    if (ts.isInAmbientContext(node)) {
                        // ambient context - no codegen impact
                        return false;
                    }
                    var root = getRootDeclaration(node);
                    if (root.kind === 129 /* Parameter */ && ts.nodeIsMissing(root.parent.body)) {
                        // just an overload - no codegen impact
                        return false;
                    }
                    return true;
                }
                function checkCollisionWithCapturedThisVariable(node, name) {
                    if (needCollisionCheckForIdentifier(node, name, "_this")) {
                        potentialThisCollisions.push(node);
                    }
                }
                // this function will run after checking the source file so 'CaptureThis' is correct for all nodes
                function checkIfThisIsCapturedInEnclosingScope(node) {
                    var current = node;
                    while (current) {
                        if (getNodeCheckFlags(current) & 4 /* CaptureThis */) {
                            var isDeclaration_1 = node.kind !== 65 /* Identifier */;
                            if (isDeclaration_1) {
                                error(node.name, ts.Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference);
                            }
                            else {
                                error(node, ts.Diagnostics.Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference);
                            }
                            return;
                        }
                        current = current.parent;
                    }
                }
                function checkCollisionWithCapturedSuperVariable(node, name) {
                    if (!needCollisionCheckForIdentifier(node, name, "_super")) {
                        return;
                    }
                    // bubble up and find containing type
                    var enclosingClass = ts.getAncestor(node, 201 /* ClassDeclaration */);
                    // if containing type was not found or it is ambient - exit (no codegen)
                    if (!enclosingClass || ts.isInAmbientContext(enclosingClass)) {
                        return;
                    }
                    if (ts.getClassExtendsHeritageClauseElement(enclosingClass)) {
                        var isDeclaration_2 = node.kind !== 65 /* Identifier */;
                        if (isDeclaration_2) {
                            error(node, ts.Diagnostics.Duplicate_identifier_super_Compiler_uses_super_to_capture_base_class_reference);
                        }
                        else {
                            error(node, ts.Diagnostics.Expression_resolves_to_super_that_compiler_uses_to_capture_base_class_reference);
                        }
                    }
                }
                function checkCollisionWithRequireExportsInGeneratedCode(node, name) {
                    if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) {
                        return;
                    }
                    // Uninstantiated modules shouldnt do this check
                    if (node.kind === 205 /* ModuleDeclaration */ && ts.getModuleInstanceState(node) !== 1 /* Instantiated */) {
                        return;
                    }
                    // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent
                    var parent = getDeclarationContainer(node);
                    if (parent.kind === 227 /* SourceFile */ && ts.isExternalModule(parent)) {
                        // If the declaration happens to be in external module, report error that require and exports are reserved keywords
                        error(name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module, ts.declarationNameToString(name), ts.declarationNameToString(name));
                    }
                }
                function checkVarDeclaredNamesNotShadowed(node) {
                    // - ScriptBody : StatementList
                    // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
                    // also occurs in the VarDeclaredNames of StatementList.
                    // - Block : { StatementList }
                    // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
                    // also occurs in the VarDeclaredNames of StatementList.
                    // Variable declarations are hoisted to the top of their function scope. They can shadow
                    // block scoped declarations, which bind tighter. this will not be flagged as duplicate definition
                    // by the binder as the declaration scope is different.
                    // A non-initialized declaration is a no-op as the block declaration will resolve before the var
                    // declaration. the problem is if the declaration has an initializer. this will act as a write to the
                    // block declared value. this is fine for let, but not const.
                    // Only consider declarations with initializers, uninitialized let declarations will not
                    // step on a let/const variable.
                    // Do not consider let and const declarations, as duplicate block-scoped declarations
                    // are handled by the binder.
                    // We are only looking for let declarations that step on let\const declarations from a
                    // different scope. e.g.:
                    //      {
                    //          const x = 0; // localDeclarationSymbol obtained after name resolution will correspond to this declaration
                    //          let x = 0; // symbol for this declaration will be 'symbol'
                    //      }
                    // skip block-scoped variables and parameters
                    if ((ts.getCombinedNodeFlags(node) & 12288 /* BlockScoped */) !== 0 || isParameterDeclaration(node)) {
                        return;
                    }
                    // skip variable declarations that don't have initializers
                    // NOTE: in ES6 spec initializer is required in variable declarations where name is binding pattern
                    // so we'll always treat binding elements as initialized
                    if (node.kind === 198 /* VariableDeclaration */ && !node.initializer) {
                        return;
                    }
                    var symbol = getSymbolOfNode(node);
                    if (symbol.flags & 1 /* FunctionScopedVariable */) {
                        var localDeclarationSymbol = resolveName(node, node.name.text, 3 /* Variable */, undefined, undefined);
                        if (localDeclarationSymbol &&
                            localDeclarationSymbol !== symbol &&
                            localDeclarationSymbol.flags & 2 /* BlockScopedVariable */) {
                            if (getDeclarationFlagsFromSymbol(localDeclarationSymbol) & 12288 /* BlockScoped */) {
                                var varDeclList = ts.getAncestor(localDeclarationSymbol.valueDeclaration, 199 /* VariableDeclarationList */);
                                var container = varDeclList.parent.kind === 180 /* VariableStatement */ && varDeclList.parent.parent
                                    ? varDeclList.parent.parent
                                    : undefined;
                                // names of block-scoped and function scoped variables can collide only
                                // if block scoped variable is defined in the function\module\source file scope (because of variable hoisting)
                                var namesShareScope = container &&
                                    (container.kind === 179 /* Block */ && ts.isFunctionLike(container.parent) ||
                                        container.kind === 206 /* ModuleBlock */ ||
                                        container.kind === 205 /* ModuleDeclaration */ ||
                                        container.kind === 227 /* SourceFile */);
                                // here we know that function scoped variable is shadowed by block scoped one
                                // if they are defined in the same scope - binder has already reported redeclaration error
                                // otherwise if variable has an initializer - show error that initialization will fail
                                // since LHS will be block scoped name instead of function scoped
                                if (!namesShareScope) {
                                    var name_9 = symbolToString(localDeclarationSymbol);
                                    error(node, ts.Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name_9, name_9);
                                }
                            }
                        }
                    }
                }
                function isParameterDeclaration(node) {
                    while (node.kind === 152 /* BindingElement */) {
                        node = node.parent.parent;
                    }
                    return node.kind === 129 /* Parameter */;
                }
                // Check that a parameter initializer contains no references to parameters declared to the right of itself
                function checkParameterInitializer(node) {
                    if (getRootDeclaration(node).kind !== 129 /* Parameter */) {
                        return;
                    }
                    var func = ts.getContainingFunction(node);
                    visit(node.initializer);
                    function visit(n) {
                        if (n.kind === 65 /* Identifier */) {
                            var referencedSymbol = getNodeLinks(n).resolvedSymbol;
                            // check FunctionLikeDeclaration.locals (stores parameters\function local variable)
                            // if it contains entry with a specified name and if this entry matches the resolved symbol
                            if (referencedSymbol && referencedSymbol !== unknownSymbol && getSymbol(func.locals, referencedSymbol.name, 107455 /* Value */) === referencedSymbol) {
                                if (referencedSymbol.valueDeclaration.kind === 129 /* Parameter */) {
                                    if (referencedSymbol.valueDeclaration === node) {
                                        error(n, ts.Diagnostics.Parameter_0_cannot_be_referenced_in_its_initializer, ts.declarationNameToString(node.name));
                                        return;
                                    }
                                    if (referencedSymbol.valueDeclaration.pos < node.pos) {
                                        // legal case - parameter initializer references some parameter strictly on left of current parameter declaration
                                        return;
                                    }
                                }
                                error(n, ts.Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, ts.declarationNameToString(node.name), ts.declarationNameToString(n));
                            }
                        }
                        else {
                            ts.forEachChild(n, visit);
                        }
                    }
                }
                // Check variable, parameter, or property declaration
                function checkVariableLikeDeclaration(node) {
                    checkGrammarDeclarationNameInStrictMode(node);
                    checkDecorators(node);
                    checkSourceElement(node.type);
                    // For a computed property, just check the initializer and exit
                    // Do not use hasDynamicName here, because that returns false for well known symbols.
                    // We want to perform checkComputedPropertyName for all computed properties, including
                    // well known symbols.
                    if (node.name.kind === 127 /* ComputedPropertyName */) {
                        checkComputedPropertyName(node.name);
                        if (node.initializer) {
                            checkExpressionCached(node.initializer);
                        }
                    }
                    // For a binding pattern, check contained binding elements
                    if (ts.isBindingPattern(node.name)) {
                        ts.forEach(node.name.elements, checkSourceElement);
                    }
                    // For a parameter declaration with an initializer, error and exit if the containing function doesn't have a body
                    if (node.initializer && getRootDeclaration(node).kind === 129 /* Parameter */ && ts.nodeIsMissing(ts.getContainingFunction(node).body)) {
                        error(node, ts.Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation);
                        return;
                    }
                    // For a binding pattern, validate the initializer and exit
                    if (ts.isBindingPattern(node.name)) {
                        if (node.initializer) {
                            checkTypeAssignableTo(checkExpressionCached(node.initializer), getWidenedTypeForVariableLikeDeclaration(node), node, undefined);
                            checkParameterInitializer(node);
                        }
                        return;
                    }
                    var symbol = getSymbolOfNode(node);
                    var type = getTypeOfVariableOrParameterOrProperty(symbol);
                    if (node === symbol.valueDeclaration) {
                        // Node is the primary declaration of the symbol, just validate the initializer
                        if (node.initializer) {
                            checkTypeAssignableTo(checkExpressionCached(node.initializer), type, node, undefined);
                            checkParameterInitializer(node);
                        }
                    }
                    else {
                        // Node is a secondary declaration, check that type is identical to primary declaration and check that
                        // initializer is consistent with type associated with the node
                        var declarationType = getWidenedTypeForVariableLikeDeclaration(node);
                        if (type !== unknownType && declarationType !== unknownType && !isTypeIdenticalTo(type, declarationType)) {
                            error(node.name, ts.Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2, ts.declarationNameToString(node.name), typeToString(type), typeToString(declarationType));
                        }
                        if (node.initializer) {
                            checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, node, undefined);
                        }
                    }
                    if (node.kind !== 132 /* PropertyDeclaration */ && node.kind !== 131 /* PropertySignature */) {
                        // We know we don't have a binding pattern or computed name here
                        checkExportsOnMergedDeclarations(node);
                        if (node.kind === 198 /* VariableDeclaration */ || node.kind === 152 /* BindingElement */) {
                            checkVarDeclaredNamesNotShadowed(node);
                        }
                        checkCollisionWithCapturedSuperVariable(node, node.name);
                        checkCollisionWithCapturedThisVariable(node, node.name);
                        checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
                    }
                }
                function checkVariableDeclaration(node) {
                    checkGrammarVariableDeclaration(node);
                    return checkVariableLikeDeclaration(node);
                }
                function checkBindingElement(node) {
                    checkGrammarBindingElement(node);
                    return checkVariableLikeDeclaration(node);
                }
                function checkVariableStatement(node) {
                    // Grammar checking
                    checkGrammarDecorators(node) || checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || checkGrammarModifiers(node) || checkGrammarVariableDeclarationList(node.declarationList) || checkGrammarForDisallowedLetOrConstStatement(node);
                    ts.forEach(node.declarationList.declarations, checkSourceElement);
                }
                function checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) {
                    if (node.modifiers) {
                        if (inBlockOrObjectLiteralExpression(node)) {
                            return grammarErrorOnFirstToken(node, ts.Diagnostics.Modifiers_cannot_appear_here);
                        }
                    }
                }
                function inBlockOrObjectLiteralExpression(node) {
                    while (node) {
                        if (node.kind === 179 /* Block */ || node.kind === 154 /* ObjectLiteralExpression */) {
                            return true;
                        }
                        node = node.parent;
                    }
                }
                function checkExpressionStatement(node) {
                    // Grammar checking
                    checkGrammarStatementInAmbientContext(node);
                    checkExpression(node.expression);
                }
                function checkIfStatement(node) {
                    // Grammar checking
                    checkGrammarStatementInAmbientContext(node);
                    checkExpression(node.expression);
                    checkSourceElement(node.thenStatement);
                    checkSourceElement(node.elseStatement);
                }
                function checkDoStatement(node) {
                    // Grammar checking
                    checkGrammarStatementInAmbientContext(node);
                    checkSourceElement(node.statement);
                    checkExpression(node.expression);
                }
                function checkWhileStatement(node) {
                    // Grammar checking
                    checkGrammarStatementInAmbientContext(node);
                    checkExpression(node.expression);
                    checkSourceElement(node.statement);
                }
                function checkForStatement(node) {
                    // Grammar checking
                    if (!checkGrammarStatementInAmbientContext(node)) {
                        if (node.initializer && node.initializer.kind == 199 /* VariableDeclarationList */) {
                            checkGrammarVariableDeclarationList(node.initializer);
                        }
                    }
                    if (node.initializer) {
                        if (node.initializer.kind === 199 /* VariableDeclarationList */) {
                            ts.forEach(node.initializer.declarations, checkVariableDeclaration);
                        }
                        else {
                            checkExpression(node.initializer);
                        }
                    }
                    if (node.condition)
                        checkExpression(node.condition);
                    if (node.incrementor)
                        checkExpression(node.incrementor);
                    checkSourceElement(node.statement);
                }
                function checkForOfStatement(node) {
                    checkGrammarForInOrForOfStatement(node);
                    // Check the LHS and RHS
                    // If the LHS is a declaration, just check it as a variable declaration, which will in turn check the RHS
                    // via checkRightHandSideOfForOf.
                    // If the LHS is an expression, check the LHS, as a destructuring assignment or as a reference.
                    // Then check that the RHS is assignable to it.
                    if (node.initializer.kind === 199 /* VariableDeclarationList */) {
                        checkForInOrForOfVariableDeclaration(node);
                    }
                    else {
                        var varExpr = node.initializer;
                        var iteratedType = checkRightHandSideOfForOf(node.expression);
                        // There may be a destructuring assignment on the left side
                        if (varExpr.kind === 153 /* ArrayLiteralExpression */ || varExpr.kind === 154 /* ObjectLiteralExpression */) {
                            // iteratedType may be undefined. In this case, we still want to check the structure of
                            // varExpr, in particular making sure it's a valid LeftHandSideExpression. But we'd like
                            // to short circuit the type relation checking as much as possible, so we pass the unknownType.
                            checkDestructuringAssignment(varExpr, iteratedType || unknownType);
                        }
                        else {
                            var leftType = checkExpression(varExpr);
                            checkReferenceExpression(varExpr, ts.Diagnostics.Invalid_left_hand_side_in_for_of_statement, 
                            /*constantVariableMessage*/ ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant);
                            // iteratedType will be undefined if the rightType was missing properties/signatures
                            // required to get its iteratedType (like [Symbol.iterator] or next). This may be
                            // because we accessed properties from anyType, or it may have led to an error inside
                            // getIteratedType.
                            if (iteratedType) {
                                checkTypeAssignableTo(iteratedType, leftType, varExpr, undefined);
                            }
                        }
                    }
                    checkSourceElement(node.statement);
                }
                function checkForInStatement(node) {
                    // Grammar checking
                    checkGrammarForInOrForOfStatement(node);
                    // TypeScript 1.0 spec  (April 2014): 5.4
                    // In a 'for-in' statement of the form
                    // for (let VarDecl in Expr) Statement
                    //   VarDecl must be a variable declaration without a type annotation that declares a variable of type Any,
                    //   and Expr must be an expression of type Any, an object type, or a type parameter type.
                    if (node.initializer.kind === 199 /* VariableDeclarationList */) {
                        var variable = node.initializer.declarations[0];
                        if (variable && ts.isBindingPattern(variable.name)) {
                            error(variable.name, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
                        }
                        checkForInOrForOfVariableDeclaration(node);
                    }
                    else {
                        // In a 'for-in' statement of the form
                        // for (Var in Expr) Statement
                        //   Var must be an expression classified as a reference of type Any or the String primitive type,
                        //   and Expr must be an expression of type Any, an object type, or a type parameter type.
                        var varExpr = node.initializer;
                        var leftType = checkExpression(varExpr);
                        if (varExpr.kind === 153 /* ArrayLiteralExpression */ || varExpr.kind === 154 /* ObjectLiteralExpression */) {
                            error(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
                        }
                        else if (!allConstituentTypesHaveKind(leftType, 1 /* Any */ | 258 /* StringLike */)) {
                            error(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any);
                        }
                        else {
                            // run check only former check succeeded to avoid cascading errors
                            checkReferenceExpression(varExpr, ts.Diagnostics.Invalid_left_hand_side_in_for_in_statement, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_previously_defined_constant);
                        }
                    }
                    var rightType = checkExpression(node.expression);
                    // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved
                    // in this case error about missing name is already reported - do not report extra one
                    if (!allConstituentTypesHaveKind(rightType, 1 /* Any */ | 48128 /* ObjectType */ | 512 /* TypeParameter */)) {
                        error(node.expression, ts.Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter);
                    }
                    checkSourceElement(node.statement);
                }
                function checkForInOrForOfVariableDeclaration(iterationStatement) {
                    var variableDeclarationList = iterationStatement.initializer;
                    // checkGrammarForInOrForOfStatement will check that there is exactly one declaration.
                    if (variableDeclarationList.declarations.length >= 1) {
                        var decl = variableDeclarationList.declarations[0];
                        checkVariableDeclaration(decl);
                    }
                }
                function checkRightHandSideOfForOf(rhsExpression) {
                    var expressionType = getTypeOfExpression(rhsExpression);
                    return checkIteratedTypeOrElementType(expressionType, rhsExpression, true);
                }
                function checkIteratedTypeOrElementType(inputType, errorNode, allowStringInput) {
                    if (inputType.flags & 1 /* Any */) {
                        return inputType;
                    }
                    if (languageVersion >= 2 /* ES6 */) {
                        return checkIteratedType(inputType, errorNode) || anyType;
                    }
                    if (allowStringInput) {
                        return checkElementTypeOfArrayOrString(inputType, errorNode);
                    }
                    if (isArrayLikeType(inputType)) {
                        var indexType = getIndexTypeOfType(inputType, 1 /* Number */);
                        if (indexType) {
                            return indexType;
                        }
                    }
                    error(errorNode, ts.Diagnostics.Type_0_is_not_an_array_type, typeToString(inputType));
                    return unknownType;
                }
                /**
                 * When errorNode is undefined, it means we should not report any errors.
                 */
                function checkIteratedType(iterable, errorNode) {
                    ts.Debug.assert(languageVersion >= 2 /* ES6 */);
                    var iteratedType = getIteratedType(iterable, errorNode);
                    // Now even though we have extracted the iteratedType, we will have to validate that the type
                    // passed in is actually an Iterable.
                    if (errorNode && iteratedType) {
                        checkTypeAssignableTo(iterable, createIterableType(iteratedType), errorNode);
                    }
                    return iteratedType;
                    function getIteratedType(iterable, errorNode) {
                        // We want to treat type as an iterable, and get the type it is an iterable of. The iterable
                        // must have the following structure (annotated with the names of the variables below):
                        //
                        // { // iterable
                        //     [Symbol.iterator]: { // iteratorFunction
                        //         (): { // iterator
                        //             next: { // iteratorNextFunction
                        //                 (): { // iteratorNextResult
                        //                     value: T // iteratorNextValue
                        //                 }
                        //             }
                        //         }
                        //     }
                        // }
                        //
                        // T is the type we are after. At every level that involves analyzing return types
                        // of signatures, we union the return types of all the signatures.
                        //
                        // Another thing to note is that at any step of this process, we could run into a dead end,
                        // meaning either the property is missing, or we run into the anyType. If either of these things
                        // happens, we return undefined to signal that we could not find the iterated type. If a property
                        // is missing, and the previous step did not result in 'any', then we also give an error if the
                        // caller requested it. Then the caller can decide what to do in the case where there is no iterated
                        // type. This is different from returning anyType, because that would signify that we have matched the
                        // whole pattern and that T (above) is 'any'.
                        if (allConstituentTypesHaveKind(iterable, 1 /* Any */)) {
                            return undefined;
                        }
                        // As an optimization, if the type is instantiated directly using the globalIterableType (Iterable<number>),
                        // then just grab its type argument.
                        if ((iterable.flags & 4096 /* Reference */) && iterable.target === globalIterableType) {
                            return iterable.typeArguments[0];
                        }
                        var iteratorFunction = getTypeOfPropertyOfType(iterable, ts.getPropertyNameForKnownSymbolName("iterator"));
                        if (iteratorFunction && allConstituentTypesHaveKind(iteratorFunction, 1 /* Any */)) {
                            return undefined;
                        }
                        var iteratorFunctionSignatures = iteratorFunction ? getSignaturesOfType(iteratorFunction, 0 /* Call */) : emptyArray;
                        if (iteratorFunctionSignatures.length === 0) {
                            if (errorNode) {
                                error(errorNode, ts.Diagnostics.Type_must_have_a_Symbol_iterator_method_that_returns_an_iterator);
                            }
                            return undefined;
                        }
                        var iterator = getUnionType(ts.map(iteratorFunctionSignatures, getReturnTypeOfSignature));
                        if (allConstituentTypesHaveKind(iterator, 1 /* Any */)) {
                            return undefined;
                        }
                        var iteratorNextFunction = getTypeOfPropertyOfType(iterator, "next");
                        if (iteratorNextFunction && allConstituentTypesHaveKind(iteratorNextFunction, 1 /* Any */)) {
                            return undefined;
                        }
                        var iteratorNextFunctionSignatures = iteratorNextFunction ? getSignaturesOfType(iteratorNextFunction, 0 /* Call */) : emptyArray;
                        if (iteratorNextFunctionSignatures.length === 0) {
                            if (errorNode) {
                                error(errorNode, ts.Diagnostics.An_iterator_must_have_a_next_method);
                            }
                            return undefined;
                        }
                        var iteratorNextResult = getUnionType(ts.map(iteratorNextFunctionSignatures, getReturnTypeOfSignature));
                        if (allConstituentTypesHaveKind(iteratorNextResult, 1 /* Any */)) {
                            return undefined;
                        }
                        var iteratorNextValue = getTypeOfPropertyOfType(iteratorNextResult, "value");
                        if (!iteratorNextValue) {
                            if (errorNode) {
                                error(errorNode, ts.Diagnostics.The_type_returned_by_the_next_method_of_an_iterator_must_have_a_value_property);
                            }
                            return undefined;
                        }
                        return iteratorNextValue;
                    }
                }
                /**
                 * This function does the following steps:
                 *   1. Break up arrayOrStringType (possibly a union) into its string constituents and array constituents.
                 *   2. Take the element types of the array constituents.
                 *   3. Return the union of the element types, and string if there was a string constitutent.
                 *
                 * For example:
                 *     string -> string
                 *     number[] -> number
                 *     string[] | number[] -> string | number
                 *     string | number[] -> string | number
                 *     string | string[] | number[] -> string | number
                 *
                 * It also errors if:
                 *   1. Some constituent is neither a string nor an array.
                 *   2. Some constituent is a string and target is less than ES5 (because in ES3 string is not indexable).
                 */
                function checkElementTypeOfArrayOrString(arrayOrStringType, errorNode) {
                    ts.Debug.assert(languageVersion < 2 /* ES6 */);
                    // After we remove all types that are StringLike, we will know if there was a string constituent
                    // based on whether the remaining type is the same as the initial type.
                    var arrayType = removeTypesFromUnionType(arrayOrStringType, 258 /* StringLike */, true, true);
                    var hasStringConstituent = arrayOrStringType !== arrayType;
                    var reportedError = false;
                    if (hasStringConstituent) {
                        if (languageVersion < 1 /* ES5 */) {
                            error(errorNode, ts.Diagnostics.Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher);
                            reportedError = true;
                        }
                        // Now that we've removed all the StringLike types, if no constituents remain, then the entire
                        // arrayOrStringType was a string.
                        if (arrayType === emptyObjectType) {
                            return stringType;
                        }
                    }
                    if (!isArrayLikeType(arrayType)) {
                        if (!reportedError) {
                            // Which error we report depends on whether there was a string constituent. For example,
                            // if the input type is number | string, we want to say that number is not an array type.
                            // But if the input was just number, we want to say that number is not an array type
                            // or a string type.
                            var diagnostic = hasStringConstituent
                                ? ts.Diagnostics.Type_0_is_not_an_array_type
                                : ts.Diagnostics.Type_0_is_not_an_array_type_or_a_string_type;
                            error(errorNode, diagnostic, typeToString(arrayType));
                        }
                        return hasStringConstituent ? stringType : unknownType;
                    }
                    var arrayElementType = getIndexTypeOfType(arrayType, 1 /* Number */) || unknownType;
                    if (hasStringConstituent) {
                        // This is just an optimization for the case where arrayOrStringType is string | string[]
                        if (arrayElementType.flags & 258 /* StringLike */) {
                            return stringType;
                        }
                        return getUnionType([arrayElementType, stringType]);
                    }
                    return arrayElementType;
                }
                function checkBreakOrContinueStatement(node) {
                    // Grammar checking
                    checkGrammarStatementInAmbientContext(node) || checkGrammarBreakOrContinueStatement(node);
                    // TODO: Check that target label is valid
                }
                function isGetAccessorWithAnnotatatedSetAccessor(node) {
                    return !!(node.kind === 136 /* GetAccessor */ && getSetAccessorTypeAnnotationNode(ts.getDeclarationOfKind(node.symbol, 137 /* SetAccessor */)));
                }
                function checkReturnStatement(node) {
                    // Grammar checking
                    if (!checkGrammarStatementInAmbientContext(node)) {
                        var functionBlock = ts.getContainingFunction(node);
                        if (!functionBlock) {
                            grammarErrorOnFirstToken(node, ts.Diagnostics.A_return_statement_can_only_be_used_within_a_function_body);
                        }
                    }
                    if (node.expression) {
                        var func = ts.getContainingFunction(node);
                        if (func) {
                            var returnType = getReturnTypeOfSignature(getSignatureFromDeclaration(func));
                            var exprType = checkExpressionCached(node.expression);
                            if (func.kind === 137 /* SetAccessor */) {
                                error(node.expression, ts.Diagnostics.Setters_cannot_return_a_value);
                            }
                            else {
                                if (func.kind === 135 /* Constructor */) {
                                    if (!isTypeAssignableTo(exprType, returnType)) {
                                        error(node.expression, ts.Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
                                    }
                                }
                                else if (func.type || isGetAccessorWithAnnotatatedSetAccessor(func)) {
                                    checkTypeAssignableTo(exprType, returnType, node.expression, undefined);
                                }
                            }
                        }
                    }
                }
                function checkWithStatement(node) {
                    // Grammar checking for withStatement
                    if (!checkGrammarStatementInAmbientContext(node)) {
                        if (node.parserContextFlags & 1 /* StrictMode */) {
                            grammarErrorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode);
                        }
                    }
                    checkExpression(node.expression);
                    error(node.expression, ts.Diagnostics.All_symbols_within_a_with_block_will_be_resolved_to_any);
                }
                function checkSwitchStatement(node) {
                    // Grammar checking
                    checkGrammarStatementInAmbientContext(node);
                    var firstDefaultClause;
                    var hasDuplicateDefaultClause = false;
                    var expressionType = checkExpression(node.expression);
                    ts.forEach(node.caseBlock.clauses, function (clause) {
                        // Grammar check for duplicate default clauses, skip if we already report duplicate default clause
                        if (clause.kind === 221 /* DefaultClause */ && !hasDuplicateDefaultClause) {
                            if (firstDefaultClause === undefined) {
                                firstDefaultClause = clause;
                            }
                            else {
                                var sourceFile = ts.getSourceFileOfNode(node);
                                var start = ts.skipTrivia(sourceFile.text, clause.pos);
                                var end = clause.statements.length > 0 ? clause.statements[0].pos : clause.end;
                                grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement);
                                hasDuplicateDefaultClause = true;
                            }
                        }
                        if (produceDiagnostics && clause.kind === 220 /* CaseClause */) {
                            var caseClause = clause;
                            // TypeScript 1.0 spec (April 2014):5.9
                            // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression.
                            var caseType = checkExpression(caseClause.expression);
                            if (!isTypeAssignableTo(expressionType, caseType)) {
                                // check 'expressionType isAssignableTo caseType' failed, try the reversed check and report errors if it fails
                                checkTypeAssignableTo(caseType, expressionType, caseClause.expression, undefined);
                            }
                        }
                        ts.forEach(clause.statements, checkSourceElement);
                    });
                }
                function checkLabeledStatement(node) {
                    // Grammar checking
                    if (!checkGrammarStatementInAmbientContext(node)) {
                        var current = node.parent;
                        while (current) {
                            if (ts.isFunctionLike(current)) {
                                break;
                            }
                            if (current.kind === 194 /* LabeledStatement */ && current.label.text === node.label.text) {
                                var sourceFile = ts.getSourceFileOfNode(node);
                                grammarErrorOnNode(node.label, ts.Diagnostics.Duplicate_label_0, ts.getTextOfNodeFromSourceText(sourceFile.text, node.label));
                                break;
                            }
                            current = current.parent;
                        }
                    }
                    // ensure that label is unique
                    checkSourceElement(node.statement);
                }
                function checkThrowStatement(node) {
                    // Grammar checking
                    if (!checkGrammarStatementInAmbientContext(node)) {
                        if (node.expression === undefined) {
                            grammarErrorAfterFirstToken(node, ts.Diagnostics.Line_break_not_permitted_here);
                        }
                    }
                    if (node.expression) {
                        checkExpression(node.expression);
                    }
                }
                function checkTryStatement(node) {
                    // Grammar checking
                    checkGrammarStatementInAmbientContext(node);
                    checkBlock(node.tryBlock);
                    var catchClause = node.catchClause;
                    if (catchClause) {
                        // Grammar checking
                        if (catchClause.variableDeclaration) {
                            if (catchClause.variableDeclaration.name.kind !== 65 /* Identifier */) {
                                grammarErrorOnFirstToken(catchClause.variableDeclaration.name, ts.Diagnostics.Catch_clause_variable_name_must_be_an_identifier);
                            }
                            else if (catchClause.variableDeclaration.type) {
                                grammarErrorOnFirstToken(catchClause.variableDeclaration.type, ts.Diagnostics.Catch_clause_variable_cannot_have_a_type_annotation);
                            }
                            else if (catchClause.variableDeclaration.initializer) {
                                grammarErrorOnFirstToken(catchClause.variableDeclaration.initializer, ts.Diagnostics.Catch_clause_variable_cannot_have_an_initializer);
                            }
                            else {
                                var identifierName = catchClause.variableDeclaration.name.text;
                                var locals = catchClause.block.locals;
                                if (locals && ts.hasProperty(locals, identifierName)) {
                                    var localSymbol = locals[identifierName];
                                    if (localSymbol && (localSymbol.flags & 2 /* BlockScopedVariable */) !== 0) {
                                        grammarErrorOnNode(localSymbol.valueDeclaration, ts.Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, identifierName);
                                    }
                                }
                                // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the
                                // Catch production is eval or arguments
                                checkGrammarEvalOrArgumentsInStrictMode(node, catchClause.variableDeclaration.name);
                            }
                        }
                        checkBlock(catchClause.block);
                    }
                    if (node.finallyBlock) {
                        checkBlock(node.finallyBlock);
                    }
                }
                function checkIndexConstraints(type) {
                    var declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol, 1 /* Number */);
                    var declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol, 0 /* String */);
                    var stringIndexType = getIndexTypeOfType(type, 0 /* String */);
                    var numberIndexType = getIndexTypeOfType(type, 1 /* Number */);
                    if (stringIndexType || numberIndexType) {
                        ts.forEach(getPropertiesOfObjectType(type), function (prop) {
                            var propType = getTypeOfSymbol(prop);
                            checkIndexConstraintForProperty(prop, propType, type, declaredStringIndexer, stringIndexType, 0 /* String */);
                            checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, 1 /* Number */);
                        });
                        if (type.flags & 1024 /* Class */ && type.symbol.valueDeclaration.kind === 201 /* ClassDeclaration */) {
                            var classDeclaration = type.symbol.valueDeclaration;
                            for (var _i = 0, _a = classDeclaration.members; _i < _a.length; _i++) {
                                var member = _a[_i];
                                // Only process instance properties with computed names here.
                                // Static properties cannot be in conflict with indexers,
                                // and properties with literal names were already checked.
                                if (!(member.flags & 128 /* Static */) && ts.hasDynamicName(member)) {
                                    var propType = getTypeOfSymbol(member.symbol);
                                    checkIndexConstraintForProperty(member.symbol, propType, type, declaredStringIndexer, stringIndexType, 0 /* String */);
                                    checkIndexConstraintForProperty(member.symbol, propType, type, declaredNumberIndexer, numberIndexType, 1 /* Number */);
                                }
                            }
                        }
                    }
                    var errorNode;
                    if (stringIndexType && numberIndexType) {
                        errorNode = declaredNumberIndexer || declaredStringIndexer;
                        // condition 'errorNode === undefined' may appear if types does not declare nor string neither number indexer
                        if (!errorNode && (type.flags & 2048 /* Interface */)) {
                            var someBaseTypeHasBothIndexers = ts.forEach(getBaseTypes(type), function (base) { return getIndexTypeOfType(base, 0 /* String */) && getIndexTypeOfType(base, 1 /* Number */); });
                            errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol.declarations[0];
                        }
                    }
                    if (errorNode && !isTypeAssignableTo(numberIndexType, stringIndexType)) {
                        error(errorNode, ts.Diagnostics.Numeric_index_type_0_is_not_assignable_to_string_index_type_1, typeToString(numberIndexType), typeToString(stringIndexType));
                    }
                    function checkIndexConstraintForProperty(prop, propertyType, containingType, indexDeclaration, indexType, indexKind) {
                        if (!indexType) {
                            return;
                        }
                        // index is numeric and property name is not valid numeric literal
                        if (indexKind === 1 /* Number */ && !isNumericName(prop.valueDeclaration.name)) {
                            return;
                        }
                        // perform property check if property or indexer is declared in 'type'
                        // this allows to rule out cases when both property and indexer are inherited from the base class
                        var errorNode;
                        if (prop.valueDeclaration.name.kind === 127 /* ComputedPropertyName */ || prop.parent === containingType.symbol) {
                            errorNode = prop.valueDeclaration;
                        }
                        else if (indexDeclaration) {
                            errorNode = indexDeclaration;
                        }
                        else if (containingType.flags & 2048 /* Interface */) {
                            // for interfaces property and indexer might be inherited from different bases
                            // check if any base class already has both property and indexer.
                            // check should be performed only if 'type' is the first type that brings property\indexer together
                            var someBaseClassHasBothPropertyAndIndexer = ts.forEach(getBaseTypes(containingType), function (base) { return getPropertyOfObjectType(base, prop.name) && getIndexTypeOfType(base, indexKind); });
                            errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol.declarations[0];
                        }
                        if (errorNode && !isTypeAssignableTo(propertyType, indexType)) {
                            var errorMessage = indexKind === 0 /* String */
                                ? ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_string_index_type_2
                                : ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2;
                            error(errorNode, errorMessage, symbolToString(prop), typeToString(propertyType), typeToString(indexType));
                        }
                    }
                }
                function checkTypeNameIsReserved(name, message) {
                    // TS 1.0 spec (April 2014): 3.6.1
                    // The predefined type keywords are reserved and cannot be used as names of user defined types.
                    switch (name.text) {
                        case "any":
                        case "number":
                        case "boolean":
                        case "string":
                        case "symbol":
                        case "void":
                            error(name, message, name.text);
                    }
                }
                // Check each type parameter and check that list has no duplicate type parameter declarations
                function checkTypeParameters(typeParameterDeclarations) {
                    if (typeParameterDeclarations) {
                        for (var i = 0, n = typeParameterDeclarations.length; i < n; i++) {
                            var node = typeParameterDeclarations[i];
                            checkTypeParameter(node);
                            if (produceDiagnostics) {
                                for (var j = 0; j < i; j++) {
                                    if (typeParameterDeclarations[j].symbol === node.symbol) {
                                        error(node.name, ts.Diagnostics.Duplicate_identifier_0, ts.declarationNameToString(node.name));
                                    }
                                }
                            }
                        }
                    }
                }
                function checkClassExpression(node) {
                    grammarErrorOnNode(node, ts.Diagnostics.class_expressions_are_not_currently_supported);
                    ts.forEach(node.members, checkSourceElement);
                    return unknownType;
                }
                function checkClassDeclaration(node) {
                    checkGrammarDeclarationNameInStrictMode(node);
                    // Grammar checking
                    if (node.parent.kind !== 206 /* ModuleBlock */ && node.parent.kind !== 227 /* SourceFile */) {
                        grammarErrorOnNode(node, ts.Diagnostics.class_declarations_are_only_supported_directly_inside_a_module_or_as_a_top_level_declaration);
                    }
                    if (!node.name && !(node.flags & 256 /* Default */)) {
                        grammarErrorOnFirstToken(node, ts.Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name);
                    }
                    checkGrammarClassDeclarationHeritageClauses(node);
                    checkDecorators(node);
                    if (node.name) {
                        checkTypeNameIsReserved(node.name, ts.Diagnostics.Class_name_cannot_be_0);
                        checkCollisionWithCapturedThisVariable(node, node.name);
                        checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
                    }
                    checkTypeParameters(node.typeParameters);
                    checkExportsOnMergedDeclarations(node);
                    var symbol = getSymbolOfNode(node);
                    var type = getDeclaredTypeOfSymbol(symbol);
                    var staticType = getTypeOfSymbol(symbol);
                    var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node);
                    if (baseTypeNode) {
                        if (!ts.isSupportedHeritageClauseElement(baseTypeNode)) {
                            error(baseTypeNode.expression, ts.Diagnostics.Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_class_extends_clauses);
                        }
                        emitExtends = emitExtends || !ts.isInAmbientContext(node);
                        checkHeritageClauseElement(baseTypeNode);
                    }
                    var baseTypes = getBaseTypes(type);
                    if (baseTypes.length) {
                        if (produceDiagnostics) {
                            var baseType = baseTypes[0];
                            checkTypeAssignableTo(type, baseType, node.name || node, ts.Diagnostics.Class_0_incorrectly_extends_base_class_1);
                            var staticBaseType = getTypeOfSymbol(baseType.symbol);
                            checkTypeAssignableTo(staticType, getTypeWithoutConstructors(staticBaseType), node.name || node, ts.Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
                            if (baseType.symbol !== resolveEntityName(baseTypeNode.expression, 107455 /* Value */)) {
                                error(baseTypeNode, ts.Diagnostics.Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0, typeToString(baseType));
                            }
                            checkKindsOfPropertyMemberOverrides(type, baseType);
                        }
                    }
                    if (baseTypes.length || (baseTypeNode && compilerOptions.separateCompilation)) {
                        // Check that base type can be evaluated as expression
                        checkExpressionOrQualifiedName(baseTypeNode.expression);
                    }
                    var implementedTypeNodes = ts.getClassImplementsHeritageClauseElements(node);
                    if (implementedTypeNodes) {
                        ts.forEach(implementedTypeNodes, function (typeRefNode) {
                            if (!ts.isSupportedHeritageClauseElement(typeRefNode)) {
                                error(typeRefNode.expression, ts.Diagnostics.A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments);
                            }
                            checkHeritageClauseElement(typeRefNode);
                            if (produceDiagnostics) {
                                var t = getTypeFromHeritageClauseElement(typeRefNode);
                                if (t !== unknownType) {
                                    var declaredType = (t.flags & 4096 /* Reference */) ? t.target : t;
                                    if (declaredType.flags & (1024 /* Class */ | 2048 /* Interface */)) {
                                        checkTypeAssignableTo(type, t, node.name || node, ts.Diagnostics.Class_0_incorrectly_implements_interface_1);
                                    }
                                    else {
                                        error(typeRefNode, ts.Diagnostics.A_class_may_only_implement_another_class_or_interface);
                                    }
                                }
                            }
                        });
                    }
                    ts.forEach(node.members, checkSourceElement);
                    if (produceDiagnostics) {
                        checkIndexConstraints(type);
                        checkTypeForDuplicateIndexSignatures(node);
                    }
                }
                function getTargetSymbol(s) {
                    // if symbol is instantiated its flags are not copied from the 'target'
                    // so we'll need to get back original 'target' symbol to work with correct set of flags
                    return s.flags & 16777216 /* Instantiated */ ? getSymbolLinks(s).target : s;
                }
                function checkKindsOfPropertyMemberOverrides(type, baseType) {
                    // TypeScript 1.0 spec (April 2014): 8.2.3
                    // A derived class inherits all members from its base class it doesn't override.
                    // Inheritance means that a derived class implicitly contains all non - overridden members of the base class.
                    // Both public and private property members are inherited, but only public property members can be overridden.
                    // A property member in a derived class is said to override a property member in a base class
                    // when the derived class property member has the same name and kind(instance or static)
                    // as the base class property member.
                    // The type of an overriding property member must be assignable(section 3.8.4)
                    // to the type of the overridden property member, or otherwise a compile - time error occurs.
                    // Base class instance member functions can be overridden by derived class instance member functions,
                    // but not by other kinds of members.
                    // Base class instance member variables and accessors can be overridden by
                    // derived class instance member variables and accessors, but not by other kinds of members.
                    // NOTE: assignability is checked in checkClassDeclaration
                    var baseProperties = getPropertiesOfObjectType(baseType);
                    for (var _i = 0; _i < baseProperties.length; _i++) {
                        var baseProperty = baseProperties[_i];
                        var base = getTargetSymbol(baseProperty);
                        if (base.flags & 134217728 /* Prototype */) {
                            continue;
                        }
                        var derived = getTargetSymbol(getPropertyOfObjectType(type, base.name));
                        if (derived) {
                            var baseDeclarationFlags = getDeclarationFlagsFromSymbol(base);
                            var derivedDeclarationFlags = getDeclarationFlagsFromSymbol(derived);
                            if ((baseDeclarationFlags & 32 /* Private */) || (derivedDeclarationFlags & 32 /* Private */)) {
                                // either base or derived property is private - not override, skip it
                                continue;
                            }
                            if ((baseDeclarationFlags & 128 /* Static */) !== (derivedDeclarationFlags & 128 /* Static */)) {
                                // value of 'static' is not the same for properties - not override, skip it
                                continue;
                            }
                            if ((base.flags & derived.flags & 8192 /* Method */) || ((base.flags & 98308 /* PropertyOrAccessor */) && (derived.flags & 98308 /* PropertyOrAccessor */))) {
                                // method is overridden with method or property/accessor is overridden with property/accessor - correct case
                                continue;
                            }
                            var errorMessage = void 0;
                            if (base.flags & 8192 /* Method */) {
                                if (derived.flags & 98304 /* Accessor */) {
                                    errorMessage = ts.Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor;
                                }
                                else {
                                    ts.Debug.assert((derived.flags & 4 /* Property */) !== 0);
                                    errorMessage = ts.Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property;
                                }
                            }
                            else if (base.flags & 4 /* Property */) {
                                ts.Debug.assert((derived.flags & 8192 /* Method */) !== 0);
                                errorMessage = ts.Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function;
                            }
                            else {
                                ts.Debug.assert((base.flags & 98304 /* Accessor */) !== 0);
                                ts.Debug.assert((derived.flags & 8192 /* Method */) !== 0);
                                errorMessage = ts.Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function;
                            }
                            error(derived.valueDeclaration.name, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type));
                        }
                    }
                }
                function isAccessor(kind) {
                    return kind === 136 /* GetAccessor */ || kind === 137 /* SetAccessor */;
                }
                function areTypeParametersIdentical(list1, list2) {
                    if (!list1 && !list2) {
                        return true;
                    }
                    if (!list1 || !list2 || list1.length !== list2.length) {
                        return false;
                    }
                    // TypeScript 1.0 spec (April 2014):
                    // When a generic interface has multiple declarations,  all declarations must have identical type parameter
                    // lists, i.e. identical type parameter names with identical constraints in identical order.
                    for (var i = 0, len = list1.length; i < len; i++) {
                        var tp1 = list1[i];
                        var tp2 = list2[i];
                        if (tp1.name.text !== tp2.name.text) {
                            return false;
                        }
                        if (!tp1.constraint && !tp2.constraint) {
                            continue;
                        }
                        if (!tp1.constraint || !tp2.constraint) {
                            return false;
                        }
                        if (!isTypeIdenticalTo(getTypeFromTypeNode(tp1.constraint), getTypeFromTypeNode(tp2.constraint))) {
                            return false;
                        }
                    }
                    return true;
                }
                function checkInheritedPropertiesAreIdentical(type, typeNode) {
                    var baseTypes = getBaseTypes(type);
                    if (baseTypes.length < 2) {
                        return true;
                    }
                    var seen = {};
                    ts.forEach(resolveDeclaredMembers(type).declaredProperties, function (p) { seen[p.name] = { prop: p, containingType: type }; });
                    var ok = true;
                    for (var _i = 0; _i < baseTypes.length; _i++) {
                        var base = baseTypes[_i];
                        var properties = getPropertiesOfObjectType(base);
                        for (var _a = 0; _a < properties.length; _a++) {
                            var prop = properties[_a];
                            if (!ts.hasProperty(seen, prop.name)) {
                                seen[prop.name] = { prop: prop, containingType: base };
                            }
                            else {
                                var existing = seen[prop.name];
                                var isInheritedProperty = existing.containingType !== type;
                                if (isInheritedProperty && !isPropertyIdenticalTo(existing.prop, prop)) {
                                    ok = false;
                                    var typeName1 = typeToString(existing.containingType);
                                    var typeName2 = typeToString(base);
                                    var errorInfo = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Named_property_0_of_types_1_and_2_are_not_identical, symbolToString(prop), typeName1, typeName2);
                                    errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2);
                                    diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(typeNode, errorInfo));
                                }
                            }
                        }
                    }
                    return ok;
                }
                function checkInterfaceDeclaration(node) {
                    // Grammar checking
                    checkGrammarDeclarationNameInStrictMode(node) || checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarInterfaceDeclaration(node);
                    checkTypeParameters(node.typeParameters);
                    if (produceDiagnostics) {
                        checkTypeNameIsReserved(node.name, ts.Diagnostics.Interface_name_cannot_be_0);
                        checkExportsOnMergedDeclarations(node);
                        var symbol = getSymbolOfNode(node);
                        var firstInterfaceDecl = ts.getDeclarationOfKind(symbol, 202 /* InterfaceDeclaration */);
                        if (symbol.declarations.length > 1) {
                            if (node !== firstInterfaceDecl && !areTypeParametersIdentical(firstInterfaceDecl.typeParameters, node.typeParameters)) {
                                error(node.name, ts.Diagnostics.All_declarations_of_an_interface_must_have_identical_type_parameters);
                            }
                        }
                        // Only check this symbol once
                        if (node === firstInterfaceDecl) {
                            var type = getDeclaredTypeOfSymbol(symbol);
                            // run subsequent checks only if first set succeeded
                            if (checkInheritedPropertiesAreIdentical(type, node.name)) {
                                ts.forEach(getBaseTypes(type), function (baseType) {
                                    checkTypeAssignableTo(type, baseType, node.name, ts.Diagnostics.Interface_0_incorrectly_extends_interface_1);
                                });
                                checkIndexConstraints(type);
                            }
                        }
                    }
                    ts.forEach(ts.getInterfaceBaseTypeNodes(node), function (heritageElement) {
                        if (!ts.isSupportedHeritageClauseElement(heritageElement)) {
                            error(heritageElement.expression, ts.Diagnostics.An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments);
                        }
                        checkHeritageClauseElement(heritageElement);
                    });
                    ts.forEach(node.members, checkSourceElement);
                    if (produceDiagnostics) {
                        checkTypeForDuplicateIndexSignatures(node);
                    }
                }
                function checkTypeAliasDeclaration(node) {
                    // Grammar checking
                    checkGrammarDecorators(node) || checkGrammarModifiers(node);
                    checkTypeNameIsReserved(node.name, ts.Diagnostics.Type_alias_name_cannot_be_0);
                    checkSourceElement(node.type);
                }
                function computeEnumMemberValues(node) {
                    var nodeLinks = getNodeLinks(node);
                    if (!(nodeLinks.flags & 128 /* EnumValuesComputed */)) {
                        var enumSymbol = getSymbolOfNode(node);
                        var enumType = getDeclaredTypeOfSymbol(enumSymbol);
                        var autoValue = 0;
                        var ambient = ts.isInAmbientContext(node);
                        var enumIsConst = ts.isConst(node);
                        ts.forEach(node.members, function (member) {
                            if (member.name.kind !== 127 /* ComputedPropertyName */ && isNumericLiteralName(member.name.text)) {
                                error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name);
                            }
                            var initializer = member.initializer;
                            if (initializer) {
                                autoValue = getConstantValueForEnumMemberInitializer(initializer);
                                if (autoValue === undefined) {
                                    if (enumIsConst) {
                                        error(initializer, ts.Diagnostics.In_const_enum_declarations_member_initializer_must_be_constant_expression);
                                    }
                                    else if (!ambient) {
                                        // Only here do we need to check that the initializer is assignable to the enum type.
                                        // If it is a constant value (not undefined), it is syntactically constrained to be a number.
                                        // Also, we do not need to check this for ambients because there is already
                                        // a syntax error if it is not a constant.
                                        checkTypeAssignableTo(checkExpression(initializer), enumType, initializer, undefined);
                                    }
                                }
                                else if (enumIsConst) {
                                    if (isNaN(autoValue)) {
                                        error(initializer, ts.Diagnostics.const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN);
                                    }
                                    else if (!isFinite(autoValue)) {
                                        error(initializer, ts.Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value);
                                    }
                                }
                            }
                            else if (ambient && !enumIsConst) {
                                autoValue = undefined;
                            }
                            if (autoValue !== undefined) {
                                getNodeLinks(member).enumMemberValue = autoValue++;
                            }
                        });
                        nodeLinks.flags |= 128 /* EnumValuesComputed */;
                    }
                    function getConstantValueForEnumMemberInitializer(initializer) {
                        return evalConstant(initializer);
                        function evalConstant(e) {
                            switch (e.kind) {
                                case 167 /* PrefixUnaryExpression */:
                                    var value = evalConstant(e.operand);
                                    if (value === undefined) {
                                        return undefined;
                                    }
                                    switch (e.operator) {
                                        case 33 /* PlusToken */: return value;
                                        case 34 /* MinusToken */: return -value;
                                        case 47 /* TildeToken */: return ~value;
                                    }
                                    return undefined;
                                case 169 /* BinaryExpression */:
                                    var left = evalConstant(e.left);
                                    if (left === undefined) {
                                        return undefined;
                                    }
                                    var right = evalConstant(e.right);
                                    if (right === undefined) {
                                        return undefined;
                                    }
                                    switch (e.operatorToken.kind) {
                                        case 44 /* BarToken */: return left | right;
                                        case 43 /* AmpersandToken */: return left & right;
                                        case 41 /* GreaterThanGreaterThanToken */: return left >> right;
                                        case 42 /* GreaterThanGreaterThanGreaterThanToken */: return left >>> right;
                                        case 40 /* LessThanLessThanToken */: return left << right;
                                        case 45 /* CaretToken */: return left ^ right;
                                        case 35 /* AsteriskToken */: return left * right;
                                        case 36 /* SlashToken */: return left / right;
                                        case 33 /* PlusToken */: return left + right;
                                        case 34 /* MinusToken */: return left - right;
                                        case 37 /* PercentToken */: return left % right;
                                    }
                                    return undefined;
                                case 7 /* NumericLiteral */:
                                    return +e.text;
                                case 161 /* ParenthesizedExpression */:
                                    return evalConstant(e.expression);
                                case 65 /* Identifier */:
                                case 156 /* ElementAccessExpression */:
                                case 155 /* PropertyAccessExpression */:
                                    var member = initializer.parent;
                                    var currentType = getTypeOfSymbol(getSymbolOfNode(member.parent));
                                    var enumType;
                                    var propertyName;
                                    if (e.kind === 65 /* Identifier */) {
                                        // unqualified names can refer to member that reside in different declaration of the enum so just doing name resolution won't work.
                                        // instead pick current enum type and later try to fetch member from the type
                                        enumType = currentType;
                                        propertyName = e.text;
                                    }
                                    else {
                                        var expression;
                                        if (e.kind === 156 /* ElementAccessExpression */) {
                                            if (e.argumentExpression === undefined ||
                                                e.argumentExpression.kind !== 8 /* StringLiteral */) {
                                                return undefined;
                                            }
                                            expression = e.expression;
                                            propertyName = e.argumentExpression.text;
                                        }
                                        else {
                                            expression = e.expression;
                                            propertyName = e.name.text;
                                        }
                                        // expression part in ElementAccess\PropertyAccess should be either identifier or dottedName
                                        var current = expression;
                                        while (current) {
                                            if (current.kind === 65 /* Identifier */) {
                                                break;
                                            }
                                            else if (current.kind === 155 /* PropertyAccessExpression */) {
                                                current = current.expression;
                                            }
                                            else {
                                                return undefined;
                                            }
                                        }
                                        enumType = checkExpression(expression);
                                        // allow references to constant members of other enums
                                        if (!(enumType.symbol && (enumType.symbol.flags & 384 /* Enum */))) {
                                            return undefined;
                                        }
                                    }
                                    if (propertyName === undefined) {
                                        return undefined;
                                    }
                                    var property = getPropertyOfObjectType(enumType, propertyName);
                                    if (!property || !(property.flags & 8 /* EnumMember */)) {
                                        return undefined;
                                    }
                                    var propertyDecl = property.valueDeclaration;
                                    // self references are illegal
                                    if (member === propertyDecl) {
                                        return undefined;
                                    }
                                    // illegal case: forward reference
                                    if (!isDefinedBefore(propertyDecl, member)) {
                                        return undefined;
                                    }
                                    return getNodeLinks(propertyDecl).enumMemberValue;
                            }
                        }
                    }
                }
                function checkEnumDeclaration(node) {
                    if (!produceDiagnostics) {
                        return;
                    }
                    // Grammar checking
                    checkGrammarDeclarationNameInStrictMode(node) || checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarEnumDeclaration(node);
                    checkTypeNameIsReserved(node.name, ts.Diagnostics.Enum_name_cannot_be_0);
                    checkCollisionWithCapturedThisVariable(node, node.name);
                    checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
                    checkExportsOnMergedDeclarations(node);
                    computeEnumMemberValues(node);
                    var enumIsConst = ts.isConst(node);
                    if (compilerOptions.separateCompilation && enumIsConst && ts.isInAmbientContext(node)) {
                        error(node.name, ts.Diagnostics.Ambient_const_enums_are_not_allowed_when_the_separateCompilation_flag_is_provided);
                    }
                    // Spec 2014 - Section 9.3:
                    // It isn't possible for one enum declaration to continue the automatic numbering sequence of another,
                    // and when an enum type has multiple declarations, only one declaration is permitted to omit a value
                    // for the first member.
                    //
                    // Only perform this check once per symbol
                    var enumSymbol = getSymbolOfNode(node);
                    var firstDeclaration = ts.getDeclarationOfKind(enumSymbol, node.kind);
                    if (node === firstDeclaration) {
                        if (enumSymbol.declarations.length > 1) {
                            // check that const is placed\omitted on all enum declarations
                            ts.forEach(enumSymbol.declarations, function (decl) {
                                if (ts.isConstEnumDeclaration(decl) !== enumIsConst) {
                                    error(decl.name, ts.Diagnostics.Enum_declarations_must_all_be_const_or_non_const);
                                }
                            });
                        }
                        var seenEnumMissingInitialInitializer = false;
                        ts.forEach(enumSymbol.declarations, function (declaration) {
                            // return true if we hit a violation of the rule, false otherwise
                            if (declaration.kind !== 204 /* EnumDeclaration */) {
                                return false;
                            }
                            var enumDeclaration = declaration;
                            if (!enumDeclaration.members.length) {
                                return false;
                            }
                            var firstEnumMember = enumDeclaration.members[0];
                            if (!firstEnumMember.initializer) {
                                if (seenEnumMissingInitialInitializer) {
                                    error(firstEnumMember.name, ts.Diagnostics.In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element);
                                }
                                else {
                                    seenEnumMissingInitialInitializer = true;
                                }
                            }
                        });
                    }
                }
                function getFirstNonAmbientClassOrFunctionDeclaration(symbol) {
                    var declarations = symbol.declarations;
                    for (var _i = 0; _i < declarations.length; _i++) {
                        var declaration = declarations[_i];
                        if ((declaration.kind === 201 /* ClassDeclaration */ ||
                            (declaration.kind === 200 /* FunctionDeclaration */ && ts.nodeIsPresent(declaration.body))) &&
                            !ts.isInAmbientContext(declaration)) {
                            return declaration;
                        }
                    }
                    return undefined;
                }
                function inSameLexicalScope(node1, node2) {
                    var container1 = ts.getEnclosingBlockScopeContainer(node1);
                    var container2 = ts.getEnclosingBlockScopeContainer(node2);
                    if (isGlobalSourceFile(container1)) {
                        return isGlobalSourceFile(container2);
                    }
                    else if (isGlobalSourceFile(container2)) {
                        return false;
                    }
                    else {
                        return container1 === container2;
                    }
                }
                function checkModuleDeclaration(node) {
                    if (produceDiagnostics) {
                        // Grammar checking
                        if (!checkGrammarDeclarationNameInStrictMode(node) && !checkGrammarDecorators(node) && !checkGrammarModifiers(node)) {
                            if (!ts.isInAmbientContext(node) && node.name.kind === 8 /* StringLiteral */) {
                                grammarErrorOnNode(node.name, ts.Diagnostics.Only_ambient_modules_can_use_quoted_names);
                            }
                        }
                        checkCollisionWithCapturedThisVariable(node, node.name);
                        checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
                        checkExportsOnMergedDeclarations(node);
                        var symbol = getSymbolOfNode(node);
                        // The following checks only apply on a non-ambient instantiated module declaration.
                        if (symbol.flags & 512 /* ValueModule */
                            && symbol.declarations.length > 1
                            && !ts.isInAmbientContext(node)
                            && ts.isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.separateCompilation)) {
                            var firstNonAmbientClassOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol);
                            if (firstNonAmbientClassOrFunc) {
                                if (ts.getSourceFileOfNode(node) !== ts.getSourceFileOfNode(firstNonAmbientClassOrFunc)) {
                                    error(node.name, ts.Diagnostics.A_module_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged);
                                }
                                else if (node.pos < firstNonAmbientClassOrFunc.pos) {
                                    error(node.name, ts.Diagnostics.A_module_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged);
                                }
                            }
                            // if the module merges with a class declaration in the same lexical scope, 
                            // we need to track this to ensure the correct emit.
                            var mergedClass = ts.getDeclarationOfKind(symbol, 201 /* ClassDeclaration */);
                            if (mergedClass &&
                                inSameLexicalScope(node, mergedClass)) {
                                getNodeLinks(node).flags |= 2048 /* LexicalModuleMergesWithClass */;
                            }
                        }
                        // Checks for ambient external modules.
                        if (node.name.kind === 8 /* StringLiteral */) {
                            if (!isGlobalSourceFile(node.parent)) {
                                error(node.name, ts.Diagnostics.Ambient_external_modules_cannot_be_nested_in_other_modules);
                            }
                            if (isExternalModuleNameRelative(node.name.text)) {
                                error(node.name, ts.Diagnostics.Ambient_external_module_declaration_cannot_specify_relative_module_name);
                            }
                        }
                    }
                    checkSourceElement(node.body);
                }
                function getFirstIdentifier(node) {
                    while (true) {
                        if (node.kind === 126 /* QualifiedName */) {
                            node = node.left;
                        }
                        else if (node.kind === 155 /* PropertyAccessExpression */) {
                            node = node.expression;
                        }
                        else {
                            break;
                        }
                    }
                    ts.Debug.assert(node.kind === 65 /* Identifier */);
                    return node;
                }
                function checkExternalImportOrExportDeclaration(node) {
                    var moduleName = ts.getExternalModuleName(node);
                    if (!ts.nodeIsMissing(moduleName) && moduleName.kind !== 8 /* StringLiteral */) {
                        error(moduleName, ts.Diagnostics.String_literal_expected);
                        return false;
                    }
                    var inAmbientExternalModule = node.parent.kind === 206 /* ModuleBlock */ && node.parent.parent.name.kind === 8 /* StringLiteral */;
                    if (node.parent.kind !== 227 /* SourceFile */ && !inAmbientExternalModule) {
                        error(moduleName, node.kind === 215 /* ExportDeclaration */ ?
                            ts.Diagnostics.Export_declarations_are_not_permitted_in_an_internal_module :
                            ts.Diagnostics.Import_declarations_in_an_internal_module_cannot_reference_an_external_module);
                        return false;
                    }
                    if (inAmbientExternalModule && isExternalModuleNameRelative(moduleName.text)) {
                        // TypeScript 1.0 spec (April 2013): 12.1.6
                        // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference
                        // other external modules only through top - level external module names.
                        // Relative external module names are not permitted.
                        error(node, ts.Diagnostics.Import_or_export_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name);
                        return false;
                    }
                    return true;
                }
                function checkAliasSymbol(node) {
                    var symbol = getSymbolOfNode(node);
                    var target = resolveAlias(symbol);
                    if (target !== unknownSymbol) {
                        var excludedMeanings = (symbol.flags & 107455 /* Value */ ? 107455 /* Value */ : 0) |
                            (symbol.flags & 793056 /* Type */ ? 793056 /* Type */ : 0) |
                            (symbol.flags & 1536 /* Namespace */ ? 1536 /* Namespace */ : 0);
                        if (target.flags & excludedMeanings) {
                            var message = node.kind === 217 /* ExportSpecifier */ ?
                                ts.Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 :
                                ts.Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0;
                            error(node, message, symbolToString(symbol));
                        }
                    }
                }
                function checkImportBinding(node) {
                    checkCollisionWithCapturedThisVariable(node, node.name);
                    checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
                    checkAliasSymbol(node);
                }
                function checkImportDeclaration(node) {
                    if (!checkGrammarImportDeclarationNameInStrictMode(node) && !checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & 499 /* Modifier */)) {
                        grammarErrorOnFirstToken(node, ts.Diagnostics.An_import_declaration_cannot_have_modifiers);
                    }
                    if (checkExternalImportOrExportDeclaration(node)) {
                        var importClause = node.importClause;
                        if (importClause) {
                            if (importClause.name) {
                                checkImportBinding(importClause);
                            }
                            if (importClause.namedBindings) {
                                if (importClause.namedBindings.kind === 211 /* NamespaceImport */) {
                                    checkImportBinding(importClause.namedBindings);
                                }
                                else {
                                    ts.forEach(importClause.namedBindings.elements, checkImportBinding);
                                }
                            }
                        }
                    }
                }
                function checkImportEqualsDeclaration(node) {
                    checkGrammarDeclarationNameInStrictMode(node) || checkGrammarDecorators(node) || checkGrammarModifiers(node);
                    if (ts.isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) {
                        checkImportBinding(node);
                        if (node.flags & 1 /* Export */) {
                            markExportAsReferenced(node);
                        }
                        if (ts.isInternalModuleImportEqualsDeclaration(node)) {
                            var target = resolveAlias(getSymbolOfNode(node));
                            if (target !== unknownSymbol) {
                                if (target.flags & 107455 /* Value */) {
                                    // Target is a value symbol, check that it is not hidden by a local declaration with the same name
                                    var moduleName = getFirstIdentifier(node.moduleReference);
                                    if (!(resolveEntityName(moduleName, 107455 /* Value */ | 1536 /* Namespace */).flags & 1536 /* Namespace */)) {
                                        error(moduleName, ts.Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, ts.declarationNameToString(moduleName));
                                    }
                                }
                                if (target.flags & 793056 /* Type */) {
                                    checkTypeNameIsReserved(node.name, ts.Diagnostics.Import_name_cannot_be_0);
                                }
                            }
                        }
                        else {
                            if (languageVersion >= 2 /* ES6 */) {
                                // Import equals declaration is deprecated in es6 or above
                                grammarErrorOnNode(node, ts.Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_or_import_d_from_mod_instead);
                            }
                        }
                    }
                }
                function checkExportDeclaration(node) {
                    if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & 499 /* Modifier */)) {
                        grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_declaration_cannot_have_modifiers);
                    }
                    if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) {
                        if (node.exportClause) {
                            // export { x, y }
                            // export { x, y } from "foo"
                            ts.forEach(node.exportClause.elements, checkExportSpecifier);
                            var inAmbientExternalModule = node.parent.kind === 206 /* ModuleBlock */ && node.parent.parent.name.kind === 8 /* StringLiteral */;
                            if (node.parent.kind !== 227 /* SourceFile */ && !inAmbientExternalModule) {
                                error(node, ts.Diagnostics.Export_declarations_are_not_permitted_in_an_internal_module);
                            }
                        }
                        else {
                            // export * from "foo"
                            var moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier);
                            if (moduleSymbol && moduleSymbol.exports["export="]) {
                                error(node.moduleSpecifier, ts.Diagnostics.External_module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol));
                            }
                        }
                    }
                }
                function checkExportSpecifier(node) {
                    checkAliasSymbol(node);
                    if (!node.parent.parent.moduleSpecifier) {
                        markExportAsReferenced(node);
                    }
                }
                function checkExportAssignment(node) {
                    var container = node.parent.kind === 227 /* SourceFile */ ? node.parent : node.parent.parent;
                    if (container.kind === 205 /* ModuleDeclaration */ && container.name.kind === 65 /* Identifier */) {
                        error(node, ts.Diagnostics.An_export_assignment_cannot_be_used_in_an_internal_module);
                        return;
                    }
                    // Grammar checking
                    if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & 499 /* Modifier */)) {
                        grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_assignment_cannot_have_modifiers);
                    }
                    if (node.expression.kind === 65 /* Identifier */) {
                        markExportAsReferenced(node);
                    }
                    else {
                        checkExpressionCached(node.expression);
                    }
                    checkExternalModuleExports(container);
                    if (node.isExportEquals && languageVersion >= 2 /* ES6 */) {
                        // export assignment is deprecated in es6 or above
                        grammarErrorOnNode(node, ts.Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_export_default_instead);
                    }
                }
                function getModuleStatements(node) {
                    if (node.kind === 227 /* SourceFile */) {
                        return node.statements;
                    }
                    if (node.kind === 205 /* ModuleDeclaration */ && node.body.kind === 206 /* ModuleBlock */) {
                        return node.body.statements;
                    }
                    return emptyArray;
                }
                function hasExportedMembers(moduleSymbol) {
                    for (var id in moduleSymbol.exports) {
                        if (id !== "export=") {
                            return true;
                        }
                    }
                    return false;
                }
                function checkExternalModuleExports(node) {
                    var moduleSymbol = getSymbolOfNode(node);
                    var links = getSymbolLinks(moduleSymbol);
                    if (!links.exportsChecked) {
                        var exportEqualsSymbol = moduleSymbol.exports["export="];
                        if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) {
                            var declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration;
                            error(declaration, ts.Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements);
                        }
                        links.exportsChecked = true;
                    }
                }
                function checkSourceElement(node) {
                    if (!node)
                        return;
                    switch (node.kind) {
                        case 128 /* TypeParameter */:
                            return checkTypeParameter(node);
                        case 129 /* Parameter */:
                            return checkParameter(node);
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                            return checkPropertyDeclaration(node);
                        case 142 /* FunctionType */:
                        case 143 /* ConstructorType */:
                        case 138 /* CallSignature */:
                        case 139 /* ConstructSignature */:
                            return checkSignatureDeclaration(node);
                        case 140 /* IndexSignature */:
                            return checkSignatureDeclaration(node);
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                            return checkMethodDeclaration(node);
                        case 135 /* Constructor */:
                            return checkConstructorDeclaration(node);
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                            return checkAccessorDeclaration(node);
                        case 141 /* TypeReference */:
                            return checkTypeReferenceNode(node);
                        case 144 /* TypeQuery */:
                            return checkTypeQuery(node);
                        case 145 /* TypeLiteral */:
                            return checkTypeLiteral(node);
                        case 146 /* ArrayType */:
                            return checkArrayType(node);
                        case 147 /* TupleType */:
                            return checkTupleType(node);
                        case 148 /* UnionType */:
                            return checkUnionType(node);
                        case 149 /* ParenthesizedType */:
                            return checkSourceElement(node.type);
                        case 200 /* FunctionDeclaration */:
                            return checkFunctionDeclaration(node);
                        case 179 /* Block */:
                        case 206 /* ModuleBlock */:
                            return checkBlock(node);
                        case 180 /* VariableStatement */:
                            return checkVariableStatement(node);
                        case 182 /* ExpressionStatement */:
                            return checkExpressionStatement(node);
                        case 183 /* IfStatement */:
                            return checkIfStatement(node);
                        case 184 /* DoStatement */:
                            return checkDoStatement(node);
                        case 185 /* WhileStatement */:
                            return checkWhileStatement(node);
                        case 186 /* ForStatement */:
                            return checkForStatement(node);
                        case 187 /* ForInStatement */:
                            return checkForInStatement(node);
                        case 188 /* ForOfStatement */:
                            return checkForOfStatement(node);
                        case 189 /* ContinueStatement */:
                        case 190 /* BreakStatement */:
                            return checkBreakOrContinueStatement(node);
                        case 191 /* ReturnStatement */:
                            return checkReturnStatement(node);
                        case 192 /* WithStatement */:
                            return checkWithStatement(node);
                        case 193 /* SwitchStatement */:
                            return checkSwitchStatement(node);
                        case 194 /* LabeledStatement */:
                            return checkLabeledStatement(node);
                        case 195 /* ThrowStatement */:
                            return checkThrowStatement(node);
                        case 196 /* TryStatement */:
                            return checkTryStatement(node);
                        case 198 /* VariableDeclaration */:
                            return checkVariableDeclaration(node);
                        case 152 /* BindingElement */:
                            return checkBindingElement(node);
                        case 201 /* ClassDeclaration */:
                            return checkClassDeclaration(node);
                        case 202 /* InterfaceDeclaration */:
                            return checkInterfaceDeclaration(node);
                        case 203 /* TypeAliasDeclaration */:
                            return checkTypeAliasDeclaration(node);
                        case 204 /* EnumDeclaration */:
                            return checkEnumDeclaration(node);
                        case 205 /* ModuleDeclaration */:
                            return checkModuleDeclaration(node);
                        case 209 /* ImportDeclaration */:
                            return checkImportDeclaration(node);
                        case 208 /* ImportEqualsDeclaration */:
                            return checkImportEqualsDeclaration(node);
                        case 215 /* ExportDeclaration */:
                            return checkExportDeclaration(node);
                        case 214 /* ExportAssignment */:
                            return checkExportAssignment(node);
                        case 181 /* EmptyStatement */:
                            checkGrammarStatementInAmbientContext(node);
                            return;
                        case 197 /* DebuggerStatement */:
                            checkGrammarStatementInAmbientContext(node);
                            return;
                        case 218 /* MissingDeclaration */:
                            return checkMissingDeclaration(node);
                    }
                }
                // Function expression bodies are checked after all statements in the enclosing body. This is to ensure
                // constructs like the following are permitted:
                //     let foo = function () {
                //        let s = foo();
                //        return "hello";
                //     }
                // Here, performing a full type check of the body of the function expression whilst in the process of
                // determining the type of foo would cause foo to be given type any because of the recursive reference.
                // Delaying the type check of the body ensures foo has been assigned a type.
                function checkFunctionExpressionBodies(node) {
                    switch (node.kind) {
                        case 162 /* FunctionExpression */:
                        case 163 /* ArrowFunction */:
                            ts.forEach(node.parameters, checkFunctionExpressionBodies);
                            checkFunctionExpressionOrObjectLiteralMethodBody(node);
                            break;
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                            ts.forEach(node.parameters, checkFunctionExpressionBodies);
                            if (ts.isObjectLiteralMethod(node)) {
                                checkFunctionExpressionOrObjectLiteralMethodBody(node);
                            }
                            break;
                        case 135 /* Constructor */:
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                        case 200 /* FunctionDeclaration */:
                            ts.forEach(node.parameters, checkFunctionExpressionBodies);
                            break;
                        case 192 /* WithStatement */:
                            checkFunctionExpressionBodies(node.expression);
                            break;
                        case 129 /* Parameter */:
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                        case 150 /* ObjectBindingPattern */:
                        case 151 /* ArrayBindingPattern */:
                        case 152 /* BindingElement */:
                        case 153 /* ArrayLiteralExpression */:
                        case 154 /* ObjectLiteralExpression */:
                        case 224 /* PropertyAssignment */:
                        case 155 /* PropertyAccessExpression */:
                        case 156 /* ElementAccessExpression */:
                        case 157 /* CallExpression */:
                        case 158 /* NewExpression */:
                        case 159 /* TaggedTemplateExpression */:
                        case 171 /* TemplateExpression */:
                        case 176 /* TemplateSpan */:
                        case 160 /* TypeAssertionExpression */:
                        case 161 /* ParenthesizedExpression */:
                        case 165 /* TypeOfExpression */:
                        case 166 /* VoidExpression */:
                        case 164 /* DeleteExpression */:
                        case 167 /* PrefixUnaryExpression */:
                        case 168 /* PostfixUnaryExpression */:
                        case 169 /* BinaryExpression */:
                        case 170 /* ConditionalExpression */:
                        case 173 /* SpreadElementExpression */:
                        case 179 /* Block */:
                        case 206 /* ModuleBlock */:
                        case 180 /* VariableStatement */:
                        case 182 /* ExpressionStatement */:
                        case 183 /* IfStatement */:
                        case 184 /* DoStatement */:
                        case 185 /* WhileStatement */:
                        case 186 /* ForStatement */:
                        case 187 /* ForInStatement */:
                        case 188 /* ForOfStatement */:
                        case 189 /* ContinueStatement */:
                        case 190 /* BreakStatement */:
                        case 191 /* ReturnStatement */:
                        case 193 /* SwitchStatement */:
                        case 207 /* CaseBlock */:
                        case 220 /* CaseClause */:
                        case 221 /* DefaultClause */:
                        case 194 /* LabeledStatement */:
                        case 195 /* ThrowStatement */:
                        case 196 /* TryStatement */:
                        case 223 /* CatchClause */:
                        case 198 /* VariableDeclaration */:
                        case 199 /* VariableDeclarationList */:
                        case 201 /* ClassDeclaration */:
                        case 204 /* EnumDeclaration */:
                        case 226 /* EnumMember */:
                        case 214 /* ExportAssignment */:
                        case 227 /* SourceFile */:
                            ts.forEachChild(node, checkFunctionExpressionBodies);
                            break;
                    }
                }
                function checkSourceFile(node) {
                    var start = new Date().getTime();
                    checkSourceFileWorker(node);
                    ts.checkTime += new Date().getTime() - start;
                }
                // Fully type check a source file and collect the relevant diagnostics.
                function checkSourceFileWorker(node) {
                    var links = getNodeLinks(node);
                    if (!(links.flags & 1 /* TypeChecked */)) {
                        // Grammar checking
                        checkGrammarSourceFile(node);
                        emitExtends = false;
                        emitDecorate = false;
                        emitParam = false;
                        potentialThisCollisions.length = 0;
                        ts.forEach(node.statements, checkSourceElement);
                        checkFunctionExpressionBodies(node);
                        if (ts.isExternalModule(node)) {
                            checkExternalModuleExports(node);
                        }
                        if (potentialThisCollisions.length) {
                            ts.forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope);
                            potentialThisCollisions.length = 0;
                        }
                        if (emitExtends) {
                            links.flags |= 8 /* EmitExtends */;
                        }
                        if (emitDecorate) {
                            links.flags |= 512 /* EmitDecorate */;
                        }
                        if (emitParam) {
                            links.flags |= 1024 /* EmitParam */;
                        }
                        links.flags |= 1 /* TypeChecked */;
                    }
                }
                function getDiagnostics(sourceFile) {
                    throwIfNonDiagnosticsProducing();
                    if (sourceFile) {
                        checkSourceFile(sourceFile);
                        return diagnostics.getDiagnostics(sourceFile.fileName);
                    }
                    ts.forEach(host.getSourceFiles(), checkSourceFile);
                    return diagnostics.getDiagnostics();
                }
                function getGlobalDiagnostics() {
                    throwIfNonDiagnosticsProducing();
                    return diagnostics.getGlobalDiagnostics();
                }
                function throwIfNonDiagnosticsProducing() {
                    if (!produceDiagnostics) {
                        throw new Error("Trying to get diagnostics from a type checker that does not produce them.");
                    }
                }
                // Language service support
                function isInsideWithStatementBody(node) {
                    if (node) {
                        while (node.parent) {
                            if (node.parent.kind === 192 /* WithStatement */ && node.parent.statement === node) {
                                return true;
                            }
                            node = node.parent;
                        }
                    }
                    return false;
                }
                function getSymbolsInScope(location, meaning) {
                    var symbols = {};
                    var memberFlags = 0;
                    if (isInsideWithStatementBody(location)) {
                        // We cannot answer semantic questions within a with block, do not proceed any further
                        return [];
                    }
                    populateSymbols();
                    return symbolsToArray(symbols);
                    function populateSymbols() {
                        while (location) {
                            if (location.locals && !isGlobalSourceFile(location)) {
                                copySymbols(location.locals, meaning);
                            }
                            switch (location.kind) {
                                case 227 /* SourceFile */:
                                    if (!ts.isExternalModule(location)) {
                                        break;
                                    }
                                case 205 /* ModuleDeclaration */:
                                    copySymbols(getSymbolOfNode(location).exports, meaning & 8914931 /* ModuleMember */);
                                    break;
                                case 204 /* EnumDeclaration */:
                                    copySymbols(getSymbolOfNode(location).exports, meaning & 8 /* EnumMember */);
                                    break;
                                case 201 /* ClassDeclaration */:
                                case 202 /* InterfaceDeclaration */:
                                    if (!(memberFlags & 128 /* Static */)) {
                                        copySymbols(getSymbolOfNode(location).members, meaning & 793056 /* Type */);
                                    }
                                    break;
                                case 162 /* FunctionExpression */:
                                    if (location.name) {
                                        copySymbol(location.symbol, meaning);
                                    }
                                    break;
                            }
                            memberFlags = location.flags;
                            location = location.parent;
                        }
                        copySymbols(globals, meaning);
                    }
                    // Returns 'true' if we should stop processing symbols.
                    function copySymbol(symbol, meaning) {
                        if (symbol.flags & meaning) {
                            var id = symbol.name;
                            if (!isReservedMemberName(id) && !ts.hasProperty(symbols, id)) {
                                symbols[id] = symbol;
                            }
                        }
                    }
                    function copySymbols(source, meaning) {
                        if (meaning) {
                            for (var id in source) {
                                if (ts.hasProperty(source, id)) {
                                    copySymbol(source[id], meaning);
                                }
                            }
                        }
                    }
                    if (isInsideWithStatementBody(location)) {
                        // We cannot answer semantic questions within a with block, do not proceed any further
                        return [];
                    }
                    while (location) {
                        if (location.locals && !isGlobalSourceFile(location)) {
                            copySymbols(location.locals, meaning);
                        }
                        switch (location.kind) {
                            case 227 /* SourceFile */:
                                if (!ts.isExternalModule(location))
                                    break;
                            case 205 /* ModuleDeclaration */:
                                copySymbols(getSymbolOfNode(location).exports, meaning & 8914931 /* ModuleMember */);
                                break;
                            case 204 /* EnumDeclaration */:
                                copySymbols(getSymbolOfNode(location).exports, meaning & 8 /* EnumMember */);
                                break;
                            case 201 /* ClassDeclaration */:
                            case 202 /* InterfaceDeclaration */:
                                if (!(memberFlags & 128 /* Static */)) {
                                    copySymbols(getSymbolOfNode(location).members, meaning & 793056 /* Type */);
                                }
                                break;
                            case 162 /* FunctionExpression */:
                                if (location.name) {
                                    copySymbol(location.symbol, meaning);
                                }
                                break;
                        }
                        memberFlags = location.flags;
                        location = location.parent;
                    }
                    copySymbols(globals, meaning);
                    return symbolsToArray(symbols);
                }
                function isTypeDeclarationName(name) {
                    return name.kind == 65 /* Identifier */ &&
                        isTypeDeclaration(name.parent) &&
                        name.parent.name === name;
                }
                function isTypeDeclaration(node) {
                    switch (node.kind) {
                        case 128 /* TypeParameter */:
                        case 201 /* ClassDeclaration */:
                        case 202 /* InterfaceDeclaration */:
                        case 203 /* TypeAliasDeclaration */:
                        case 204 /* EnumDeclaration */:
                            return true;
                    }
                }
                // True if the given identifier is part of a type reference
                function isTypeReferenceIdentifier(entityName) {
                    var node = entityName;
                    while (node.parent && node.parent.kind === 126 /* QualifiedName */) {
                        node = node.parent;
                    }
                    return node.parent && node.parent.kind === 141 /* TypeReference */;
                }
                function isHeritageClauseElementIdentifier(entityName) {
                    var node = entityName;
                    while (node.parent && node.parent.kind === 155 /* PropertyAccessExpression */) {
                        node = node.parent;
                    }
                    return node.parent && node.parent.kind === 177 /* HeritageClauseElement */;
                }
                function isTypeNode(node) {
                    if (141 /* FirstTypeNode */ <= node.kind && node.kind <= 149 /* LastTypeNode */) {
                        return true;
                    }
                    switch (node.kind) {
                        case 112 /* AnyKeyword */:
                        case 119 /* NumberKeyword */:
                        case 121 /* StringKeyword */:
                        case 113 /* BooleanKeyword */:
                        case 122 /* SymbolKeyword */:
                            return true;
                        case 99 /* VoidKeyword */:
                            return node.parent.kind !== 166 /* VoidExpression */;
                        case 8 /* StringLiteral */:
                            // Specialized signatures can have string literals as their parameters' type names
                            return node.parent.kind === 129 /* Parameter */;
                        case 177 /* HeritageClauseElement */:
                            return true;
                        // Identifiers and qualified names may be type nodes, depending on their context. Climb
                        // above them to find the lowest container
                        case 65 /* Identifier */:
                            // If the identifier is the RHS of a qualified name, then it's a type iff its parent is.
                            if (node.parent.kind === 126 /* QualifiedName */ && node.parent.right === node) {
                                node = node.parent;
                            }
                            else if (node.parent.kind === 155 /* PropertyAccessExpression */ && node.parent.name === node) {
                                node = node.parent;
                            }
                        // fall through
                        case 126 /* QualifiedName */:
                        case 155 /* PropertyAccessExpression */:
                            // At this point, node is either a qualified name or an identifier
                            ts.Debug.assert(node.kind === 65 /* Identifier */ || node.kind === 126 /* QualifiedName */ || node.kind === 155 /* PropertyAccessExpression */, "'node' was expected to be a qualified name, identifier or property access in 'isTypeNode'.");
                            var parent_5 = node.parent;
                            if (parent_5.kind === 144 /* TypeQuery */) {
                                return false;
                            }
                            // Do not recursively call isTypeNode on the parent. In the example:
                            //
                            //     let a: A.B.C;
                            //
                            // Calling isTypeNode would consider the qualified name A.B a type node. Only C or
                            // A.B.C is a type node.
                            if (141 /* FirstTypeNode */ <= parent_5.kind && parent_5.kind <= 149 /* LastTypeNode */) {
                                return true;
                            }
                            switch (parent_5.kind) {
                                case 177 /* HeritageClauseElement */:
                                    return true;
                                case 128 /* TypeParameter */:
                                    return node === parent_5.constraint;
                                case 132 /* PropertyDeclaration */:
                                case 131 /* PropertySignature */:
                                case 129 /* Parameter */:
                                case 198 /* VariableDeclaration */:
                                    return node === parent_5.type;
                                case 200 /* FunctionDeclaration */:
                                case 162 /* FunctionExpression */:
                                case 163 /* ArrowFunction */:
                                case 135 /* Constructor */:
                                case 134 /* MethodDeclaration */:
                                case 133 /* MethodSignature */:
                                case 136 /* GetAccessor */:
                                case 137 /* SetAccessor */:
                                    return node === parent_5.type;
                                case 138 /* CallSignature */:
                                case 139 /* ConstructSignature */:
                                case 140 /* IndexSignature */:
                                    return node === parent_5.type;
                                case 160 /* TypeAssertionExpression */:
                                    return node === parent_5.type;
                                case 157 /* CallExpression */:
                                case 158 /* NewExpression */:
                                    return parent_5.typeArguments && ts.indexOf(parent_5.typeArguments, node) >= 0;
                                case 159 /* TaggedTemplateExpression */:
                                    // TODO (drosen): TaggedTemplateExpressions may eventually support type arguments.
                                    return false;
                            }
                    }
                    return false;
                }
                function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide) {
                    while (nodeOnRightSide.parent.kind === 126 /* QualifiedName */) {
                        nodeOnRightSide = nodeOnRightSide.parent;
                    }
                    if (nodeOnRightSide.parent.kind === 208 /* ImportEqualsDeclaration */) {
                        return nodeOnRightSide.parent.moduleReference === nodeOnRightSide && nodeOnRightSide.parent;
                    }
                    if (nodeOnRightSide.parent.kind === 214 /* ExportAssignment */) {
                        return nodeOnRightSide.parent.expression === nodeOnRightSide && nodeOnRightSide.parent;
                    }
                    return undefined;
                }
                function isInRightSideOfImportOrExportAssignment(node) {
                    return getLeftSideOfImportEqualsOrExportAssignment(node) !== undefined;
                }
                function getSymbolOfEntityNameOrPropertyAccessExpression(entityName) {
                    if (ts.isDeclarationName(entityName)) {
                        return getSymbolOfNode(entityName.parent);
                    }
                    if (entityName.parent.kind === 214 /* ExportAssignment */) {
                        return resolveEntityName(entityName, 
                        /*all meanings*/ 107455 /* Value */ | 793056 /* Type */ | 1536 /* Namespace */ | 8388608 /* Alias */);
                    }
                    if (entityName.kind !== 155 /* PropertyAccessExpression */) {
                        if (isInRightSideOfImportOrExportAssignment(entityName)) {
                            // Since we already checked for ExportAssignment, this really could only be an Import
                            return getSymbolOfPartOfRightHandSideOfImportEquals(entityName);
                        }
                    }
                    if (ts.isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
                        entityName = entityName.parent;
                    }
                    if (isHeritageClauseElementIdentifier(entityName)) {
                        var meaning = entityName.parent.kind === 177 /* HeritageClauseElement */ ? 793056 /* Type */ : 1536 /* Namespace */;
                        meaning |= 8388608 /* Alias */;
                        return resolveEntityName(entityName, meaning);
                    }
                    else if (ts.isExpression(entityName)) {
                        if (ts.nodeIsMissing(entityName)) {
                            // Missing entity name.
                            return undefined;
                        }
                        if (entityName.kind === 65 /* Identifier */) {
                            // Include aliases in the meaning, this ensures that we do not follow aliases to where they point and instead
                            // return the alias symbol.
                            var meaning = 107455 /* Value */ | 8388608 /* Alias */;
                            return resolveEntityName(entityName, meaning);
                        }
                        else if (entityName.kind === 155 /* PropertyAccessExpression */) {
                            var symbol = getNodeLinks(entityName).resolvedSymbol;
                            if (!symbol) {
                                checkPropertyAccessExpression(entityName);
                            }
                            return getNodeLinks(entityName).resolvedSymbol;
                        }
                        else if (entityName.kind === 126 /* QualifiedName */) {
                            var symbol = getNodeLinks(entityName).resolvedSymbol;
                            if (!symbol) {
                                checkQualifiedName(entityName);
                            }
                            return getNodeLinks(entityName).resolvedSymbol;
                        }
                    }
                    else if (isTypeReferenceIdentifier(entityName)) {
                        var meaning = entityName.parent.kind === 141 /* TypeReference */ ? 793056 /* Type */ : 1536 /* Namespace */;
                        // Include aliases in the meaning, this ensures that we do not follow aliases to where they point and instead
                        // return the alias symbol.
                        meaning |= 8388608 /* Alias */;
                        return resolveEntityName(entityName, meaning);
                    }
                    // Do we want to return undefined here?
                    return undefined;
                }
                function getSymbolInfo(node) {
                    if (isInsideWithStatementBody(node)) {
                        // We cannot answer semantic questions within a with block, do not proceed any further
                        return undefined;
                    }
                    if (ts.isDeclarationName(node)) {
                        // This is a declaration, call getSymbolOfNode
                        return getSymbolOfNode(node.parent);
                    }
                    if (node.kind === 65 /* Identifier */ && isInRightSideOfImportOrExportAssignment(node)) {
                        return node.parent.kind === 214 /* ExportAssignment */
                            ? getSymbolOfEntityNameOrPropertyAccessExpression(node)
                            : getSymbolOfPartOfRightHandSideOfImportEquals(node);
                    }
                    switch (node.kind) {
                        case 65 /* Identifier */:
                        case 155 /* PropertyAccessExpression */:
                        case 126 /* QualifiedName */:
                            return getSymbolOfEntityNameOrPropertyAccessExpression(node);
                        case 93 /* ThisKeyword */:
                        case 91 /* SuperKeyword */:
                            var type = checkExpression(node);
                            return type.symbol;
                        case 114 /* ConstructorKeyword */:
                            // constructor keyword for an overload, should take us to the definition if it exist
                            var constructorDeclaration = node.parent;
                            if (constructorDeclaration && constructorDeclaration.kind === 135 /* Constructor */) {
                                return constructorDeclaration.parent.symbol;
                            }
                            return undefined;
                        case 8 /* StringLiteral */:
                            // External module name in an import declaration
                            var moduleName;
                            if ((ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) &&
                                ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) ||
                                ((node.parent.kind === 209 /* ImportDeclaration */ || node.parent.kind === 215 /* ExportDeclaration */) &&
                                    node.parent.moduleSpecifier === node)) {
                                return resolveExternalModuleName(node, node);
                            }
                        // Intentional fall-through
                        case 7 /* NumericLiteral */:
                            // index access
                            if (node.parent.kind == 156 /* ElementAccessExpression */ && node.parent.argumentExpression === node) {
                                var objectType = checkExpression(node.parent.expression);
                                if (objectType === unknownType)
                                    return undefined;
                                var apparentType = getApparentType(objectType);
                                if (apparentType === unknownType)
                                    return undefined;
                                return getPropertyOfType(apparentType, node.text);
                            }
                            break;
                    }
                    return undefined;
                }
                function getShorthandAssignmentValueSymbol(location) {
                    // The function returns a value symbol of an identifier in the short-hand property assignment.
                    // This is necessary as an identifier in short-hand property assignment can contains two meaning:
                    // property name and property value.
                    if (location && location.kind === 225 /* ShorthandPropertyAssignment */) {
                        return resolveEntityName(location.name, 107455 /* Value */);
                    }
                    return undefined;
                }
                function getTypeOfNode(node) {
                    if (isInsideWithStatementBody(node)) {
                        // We cannot answer semantic questions within a with block, do not proceed any further
                        return unknownType;
                    }
                    if (isTypeNode(node)) {
                        return getTypeFromTypeNode(node);
                    }
                    if (ts.isExpression(node)) {
                        return getTypeOfExpression(node);
                    }
                    if (isTypeDeclaration(node)) {
                        // In this case, we call getSymbolOfNode instead of getSymbolInfo because it is a declaration
                        var symbol = getSymbolOfNode(node);
                        return getDeclaredTypeOfSymbol(symbol);
                    }
                    if (isTypeDeclarationName(node)) {
                        var symbol = getSymbolInfo(node);
                        return symbol && getDeclaredTypeOfSymbol(symbol);
                    }
                    if (ts.isDeclaration(node)) {
                        // In this case, we call getSymbolOfNode instead of getSymbolInfo because it is a declaration
                        var symbol = getSymbolOfNode(node);
                        return getTypeOfSymbol(symbol);
                    }
                    if (ts.isDeclarationName(node)) {
                        var symbol = getSymbolInfo(node);
                        return symbol && getTypeOfSymbol(symbol);
                    }
                    if (isInRightSideOfImportOrExportAssignment(node)) {
                        var symbol = getSymbolInfo(node);
                        var declaredType = symbol && getDeclaredTypeOfSymbol(symbol);
                        return declaredType !== unknownType ? declaredType : getTypeOfSymbol(symbol);
                    }
                    return unknownType;
                }
                function getTypeOfExpression(expr) {
                    if (ts.isRightSideOfQualifiedNameOrPropertyAccess(expr)) {
                        expr = expr.parent;
                    }
                    return checkExpression(expr);
                }
                // Return the list of properties of the given type, augmented with properties from Function
                // if the type has call or construct signatures
                function getAugmentedPropertiesOfType(type) {
                    type = getApparentType(type);
                    var propsByName = createSymbolTable(getPropertiesOfType(type));
                    if (getSignaturesOfType(type, 0 /* Call */).length || getSignaturesOfType(type, 1 /* Construct */).length) {
                        ts.forEach(getPropertiesOfType(globalFunctionType), function (p) {
                            if (!ts.hasProperty(propsByName, p.name)) {
                                propsByName[p.name] = p;
                            }
                        });
                    }
                    return getNamedMembers(propsByName);
                }
                function getRootSymbols(symbol) {
                    if (symbol.flags & 268435456 /* UnionProperty */) {
                        var symbols = [];
                        var name_10 = symbol.name;
                        ts.forEach(getSymbolLinks(symbol).unionType.types, function (t) {
                            symbols.push(getPropertyOfType(t, name_10));
                        });
                        return symbols;
                    }
                    else if (symbol.flags & 67108864 /* Transient */) {
                        var target = getSymbolLinks(symbol).target;
                        if (target) {
                            return [target];
                        }
                    }
                    return [symbol];
                }
                // Emitter support
                function isExternalModuleSymbol(symbol) {
                    return symbol.flags & 512 /* ValueModule */ && symbol.declarations.length === 1 && symbol.declarations[0].kind === 227 /* SourceFile */;
                }
                function getAliasNameSubstitution(symbol, getGeneratedNameForNode) {
                    // If this is es6 or higher, just use the name of the export
                    // no need to qualify it.
                    if (languageVersion >= 2 /* ES6 */) {
                        return undefined;
                    }
                    var node = getDeclarationOfAliasSymbol(symbol);
                    if (node) {
                        if (node.kind === 210 /* ImportClause */) {
                            var defaultKeyword;
                            if (languageVersion === 0 /* ES3 */) {
                                defaultKeyword = "[\"default\"]";
                            }
                            else {
                                defaultKeyword = ".default";
                            }
                            return getGeneratedNameForNode(node.parent) + defaultKeyword;
                        }
                        if (node.kind === 213 /* ImportSpecifier */) {
                            var moduleName = getGeneratedNameForNode(node.parent.parent.parent);
                            var propertyName = node.propertyName || node.name;
                            return moduleName + "." + ts.unescapeIdentifier(propertyName.text);
                        }
                    }
                }
                function getExportNameSubstitution(symbol, location, getGeneratedNameForNode) {
                    if (isExternalModuleSymbol(symbol.parent)) {
                        // If this is es6 or higher, just use the name of the export
                        // no need to qualify it.
                        if (languageVersion >= 2 /* ES6 */) {
                            return undefined;
                        }
                        return "exports." + ts.unescapeIdentifier(symbol.name);
                    }
                    var node = location;
                    var containerSymbol = getParentOfSymbol(symbol);
                    while (node) {
                        if ((node.kind === 205 /* ModuleDeclaration */ || node.kind === 204 /* EnumDeclaration */) && getSymbolOfNode(node) === containerSymbol) {
                            return getGeneratedNameForNode(node) + "." + ts.unescapeIdentifier(symbol.name);
                        }
                        node = node.parent;
                    }
                }
                function getExpressionNameSubstitution(node, getGeneratedNameForNode) {
                    var symbol = getNodeLinks(node).resolvedSymbol || (ts.isDeclarationName(node) ? getSymbolOfNode(node.parent) : undefined);
                    if (symbol) {
                        // Whan an identifier resolves to a parented symbol, it references an exported entity from
                        // another declaration of the same internal module.
                        if (symbol.parent) {
                            return getExportNameSubstitution(symbol, node.parent, getGeneratedNameForNode);
                        }
                        // If we reference an exported entity within the same module declaration, then whether
                        // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the
                        // kinds that we do NOT prefix.
                        var exportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
                        if (symbol !== exportSymbol && !(exportSymbol.flags & 944 /* ExportHasLocal */)) {
                            return getExportNameSubstitution(exportSymbol, node.parent, getGeneratedNameForNode);
                        }
                        // Named imports from ES6 import declarations are rewritten
                        if (symbol.flags & 8388608 /* Alias */) {
                            return getAliasNameSubstitution(symbol, getGeneratedNameForNode);
                        }
                    }
                }
                function isValueAliasDeclaration(node) {
                    switch (node.kind) {
                        case 208 /* ImportEqualsDeclaration */:
                        case 210 /* ImportClause */:
                        case 211 /* NamespaceImport */:
                        case 213 /* ImportSpecifier */:
                        case 217 /* ExportSpecifier */:
                            return isAliasResolvedToValue(getSymbolOfNode(node));
                        case 215 /* ExportDeclaration */:
                            var exportClause = node.exportClause;
                            return exportClause && ts.forEach(exportClause.elements, isValueAliasDeclaration);
                        case 214 /* ExportAssignment */:
                            return node.expression && node.expression.kind === 65 /* Identifier */ ? isAliasResolvedToValue(getSymbolOfNode(node)) : true;
                    }
                    return false;
                }
                function isTopLevelValueImportEqualsWithEntityName(node) {
                    if (node.parent.kind !== 227 /* SourceFile */ || !ts.isInternalModuleImportEqualsDeclaration(node)) {
                        // parent is not source file or it is not reference to internal module
                        return false;
                    }
                    var isValue = isAliasResolvedToValue(getSymbolOfNode(node));
                    return isValue && node.moduleReference && !ts.nodeIsMissing(node.moduleReference);
                }
                function isAliasResolvedToValue(symbol) {
                    var target = resolveAlias(symbol);
                    if (target === unknownSymbol && compilerOptions.separateCompilation) {
                        return true;
                    }
                    // const enums and modules that contain only const enums are not considered values from the emit perespective
                    return target !== unknownSymbol && target && target.flags & 107455 /* Value */ && !isConstEnumOrConstEnumOnlyModule(target);
                }
                function isConstEnumOrConstEnumOnlyModule(s) {
                    return isConstEnumSymbol(s) || s.constEnumOnlyModule;
                }
                function isReferencedAliasDeclaration(node, checkChildren) {
                    if (ts.isAliasSymbolDeclaration(node)) {
                        var symbol = getSymbolOfNode(node);
                        if (getSymbolLinks(symbol).referenced) {
                            return true;
                        }
                    }
                    if (checkChildren) {
                        return ts.forEachChild(node, function (node) { return isReferencedAliasDeclaration(node, checkChildren); });
                    }
                    return false;
                }
                function isImplementationOfOverload(node) {
                    if (ts.nodeIsPresent(node.body)) {
                        var symbol = getSymbolOfNode(node);
                        var signaturesOfSymbol = getSignaturesOfSymbol(symbol);
                        // If this function body corresponds to function with multiple signature, it is implementation of overload
                        // e.g.: function foo(a: string): string;
                        //       function foo(a: number): number;
                        //       function foo(a: any) { // This is implementation of the overloads
                        //           return a;
                        //       }
                        return signaturesOfSymbol.length > 1 ||
                            // If there is single signature for the symbol, it is overload if that signature isn't coming from the node
                            // e.g.: function foo(a: string): string;
                            //       function foo(a: any) { // This is implementation of the overloads
                            //           return a;
                            //       }
                            (signaturesOfSymbol.length === 1 && signaturesOfSymbol[0].declaration !== node);
                    }
                    return false;
                }
                function getNodeCheckFlags(node) {
                    return getNodeLinks(node).flags;
                }
                function getEnumMemberValue(node) {
                    computeEnumMemberValues(node.parent);
                    return getNodeLinks(node).enumMemberValue;
                }
                function getConstantValue(node) {
                    if (node.kind === 226 /* EnumMember */) {
                        return getEnumMemberValue(node);
                    }
                    var symbol = getNodeLinks(node).resolvedSymbol;
                    if (symbol && (symbol.flags & 8 /* EnumMember */)) {
                        // inline property\index accesses only for const enums
                        if (ts.isConstEnumDeclaration(symbol.valueDeclaration.parent)) {
                            return getEnumMemberValue(symbol.valueDeclaration);
                        }
                    }
                    return undefined;
                }
                /** Serializes an EntityName (with substitutions) to an appropriate JS constructor value. Used by the __metadata decorator. */
                function serializeEntityName(node, getGeneratedNameForNode, fallbackPath) {
                    if (node.kind === 65 /* Identifier */) {
                        var substitution = getExpressionNameSubstitution(node, getGeneratedNameForNode);
                        var text = substitution || node.text;
                        if (fallbackPath) {
                            fallbackPath.push(text);
                        }
                        else {
                            return text;
                        }
                    }
                    else {
                        var left = serializeEntityName(node.left, getGeneratedNameForNode, fallbackPath);
                        var right = serializeEntityName(node.right, getGeneratedNameForNode, fallbackPath);
                        if (!fallbackPath) {
                            return left + "." + right;
                        }
                    }
                }
                /** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */
                function serializeTypeReferenceNode(node, getGeneratedNameForNode) {
                    // serialization of a TypeReferenceNode uses the following rules:
                    //
                    // * The serialized type of a TypeReference that is `void` is "void 0".
                    // * The serialized type of a TypeReference that is a `boolean` is "Boolean".
                    // * The serialized type of a TypeReference that is an enum or `number` is "Number".
                    // * The serialized type of a TypeReference that is a string literal or `string` is "String".
                    // * The serialized type of a TypeReference that is a tuple is "Array".
                    // * The serialized type of a TypeReference that is a `symbol` is "Symbol".
                    // * The serialized type of a TypeReference with a value declaration is its entity name.
                    // * The serialized type of a TypeReference with a call or construct signature is "Function".
                    // * The serialized type of any other type is "Object".
                    var type = getTypeFromTypeReference(node);
                    if (type.flags & 16 /* Void */) {
                        return "void 0";
                    }
                    else if (type.flags & 8 /* Boolean */) {
                        return "Boolean";
                    }
                    else if (type.flags & 132 /* NumberLike */) {
                        return "Number";
                    }
                    else if (type.flags & 258 /* StringLike */) {
                        return "String";
                    }
                    else if (type.flags & 8192 /* Tuple */) {
                        return "Array";
                    }
                    else if (type.flags & 1048576 /* ESSymbol */) {
                        return "Symbol";
                    }
                    else if (type === unknownType) {
                        var fallbackPath = [];
                        serializeEntityName(node.typeName, getGeneratedNameForNode, fallbackPath);
                        return fallbackPath;
                    }
                    else if (type.symbol && type.symbol.valueDeclaration) {
                        return serializeEntityName(node.typeName, getGeneratedNameForNode);
                    }
                    else if (typeHasCallOrConstructSignatures(type)) {
                        return "Function";
                    }
                    return "Object";
                }
                /** Serializes a TypeNode to an appropriate JS constructor value. Used by the __metadata decorator. */
                function serializeTypeNode(node, getGeneratedNameForNode) {
                    // serialization of a TypeNode uses the following rules:
                    //
                    // * The serialized type of `void` is "void 0" (undefined).
                    // * The serialized type of a parenthesized type is the serialized type of its nested type.
                    // * The serialized type of a Function or Constructor type is "Function".
                    // * The serialized type of an Array or Tuple type is "Array".
                    // * The serialized type of `boolean` is "Boolean".
                    // * The serialized type of `string` or a string-literal type is "String".
                    // * The serialized type of a type reference is handled by `serializeTypeReferenceNode`.
                    // * The serialized type of any other type node is "Object".
                    if (node) {
                        switch (node.kind) {
                            case 99 /* VoidKeyword */:
                                return "void 0";
                            case 149 /* ParenthesizedType */:
                                return serializeTypeNode(node.type, getGeneratedNameForNode);
                            case 142 /* FunctionType */:
                            case 143 /* ConstructorType */:
                                return "Function";
                            case 146 /* ArrayType */:
                            case 147 /* TupleType */:
                                return "Array";
                            case 113 /* BooleanKeyword */:
                                return "Boolean";
                            case 121 /* StringKeyword */:
                            case 8 /* StringLiteral */:
                                return "String";
                            case 119 /* NumberKeyword */:
                                return "Number";
                            case 141 /* TypeReference */:
                                return serializeTypeReferenceNode(node, getGeneratedNameForNode);
                            case 144 /* TypeQuery */:
                            case 145 /* TypeLiteral */:
                            case 148 /* UnionType */:
                            case 112 /* AnyKeyword */:
                                break;
                            default:
                                ts.Debug.fail("Cannot serialize unexpected type node.");
                                break;
                        }
                    }
                    return "Object";
                }
                /** Serializes the type of a declaration to an appropriate JS constructor value. Used by the __metadata decorator for a class member. */
                function serializeTypeOfNode(node, getGeneratedNameForNode) {
                    // serialization of the type of a declaration uses the following rules:
                    //
                    // * The serialized type of a ClassDeclaration is "Function"
                    // * The serialized type of a ParameterDeclaration is the serialized type of its type annotation.
                    // * The serialized type of a PropertyDeclaration is the serialized type of its type annotation.
                    // * The serialized type of an AccessorDeclaration is the serialized type of the return type annotation of its getter or parameter type annotation of its setter.
                    // * The serialized type of any other FunctionLikeDeclaration is "Function".
                    // * The serialized type of any other node is "void 0".
                    // 
                    // For rules on serializing type annotations, see `serializeTypeNode`.
                    switch (node.kind) {
                        case 201 /* ClassDeclaration */: return "Function";
                        case 132 /* PropertyDeclaration */: return serializeTypeNode(node.type, getGeneratedNameForNode);
                        case 129 /* Parameter */: return serializeTypeNode(node.type, getGeneratedNameForNode);
                        case 136 /* GetAccessor */: return serializeTypeNode(node.type, getGeneratedNameForNode);
                        case 137 /* SetAccessor */: return serializeTypeNode(getSetAccessorTypeAnnotationNode(node), getGeneratedNameForNode);
                    }
                    if (ts.isFunctionLike(node)) {
                        return "Function";
                    }
                    return "void 0";
                }
                /** Serializes the parameter types of a function or the constructor of a class. Used by the __metadata decorator for a method or set accessor. */
                function serializeParameterTypesOfNode(node, getGeneratedNameForNode) {
                    // serialization of parameter types uses the following rules:
                    //
                    // * If the declaration is a class, the parameters of the first constructor with a body are used.
                    // * If the declaration is function-like and has a body, the parameters of the function are used.
                    // 
                    // For the rules on serializing the type of each parameter declaration, see `serializeTypeOfDeclaration`.
                    if (node) {
                        var valueDeclaration;
                        if (node.kind === 201 /* ClassDeclaration */) {
                            valueDeclaration = ts.getFirstConstructorWithBody(node);
                        }
                        else if (ts.isFunctionLike(node) && ts.nodeIsPresent(node.body)) {
                            valueDeclaration = node;
                        }
                        if (valueDeclaration) {
                            var result;
                            var parameters = valueDeclaration.parameters;
                            var parameterCount = parameters.length;
                            if (parameterCount > 0) {
                                result = new Array(parameterCount);
                                for (var i = 0; i < parameterCount; i++) {
                                    if (parameters[i].dotDotDotToken) {
                                        var parameterType = parameters[i].type;
                                        if (parameterType.kind === 146 /* ArrayType */) {
                                            parameterType = parameterType.elementType;
                                        }
                                        else if (parameterType.kind === 141 /* TypeReference */ && parameterType.typeArguments && parameterType.typeArguments.length === 1) {
                                            parameterType = parameterType.typeArguments[0];
                                        }
                                        else {
                                            parameterType = undefined;
                                        }
                                        result[i] = serializeTypeNode(parameterType, getGeneratedNameForNode);
                                    }
                                    else {
                                        result[i] = serializeTypeOfNode(parameters[i], getGeneratedNameForNode);
                                    }
                                }
                                return result;
                            }
                        }
                    }
                    return emptyArray;
                }
                /** Serializes the return type of function. Used by the __metadata decorator for a method. */
                function serializeReturnTypeOfNode(node, getGeneratedNameForNode) {
                    if (node && ts.isFunctionLike(node)) {
                        return serializeTypeNode(node.type, getGeneratedNameForNode);
                    }
                    return "void 0";
                }
                function writeTypeOfDeclaration(declaration, enclosingDeclaration, flags, writer) {
                    // Get type of the symbol if this is the valid symbol otherwise get type at location
                    var symbol = getSymbolOfNode(declaration);
                    var type = symbol && !(symbol.flags & (2048 /* TypeLiteral */ | 131072 /* Signature */))
                        ? getTypeOfSymbol(symbol)
                        : unknownType;
                    getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
                }
                function writeReturnTypeOfSignatureDeclaration(signatureDeclaration, enclosingDeclaration, flags, writer) {
                    var signature = getSignatureFromDeclaration(signatureDeclaration);
                    getSymbolDisplayBuilder().buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags);
                }
                function writeTypeOfExpression(expr, enclosingDeclaration, flags, writer) {
                    var type = getTypeOfExpression(expr);
                    getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
                }
                function hasGlobalName(name) {
                    return ts.hasProperty(globals, name);
                }
                function resolvesToSomeValue(location, name) {
                    ts.Debug.assert(!ts.nodeIsSynthesized(location), "resolvesToSomeValue called with a synthesized location");
                    return !!resolveName(location, name, 107455 /* Value */, undefined, undefined);
                }
                function getBlockScopedVariableId(n) {
                    ts.Debug.assert(!ts.nodeIsSynthesized(n));
                    var isVariableDeclarationOrBindingElement = n.parent.kind === 152 /* BindingElement */ || (n.parent.kind === 198 /* VariableDeclaration */ && n.parent.name === n);
                    var symbol = (isVariableDeclarationOrBindingElement ? getSymbolOfNode(n.parent) : undefined) ||
                        getNodeLinks(n).resolvedSymbol ||
                        resolveName(n, n.text, 107455 /* Value */ | 8388608 /* Alias */, undefined, undefined);
                    var isLetOrConst = symbol &&
                        (symbol.flags & 2 /* BlockScopedVariable */) &&
                        symbol.valueDeclaration.parent.kind !== 223 /* CatchClause */;
                    if (isLetOrConst) {
                        // side-effect of calling this method:
                        //   assign id to symbol if it was not yet set
                        getSymbolLinks(symbol);
                        return symbol.id;
                    }
                    return undefined;
                }
                function instantiateSingleCallFunctionType(functionType, typeArguments) {
                    if (functionType === unknownType) {
                        return unknownType;
                    }
                    var signature = getSingleCallSignature(functionType);
                    if (!signature) {
                        return unknownType;
                    }
                    var instantiatedSignature = getSignatureInstantiation(signature, typeArguments);
                    return getOrCreateTypeFromSignature(instantiatedSignature);
                }
                function createResolver() {
                    return {
                        getExpressionNameSubstitution: getExpressionNameSubstitution,
                        isValueAliasDeclaration: isValueAliasDeclaration,
                        hasGlobalName: hasGlobalName,
                        isReferencedAliasDeclaration: isReferencedAliasDeclaration,
                        getNodeCheckFlags: getNodeCheckFlags,
                        isTopLevelValueImportEqualsWithEntityName: isTopLevelValueImportEqualsWithEntityName,
                        isDeclarationVisible: isDeclarationVisible,
                        isImplementationOfOverload: isImplementationOfOverload,
                        writeTypeOfDeclaration: writeTypeOfDeclaration,
                        writeReturnTypeOfSignatureDeclaration: writeReturnTypeOfSignatureDeclaration,
                        writeTypeOfExpression: writeTypeOfExpression,
                        isSymbolAccessible: isSymbolAccessible,
                        isEntityNameVisible: isEntityNameVisible,
                        getConstantValue: getConstantValue,
                        resolvesToSomeValue: resolvesToSomeValue,
                        collectLinkedAliases: collectLinkedAliases,
                        getBlockScopedVariableId: getBlockScopedVariableId,
                        serializeTypeOfNode: serializeTypeOfNode,
                        serializeParameterTypesOfNode: serializeParameterTypesOfNode,
                        serializeReturnTypeOfNode: serializeReturnTypeOfNode
                    };
                }
                function initializeTypeChecker() {
                    // Bind all source files and propagate errors
                    ts.forEach(host.getSourceFiles(), function (file) {
                        ts.bindSourceFile(file);
                    });
                    // Initialize global symbol table
                    ts.forEach(host.getSourceFiles(), function (file) {
                        if (!ts.isExternalModule(file)) {
                            mergeSymbolTable(globals, file.locals);
                        }
                    });
                    // Initialize special symbols
                    getSymbolLinks(undefinedSymbol).type = undefinedType;
                    getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments");
                    getSymbolLinks(unknownSymbol).type = unknownType;
                    globals[undefinedSymbol.name] = undefinedSymbol;
                    // Initialize special types
                    globalArraySymbol = getGlobalTypeSymbol("Array");
                    globalArrayType = getTypeOfGlobalSymbol(globalArraySymbol, 1);
                    globalObjectType = getGlobalType("Object");
                    globalFunctionType = getGlobalType("Function");
                    globalStringType = getGlobalType("String");
                    globalNumberType = getGlobalType("Number");
                    globalBooleanType = getGlobalType("Boolean");
                    globalRegExpType = getGlobalType("RegExp");
                    getGlobalClassDecoratorType = ts.memoize(function () { return getGlobalType("ClassDecorator"); });
                    getGlobalPropertyDecoratorType = ts.memoize(function () { return getGlobalType("PropertyDecorator"); });
                    getGlobalMethodDecoratorType = ts.memoize(function () { return getGlobalType("MethodDecorator"); });
                    getGlobalParameterDecoratorType = ts.memoize(function () { return getGlobalType("ParameterDecorator"); });
                    // If we're in ES6 mode, load the TemplateStringsArray.
                    // Otherwise, default to 'unknown' for the purposes of type checking in LS scenarios.
                    if (languageVersion >= 2 /* ES6 */) {
                        globalTemplateStringsArrayType = getGlobalType("TemplateStringsArray");
                        globalESSymbolType = getGlobalType("Symbol");
                        globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol");
                        globalIterableType = getGlobalType("Iterable", 1);
                    }
                    else {
                        globalTemplateStringsArrayType = unknownType;
                        // Consider putting Symbol interface in lib.d.ts. On the plus side, putting it in lib.d.ts would make it
                        // extensible for Polyfilling Symbols. But putting it into lib.d.ts could also break users that have
                        // a global Symbol already, particularly if it is a class.
                        globalESSymbolType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
                        globalESSymbolConstructorSymbol = undefined;
                    }
                    anyArrayType = createArrayType(anyType);
                }
                // GRAMMAR CHECKING
                function isReservedWordInStrictMode(node) {
                    // Check that originalKeywordKind is less than LastFutureReservedWord to see if an Identifier is a strict-mode reserved word
                    return (node.parserContextFlags & 1 /* StrictMode */) &&
                        (node.originalKeywordKind >= 102 /* FirstFutureReservedWord */ && node.originalKeywordKind <= 110 /* LastFutureReservedWord */);
                }
                function reportStrictModeGrammarErrorInClassDeclaration(identifier, message, arg0, arg1, arg2) {
                    // We are checking if this name is inside class declaration or class expression (which are under class definitions inside ES6 spec.)
                    // if so, we would like to give more explicit invalid usage error.
                    if (ts.getAncestor(identifier, 201 /* ClassDeclaration */) || ts.getAncestor(identifier, 174 /* ClassExpression */)) {
                        return grammarErrorOnNode(identifier, message, arg0);
                    }
                    return false;
                }
                function checkGrammarImportDeclarationNameInStrictMode(node) {
                    // Check if the import declaration used strict-mode reserved word in its names bindings
                    if (node.importClause) {
                        var impotClause = node.importClause;
                        if (impotClause.namedBindings) {
                            var nameBindings = impotClause.namedBindings;
                            if (nameBindings.kind === 211 /* NamespaceImport */) {
                                var name_11 = nameBindings.name;
                                if (name_11.originalKeywordKind) {
                                    var nameText = ts.declarationNameToString(name_11);
                                    return grammarErrorOnNode(name_11, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
                                }
                            }
                            else if (nameBindings.kind === 212 /* NamedImports */) {
                                var reportError = false;
                                for (var _i = 0, _a = nameBindings.elements; _i < _a.length; _i++) {
                                    var element = _a[_i];
                                    var name_12 = element.name;
                                    if (name_12.originalKeywordKind) {
                                        var nameText = ts.declarationNameToString(name_12);
                                        reportError = reportError || grammarErrorOnNode(name_12, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
                                    }
                                }
                                return reportError;
                            }
                        }
                    }
                    return false;
                }
                function checkGrammarDeclarationNameInStrictMode(node) {
                    var name = node.name;
                    if (name && name.kind === 65 /* Identifier */ && isReservedWordInStrictMode(name)) {
                        var nameText = ts.declarationNameToString(name);
                        switch (node.kind) {
                            case 129 /* Parameter */:
                            case 198 /* VariableDeclaration */:
                            case 200 /* FunctionDeclaration */:
                            case 128 /* TypeParameter */:
                            case 152 /* BindingElement */:
                            case 202 /* InterfaceDeclaration */:
                            case 203 /* TypeAliasDeclaration */:
                            case 204 /* EnumDeclaration */:
                                return checkGrammarIdentifierInStrictMode(name);
                            case 201 /* ClassDeclaration */:
                                // Report an error if the class declaration uses strict-mode reserved word.
                                return grammarErrorOnNode(name, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode, nameText);
                            case 205 /* ModuleDeclaration */:
                                // Report an error if the module declaration uses strict-mode reserved word.
                                // TODO(yuisu): fix this when having external module in strict mode
                                return grammarErrorOnNode(name, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
                            case 208 /* ImportEqualsDeclaration */:
                                // TODO(yuisu): fix this when having external module in strict mode
                                return grammarErrorOnNode(name, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
                        }
                    }
                    return false;
                }
                function checkGrammarTypeReferenceInStrictMode(typeName) {
                    // Check if the type reference is using strict mode keyword
                    // Example:
                    //      class C {
                    //          foo(x: public){}  // Error.
                    //      }
                    if (typeName.kind === 65 /* Identifier */) {
                        checkGrammarTypeNameInStrictMode(typeName);
                    }
                    else if (typeName.kind === 126 /* QualifiedName */) {
                        // Walk from right to left and report a possible error at each Identifier in QualifiedName
                        // Example:
                        //      x1: public.private.package  // error at public and private
                        checkGrammarTypeNameInStrictMode(typeName.right);
                        checkGrammarTypeReferenceInStrictMode(typeName.left);
                    }
                }
                // This function will report an error for every identifier in property access expression
                // whether it violates strict mode reserved words.
                // Example:
                //      public                  // error at public
                //      public.private.package  // error at public
                //      B.private.B             // no error
                function checkGrammarHeritageClauseElementInStrictMode(expression) {
                    // Example:
                    //      class C extends public // error at public
                    if (expression && expression.kind === 65 /* Identifier */) {
                        return checkGrammarIdentifierInStrictMode(expression);
                    }
                    else if (expression && expression.kind === 155 /* PropertyAccessExpression */) {
                        // Walk from left to right in PropertyAccessExpression until we are at the left most expression
                        // in PropertyAccessExpression. According to grammar production of MemberExpression,
                        // the left component expression is a PrimaryExpression (i.e. Identifier) while the other
                        // component after dots can be IdentifierName.
                        checkGrammarHeritageClauseElementInStrictMode(expression.expression);
                    }
                }
                // The function takes an identifier itself or an expression which has SyntaxKind.Identifier.
                function checkGrammarIdentifierInStrictMode(node, nameText) {
                    if (node && node.kind === 65 /* Identifier */ && isReservedWordInStrictMode(node)) {
                        if (!nameText) {
                            nameText = ts.declarationNameToString(node);
                        }
                        // TODO (yuisu): Fix when module is a strict mode
                        var errorReport = reportStrictModeGrammarErrorInClassDeclaration(node, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode, nameText) ||
                            grammarErrorOnNode(node, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
                        return errorReport;
                    }
                    return false;
                }
                // The function takes an identifier when uses as a typeName in TypeReferenceNode
                function checkGrammarTypeNameInStrictMode(node) {
                    if (node && node.kind === 65 /* Identifier */ && isReservedWordInStrictMode(node)) {
                        var nameText = ts.declarationNameToString(node);
                        // TODO (yuisu): Fix when module is a strict mode
                        var errorReport = reportStrictModeGrammarErrorInClassDeclaration(node, ts.Diagnostics.Type_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode, nameText) ||
                            grammarErrorOnNode(node, ts.Diagnostics.Type_expected_0_is_a_reserved_word_in_strict_mode, nameText);
                        return errorReport;
                    }
                    return false;
                }
                function checkGrammarDecorators(node) {
                    if (!node.decorators) {
                        return false;
                    }
                    if (!ts.nodeCanBeDecorated(node)) {
                        return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_are_not_valid_here);
                    }
                    else if (languageVersion < 1 /* ES5 */) {
                        return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher);
                    }
                    else if (node.kind === 136 /* GetAccessor */ || node.kind === 137 /* SetAccessor */) {
                        var accessors = ts.getAllAccessorDeclarations(node.parent.members, node);
                        if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) {
                            return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name);
                        }
                    }
                    return false;
                }
                function checkGrammarModifiers(node) {
                    switch (node.kind) {
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                        case 135 /* Constructor */:
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                        case 140 /* IndexSignature */:
                        case 201 /* ClassDeclaration */:
                        case 202 /* InterfaceDeclaration */:
                        case 205 /* ModuleDeclaration */:
                        case 204 /* EnumDeclaration */:
                        case 180 /* VariableStatement */:
                        case 200 /* FunctionDeclaration */:
                        case 203 /* TypeAliasDeclaration */:
                        case 209 /* ImportDeclaration */:
                        case 208 /* ImportEqualsDeclaration */:
                        case 215 /* ExportDeclaration */:
                        case 214 /* ExportAssignment */:
                        case 129 /* Parameter */:
                            break;
                        default:
                            return false;
                    }
                    if (!node.modifiers) {
                        return;
                    }
                    var lastStatic, lastPrivate, lastProtected, lastDeclare;
                    var flags = 0;
                    for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) {
                        var modifier = _a[_i];
                        switch (modifier.kind) {
                            case 108 /* PublicKeyword */:
                            case 107 /* ProtectedKeyword */:
                            case 106 /* PrivateKeyword */:
                                var text = void 0;
                                if (modifier.kind === 108 /* PublicKeyword */) {
                                    text = "public";
                                }
                                else if (modifier.kind === 107 /* ProtectedKeyword */) {
                                    text = "protected";
                                    lastProtected = modifier;
                                }
                                else {
                                    text = "private";
                                    lastPrivate = modifier;
                                }
                                if (flags & 112 /* AccessibilityModifier */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics.Accessibility_modifier_already_seen);
                                }
                                else if (flags & 128 /* Static */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "static");
                                }
                                else if (node.parent.kind === 206 /* ModuleBlock */ || node.parent.kind === 227 /* SourceFile */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_module_element, text);
                                }
                                flags |= ts.modifierToFlag(modifier.kind);
                                break;
                            case 109 /* StaticKeyword */:
                                if (flags & 128 /* Static */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "static");
                                }
                                else if (node.parent.kind === 206 /* ModuleBlock */ || node.parent.kind === 227 /* SourceFile */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_module_element, "static");
                                }
                                else if (node.kind === 129 /* Parameter */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "static");
                                }
                                flags |= 128 /* Static */;
                                lastStatic = modifier;
                                break;
                            case 78 /* ExportKeyword */:
                                if (flags & 1 /* Export */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "export");
                                }
                                else if (flags & 2 /* Ambient */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare");
                                }
                                else if (node.parent.kind === 201 /* ClassDeclaration */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_class_element, "export");
                                }
                                else if (node.kind === 129 /* Parameter */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "export");
                                }
                                flags |= 1 /* Export */;
                                break;
                            case 115 /* DeclareKeyword */:
                                if (flags & 2 /* Ambient */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "declare");
                                }
                                else if (node.parent.kind === 201 /* ClassDeclaration */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_class_element, "declare");
                                }
                                else if (node.kind === 129 /* Parameter */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "declare");
                                }
                                else if (ts.isInAmbientContext(node.parent) && node.parent.kind === 206 /* ModuleBlock */) {
                                    return grammarErrorOnNode(modifier, ts.Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context);
                                }
                                flags |= 2 /* Ambient */;
                                lastDeclare = modifier;
                                break;
                        }
                    }
                    if (node.kind === 135 /* Constructor */) {
                        if (flags & 128 /* Static */) {
                            return grammarErrorOnNode(lastStatic, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static");
                        }
                        else if (flags & 64 /* Protected */) {
                            return grammarErrorOnNode(lastProtected, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "protected");
                        }
                        else if (flags & 32 /* Private */) {
                            return grammarErrorOnNode(lastPrivate, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "private");
                        }
                    }
                    else if ((node.kind === 209 /* ImportDeclaration */ || node.kind === 208 /* ImportEqualsDeclaration */) && flags & 2 /* Ambient */) {
                        return grammarErrorOnNode(lastDeclare, ts.Diagnostics.A_declare_modifier_cannot_be_used_with_an_import_declaration, "declare");
                    }
                    else if (node.kind === 202 /* InterfaceDeclaration */ && flags & 2 /* Ambient */) {
                        return grammarErrorOnNode(lastDeclare, ts.Diagnostics.A_declare_modifier_cannot_be_used_with_an_interface_declaration, "declare");
                    }
                    else if (node.kind === 129 /* Parameter */ && (flags & 112 /* AccessibilityModifier */) && ts.isBindingPattern(node.name)) {
                        return grammarErrorOnNode(node, ts.Diagnostics.A_parameter_property_may_not_be_a_binding_pattern);
                    }
                }
                function checkGrammarForDisallowedTrailingComma(list) {
                    if (list && list.hasTrailingComma) {
                        var start = list.end - ",".length;
                        var end = list.end;
                        var sourceFile = ts.getSourceFileOfNode(list[0]);
                        return grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.Trailing_comma_not_allowed);
                    }
                }
                function checkGrammarTypeParameterList(node, typeParameters, file) {
                    if (checkGrammarForDisallowedTrailingComma(typeParameters)) {
                        return true;
                    }
                    if (typeParameters && typeParameters.length === 0) {
                        var start = typeParameters.pos - "<".length;
                        var end = ts.skipTrivia(file.text, typeParameters.end) + ">".length;
                        return grammarErrorAtPos(file, start, end - start, ts.Diagnostics.Type_parameter_list_cannot_be_empty);
                    }
                }
                function checkGrammarParameterList(parameters) {
                    if (checkGrammarForDisallowedTrailingComma(parameters)) {
                        return true;
                    }
                    var seenOptionalParameter = false;
                    var parameterCount = parameters.length;
                    for (var i = 0; i < parameterCount; i++) {
                        var parameter = parameters[i];
                        if (parameter.dotDotDotToken) {
                            if (i !== (parameterCount - 1)) {
                                return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list);
                            }
                            if (ts.isBindingPattern(parameter.name)) {
                                return grammarErrorOnNode(parameter.name, ts.Diagnostics.A_rest_element_cannot_contain_a_binding_pattern);
                            }
                            if (parameter.questionToken) {
                                return grammarErrorOnNode(parameter.questionToken, ts.Diagnostics.A_rest_parameter_cannot_be_optional);
                            }
                            if (parameter.initializer) {
                                return grammarErrorOnNode(parameter.name, ts.Diagnostics.A_rest_parameter_cannot_have_an_initializer);
                            }
                        }
                        else if (parameter.questionToken || parameter.initializer) {
                            seenOptionalParameter = true;
                            if (parameter.questionToken && parameter.initializer) {
                                return grammarErrorOnNode(parameter.name, ts.Diagnostics.Parameter_cannot_have_question_mark_and_initializer);
                            }
                        }
                        else {
                            if (seenOptionalParameter) {
                                return grammarErrorOnNode(parameter.name, ts.Diagnostics.A_required_parameter_cannot_follow_an_optional_parameter);
                            }
                        }
                    }
                }
                function checkGrammarFunctionLikeDeclaration(node) {
                    // Prevent cascading error by short-circuit
                    var file = ts.getSourceFileOfNode(node);
                    return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarTypeParameterList(node, node.typeParameters, file) ||
                        checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file);
                }
                function checkGrammarArrowFunction(node, file) {
                    if (node.kind === 163 /* ArrowFunction */) {
                        var arrowFunction = node;
                        var startLine = ts.getLineAndCharacterOfPosition(file, arrowFunction.equalsGreaterThanToken.pos).line;
                        var endLine = ts.getLineAndCharacterOfPosition(file, arrowFunction.equalsGreaterThanToken.end).line;
                        if (startLine !== endLine) {
                            return grammarErrorOnNode(arrowFunction.equalsGreaterThanToken, ts.Diagnostics.Line_terminator_not_permitted_before_arrow);
                        }
                    }
                    return false;
                }
                function checkGrammarIndexSignatureParameters(node) {
                    var parameter = node.parameters[0];
                    if (node.parameters.length !== 1) {
                        if (parameter) {
                            return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_must_have_exactly_one_parameter);
                        }
                        else {
                            return grammarErrorOnNode(node, ts.Diagnostics.An_index_signature_must_have_exactly_one_parameter);
                        }
                    }
                    if (parameter.dotDotDotToken) {
                        return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.An_index_signature_cannot_have_a_rest_parameter);
                    }
                    if (parameter.flags & 499 /* Modifier */) {
                        return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier);
                    }
                    if (parameter.questionToken) {
                        return grammarErrorOnNode(parameter.questionToken, ts.Diagnostics.An_index_signature_parameter_cannot_have_a_question_mark);
                    }
                    if (parameter.initializer) {
                        return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_cannot_have_an_initializer);
                    }
                    if (!parameter.type) {
                        return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_must_have_a_type_annotation);
                    }
                    if (parameter.type.kind !== 121 /* StringKeyword */ && parameter.type.kind !== 119 /* NumberKeyword */) {
                        return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_type_must_be_string_or_number);
                    }
                    if (!node.type) {
                        return grammarErrorOnNode(node, ts.Diagnostics.An_index_signature_must_have_a_type_annotation);
                    }
                }
                function checkGrammarForIndexSignatureModifier(node) {
                    if (node.flags & 499 /* Modifier */) {
                        grammarErrorOnFirstToken(node, ts.Diagnostics.Modifiers_not_permitted_on_index_signature_members);
                    }
                }
                function checkGrammarIndexSignature(node) {
                    // Prevent cascading error by short-circuit
                    return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarIndexSignatureParameters(node) || checkGrammarForIndexSignatureModifier(node);
                }
                function checkGrammarForAtLeastOneTypeArgument(node, typeArguments) {
                    if (typeArguments && typeArguments.length === 0) {
                        var sourceFile = ts.getSourceFileOfNode(node);
                        var start = typeArguments.pos - "<".length;
                        var end = ts.skipTrivia(sourceFile.text, typeArguments.end) + ">".length;
                        return grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.Type_argument_list_cannot_be_empty);
                    }
                }
                function checkGrammarTypeArguments(node, typeArguments) {
                    return checkGrammarForDisallowedTrailingComma(typeArguments) ||
                        checkGrammarForAtLeastOneTypeArgument(node, typeArguments);
                }
                function checkGrammarForOmittedArgument(node, arguments) {
                    if (arguments) {
                        var sourceFile = ts.getSourceFileOfNode(node);
                        for (var _i = 0; _i < arguments.length; _i++) {
                            var arg = arguments[_i];
                            if (arg.kind === 175 /* OmittedExpression */) {
                                return grammarErrorAtPos(sourceFile, arg.pos, 0, ts.Diagnostics.Argument_expression_expected);
                            }
                        }
                    }
                }
                function checkGrammarArguments(node, arguments) {
                    return checkGrammarForDisallowedTrailingComma(arguments) ||
                        checkGrammarForOmittedArgument(node, arguments);
                }
                function checkGrammarHeritageClause(node) {
                    var types = node.types;
                    if (checkGrammarForDisallowedTrailingComma(types)) {
                        return true;
                    }
                    if (types && types.length === 0) {
                        var listType = ts.tokenToString(node.token);
                        var sourceFile = ts.getSourceFileOfNode(node);
                        return grammarErrorAtPos(sourceFile, types.pos, 0, ts.Diagnostics._0_list_cannot_be_empty, listType);
                    }
                }
                function checkGrammarClassDeclarationHeritageClauses(node) {
                    var seenExtendsClause = false;
                    var seenImplementsClause = false;
                    if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && node.heritageClauses) {
                        for (var _i = 0, _a = node.heritageClauses; _i < _a.length; _i++) {
                            var heritageClause = _a[_i];
                            if (heritageClause.token === 79 /* ExtendsKeyword */) {
                                if (seenExtendsClause) {
                                    return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_already_seen);
                                }
                                if (seenImplementsClause) {
                                    return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_must_precede_implements_clause);
                                }
                                if (heritageClause.types.length > 1) {
                                    return grammarErrorOnFirstToken(heritageClause.types[1], ts.Diagnostics.Classes_can_only_extend_a_single_class);
                                }
                                seenExtendsClause = true;
                            }
                            else {
                                ts.Debug.assert(heritageClause.token === 102 /* ImplementsKeyword */);
                                if (seenImplementsClause) {
                                    return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.implements_clause_already_seen);
                                }
                                seenImplementsClause = true;
                            }
                            // Grammar checking heritageClause inside class declaration
                            checkGrammarHeritageClause(heritageClause);
                        }
                    }
                }
                function checkGrammarInterfaceDeclaration(node) {
                    var seenExtendsClause = false;
                    if (node.heritageClauses) {
                        for (var _i = 0, _a = node.heritageClauses; _i < _a.length; _i++) {
                            var heritageClause = _a[_i];
                            if (heritageClause.token === 79 /* ExtendsKeyword */) {
                                if (seenExtendsClause) {
                                    return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_already_seen);
                                }
                                seenExtendsClause = true;
                            }
                            else {
                                ts.Debug.assert(heritageClause.token === 102 /* ImplementsKeyword */);
                                return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.Interface_declaration_cannot_have_implements_clause);
                            }
                            // Grammar checking heritageClause inside class declaration
                            checkGrammarHeritageClause(heritageClause);
                        }
                    }
                    return false;
                }
                function checkGrammarComputedPropertyName(node) {
                    // If node is not a computedPropertyName, just skip the grammar checking
                    if (node.kind !== 127 /* ComputedPropertyName */) {
                        return false;
                    }
                    var computedPropertyName = node;
                    if (computedPropertyName.expression.kind === 169 /* BinaryExpression */ && computedPropertyName.expression.operatorToken.kind === 23 /* CommaToken */) {
                        return grammarErrorOnNode(computedPropertyName.expression, ts.Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name);
                    }
                }
                function checkGrammarForGenerator(node) {
                    if (node.asteriskToken) {
                        return grammarErrorOnNode(node.asteriskToken, ts.Diagnostics.Generators_are_not_currently_supported);
                    }
                }
                function checkGrammarFunctionName(name) {
                    // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1))
                    return checkGrammarEvalOrArgumentsInStrictMode(name, name);
                }
                function checkGrammarForInvalidQuestionMark(node, questionToken, message) {
                    if (questionToken) {
                        return grammarErrorOnNode(questionToken, message);
                    }
                }
                function checkGrammarObjectLiteralExpression(node) {
                    var seen = {};
                    var Property = 1;
                    var GetAccessor = 2;
                    var SetAccesor = 4;
                    var GetOrSetAccessor = GetAccessor | SetAccesor;
                    var inStrictMode = (node.parserContextFlags & 1 /* StrictMode */) !== 0;
                    for (var _i = 0, _a = node.properties; _i < _a.length; _i++) {
                        var prop = _a[_i];
                        var name_13 = prop.name;
                        if (prop.kind === 175 /* OmittedExpression */ ||
                            name_13.kind === 127 /* ComputedPropertyName */) {
                            // If the name is not a ComputedPropertyName, the grammar checking will skip it
                            checkGrammarComputedPropertyName(name_13);
                            continue;
                        }
                        // ECMA-262 11.1.5 Object Initialiser
                        // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true
                        // a.This production is contained in strict code and IsDataDescriptor(previous) is true and
                        // IsDataDescriptor(propId.descriptor) is true.
                        //    b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true.
                        //    c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true.
                        //    d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true
                        // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields
                        var currentKind = void 0;
                        if (prop.kind === 224 /* PropertyAssignment */ || prop.kind === 225 /* ShorthandPropertyAssignment */) {
                            // Grammar checking for computedPropertName and shorthandPropertyAssignment
                            checkGrammarForInvalidQuestionMark(prop, prop.questionToken, ts.Diagnostics.An_object_member_cannot_be_declared_optional);
                            if (name_13.kind === 7 /* NumericLiteral */) {
                                checkGrammarNumericLiteral(name_13);
                            }
                            currentKind = Property;
                        }
                        else if (prop.kind === 134 /* MethodDeclaration */) {
                            currentKind = Property;
                        }
                        else if (prop.kind === 136 /* GetAccessor */) {
                            currentKind = GetAccessor;
                        }
                        else if (prop.kind === 137 /* SetAccessor */) {
                            currentKind = SetAccesor;
                        }
                        else {
                            ts.Debug.fail("Unexpected syntax kind:" + prop.kind);
                        }
                        if (!ts.hasProperty(seen, name_13.text)) {
                            seen[name_13.text] = currentKind;
                        }
                        else {
                            var existingKind = seen[name_13.text];
                            if (currentKind === Property && existingKind === Property) {
                                if (inStrictMode) {
                                    grammarErrorOnNode(name_13, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode);
                                }
                            }
                            else if ((currentKind & GetOrSetAccessor) && (existingKind & GetOrSetAccessor)) {
                                if (existingKind !== GetOrSetAccessor && currentKind !== existingKind) {
                                    seen[name_13.text] = currentKind | existingKind;
                                }
                                else {
                                    return grammarErrorOnNode(name_13, ts.Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name);
                                }
                            }
                            else {
                                return grammarErrorOnNode(name_13, ts.Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name);
                            }
                        }
                    }
                }
                function checkGrammarForInOrForOfStatement(forInOrOfStatement) {
                    if (checkGrammarStatementInAmbientContext(forInOrOfStatement)) {
                        return true;
                    }
                    if (forInOrOfStatement.initializer.kind === 199 /* VariableDeclarationList */) {
                        var variableList = forInOrOfStatement.initializer;
                        if (!checkGrammarVariableDeclarationList(variableList)) {
                            if (variableList.declarations.length > 1) {
                                var diagnostic = forInOrOfStatement.kind === 187 /* ForInStatement */
                                    ? ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement
                                    : ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement;
                                return grammarErrorOnFirstToken(variableList.declarations[1], diagnostic);
                            }
                            var firstDeclaration = variableList.declarations[0];
                            if (firstDeclaration.initializer) {
                                var diagnostic = forInOrOfStatement.kind === 187 /* ForInStatement */
                                    ? ts.Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer
                                    : ts.Diagnostics.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer;
                                return grammarErrorOnNode(firstDeclaration.name, diagnostic);
                            }
                            if (firstDeclaration.type) {
                                var diagnostic = forInOrOfStatement.kind === 187 /* ForInStatement */
                                    ? ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation
                                    : ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation;
                                return grammarErrorOnNode(firstDeclaration, diagnostic);
                            }
                        }
                    }
                    return false;
                }
                function checkGrammarAccessor(accessor) {
                    var kind = accessor.kind;
                    if (languageVersion < 1 /* ES5 */) {
                        return grammarErrorOnNode(accessor.name, ts.Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher);
                    }
                    else if (ts.isInAmbientContext(accessor)) {
                        return grammarErrorOnNode(accessor.name, ts.Diagnostics.An_accessor_cannot_be_declared_in_an_ambient_context);
                    }
                    else if (accessor.body === undefined) {
                        return grammarErrorAtPos(ts.getSourceFileOfNode(accessor), accessor.end - 1, ";".length, ts.Diagnostics._0_expected, "{");
                    }
                    else if (accessor.typeParameters) {
                        return grammarErrorOnNode(accessor.name, ts.Diagnostics.An_accessor_cannot_have_type_parameters);
                    }
                    else if (kind === 136 /* GetAccessor */ && accessor.parameters.length) {
                        return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_get_accessor_cannot_have_parameters);
                    }
                    else if (kind === 137 /* SetAccessor */) {
                        if (accessor.type) {
                            return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_set_accessor_cannot_have_a_return_type_annotation);
                        }
                        else if (accessor.parameters.length !== 1) {
                            return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_set_accessor_must_have_exactly_one_parameter);
                        }
                        else {
                            var parameter = accessor.parameters[0];
                            if (parameter.dotDotDotToken) {
                                return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.A_set_accessor_cannot_have_rest_parameter);
                            }
                            else if (parameter.flags & 499 /* Modifier */) {
                                return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
                            }
                            else if (parameter.questionToken) {
                                return grammarErrorOnNode(parameter.questionToken, ts.Diagnostics.A_set_accessor_cannot_have_an_optional_parameter);
                            }
                            else if (parameter.initializer) {
                                return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_set_accessor_parameter_cannot_have_an_initializer);
                            }
                        }
                    }
                }
                function checkGrammarForNonSymbolComputedProperty(node, message) {
                    if (node.kind === 127 /* ComputedPropertyName */ && !ts.isWellKnownSymbolSyntactically(node.expression)) {
                        return grammarErrorOnNode(node, message);
                    }
                }
                function checkGrammarMethod(node) {
                    if (checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) ||
                        checkGrammarFunctionLikeDeclaration(node) ||
                        checkGrammarForGenerator(node)) {
                        return true;
                    }
                    if (node.parent.kind === 154 /* ObjectLiteralExpression */) {
                        if (checkGrammarForInvalidQuestionMark(node, node.questionToken, ts.Diagnostics.A_class_member_cannot_be_declared_optional)) {
                            return true;
                        }
                        else if (node.body === undefined) {
                            return grammarErrorAtPos(getSourceFile(node), node.end - 1, ";".length, ts.Diagnostics._0_expected, "{");
                        }
                    }
                    if (node.parent.kind === 201 /* ClassDeclaration */) {
                        if (checkGrammarForInvalidQuestionMark(node, node.questionToken, ts.Diagnostics.A_class_member_cannot_be_declared_optional)) {
                            return true;
                        }
                        // Technically, computed properties in ambient contexts is disallowed
                        // for property declarations and accessors too, not just methods.
                        // However, property declarations disallow computed names in general,
                        // and accessors are not allowed in ambient contexts in general,
                        // so this error only really matters for methods.
                        if (ts.isInAmbientContext(node)) {
                            return checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_an_ambient_context_must_directly_refer_to_a_built_in_symbol);
                        }
                        else if (!node.body) {
                            return checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_a_method_overload_must_directly_refer_to_a_built_in_symbol);
                        }
                    }
                    else if (node.parent.kind === 202 /* InterfaceDeclaration */) {
                        return checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol);
                    }
                    else if (node.parent.kind === 145 /* TypeLiteral */) {
                        return checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol);
                    }
                }
                function isIterationStatement(node, lookInLabeledStatements) {
                    switch (node.kind) {
                        case 186 /* ForStatement */:
                        case 187 /* ForInStatement */:
                        case 188 /* ForOfStatement */:
                        case 184 /* DoStatement */:
                        case 185 /* WhileStatement */:
                            return true;
                        case 194 /* LabeledStatement */:
                            return lookInLabeledStatements && isIterationStatement(node.statement, lookInLabeledStatements);
                    }
                    return false;
                }
                function checkGrammarBreakOrContinueStatement(node) {
                    var current = node;
                    while (current) {
                        if (ts.isFunctionLike(current)) {
                            return grammarErrorOnNode(node, ts.Diagnostics.Jump_target_cannot_cross_function_boundary);
                        }
                        switch (current.kind) {
                            case 194 /* LabeledStatement */:
                                if (node.label && current.label.text === node.label.text) {
                                    // found matching label - verify that label usage is correct
                                    // continue can only target labels that are on iteration statements
                                    var isMisplacedContinueLabel = node.kind === 189 /* ContinueStatement */
                                        && !isIterationStatement(current.statement, true);
                                    if (isMisplacedContinueLabel) {
                                        return grammarErrorOnNode(node, ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement);
                                    }
                                    return false;
                                }
                                break;
                            case 193 /* SwitchStatement */:
                                if (node.kind === 190 /* BreakStatement */ && !node.label) {
                                    // unlabeled break within switch statement - ok
                                    return false;
                                }
                                break;
                            default:
                                if (isIterationStatement(current, false) && !node.label) {
                                    // unlabeled break or continue within iteration statement - ok
                                    return false;
                                }
                                break;
                        }
                        current = current.parent;
                    }
                    if (node.label) {
                        var message = node.kind === 190 /* BreakStatement */
                            ? ts.Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement
                            : ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement;
                        return grammarErrorOnNode(node, message);
                    }
                    else {
                        var message = node.kind === 190 /* BreakStatement */
                            ? ts.Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement
                            : ts.Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement;
                        return grammarErrorOnNode(node, message);
                    }
                }
                function checkGrammarBindingElement(node) {
                    if (node.dotDotDotToken) {
                        var elements = node.parent.elements;
                        if (node !== elements[elements.length - 1]) {
                            return grammarErrorOnNode(node, ts.Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
                        }
                        if (node.name.kind === 151 /* ArrayBindingPattern */ || node.name.kind === 150 /* ObjectBindingPattern */) {
                            return grammarErrorOnNode(node.name, ts.Diagnostics.A_rest_element_cannot_contain_a_binding_pattern);
                        }
                        if (node.initializer) {
                            // Error on equals token which immediate precedes the initializer
                            return grammarErrorAtPos(ts.getSourceFileOfNode(node), node.initializer.pos - 1, 1, ts.Diagnostics.A_rest_element_cannot_have_an_initializer);
                        }
                    }
                    // It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code
                    // and its Identifier is eval or arguments
                    return checkGrammarEvalOrArgumentsInStrictMode(node, node.name);
                }
                function checkGrammarVariableDeclaration(node) {
                    if (node.parent.parent.kind !== 187 /* ForInStatement */ && node.parent.parent.kind !== 188 /* ForOfStatement */) {
                        if (ts.isInAmbientContext(node)) {
                            if (node.initializer) {
                                // Error on equals token which immediate precedes the initializer
                                var equalsTokenLength = "=".length;
                                return grammarErrorAtPos(ts.getSourceFileOfNode(node), node.initializer.pos - equalsTokenLength, equalsTokenLength, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
                            }
                        }
                        else if (!node.initializer) {
                            if (ts.isBindingPattern(node.name) && !ts.isBindingPattern(node.parent)) {
                                return grammarErrorOnNode(node, ts.Diagnostics.A_destructuring_declaration_must_have_an_initializer);
                            }
                            if (ts.isConst(node)) {
                                return grammarErrorOnNode(node, ts.Diagnostics.const_declarations_must_be_initialized);
                            }
                        }
                    }
                    var checkLetConstNames = languageVersion >= 2 /* ES6 */ && (ts.isLet(node) || ts.isConst(node));
                    // 1. LexicalDeclaration : LetOrConst BindingList ;
                    // It is a Syntax Error if the BoundNames of BindingList contains "let".
                    // 2. ForDeclaration: ForDeclaration : LetOrConst ForBinding
                    // It is a Syntax Error if the BoundNames of ForDeclaration contains "let".
                    // It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code
                    // and its Identifier is eval or arguments
                    return (checkLetConstNames && checkGrammarNameInLetOrConstDeclarations(node.name)) ||
                        checkGrammarEvalOrArgumentsInStrictMode(node, node.name);
                }
                function checkGrammarNameInLetOrConstDeclarations(name) {
                    if (name.kind === 65 /* Identifier */) {
                        if (name.text === "let") {
                            return grammarErrorOnNode(name, ts.Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations);
                        }
                    }
                    else {
                        var elements = name.elements;
                        for (var _i = 0; _i < elements.length; _i++) {
                            var element = elements[_i];
                            if (element.kind !== 175 /* OmittedExpression */) {
                                checkGrammarNameInLetOrConstDeclarations(element.name);
                            }
                        }
                    }
                }
                function checkGrammarVariableDeclarationList(declarationList) {
                    var declarations = declarationList.declarations;
                    if (checkGrammarForDisallowedTrailingComma(declarationList.declarations)) {
                        return true;
                    }
                    if (!declarationList.declarations.length) {
                        return grammarErrorAtPos(ts.getSourceFileOfNode(declarationList), declarations.pos, declarations.end - declarations.pos, ts.Diagnostics.Variable_declaration_list_cannot_be_empty);
                    }
                }
                function allowLetAndConstDeclarations(parent) {
                    switch (parent.kind) {
                        case 183 /* IfStatement */:
                        case 184 /* DoStatement */:
                        case 185 /* WhileStatement */:
                        case 192 /* WithStatement */:
                        case 186 /* ForStatement */:
                        case 187 /* ForInStatement */:
                        case 188 /* ForOfStatement */:
                            return false;
                        case 194 /* LabeledStatement */:
                            return allowLetAndConstDeclarations(parent.parent);
                    }
                    return true;
                }
                function checkGrammarForDisallowedLetOrConstStatement(node) {
                    if (!allowLetAndConstDeclarations(node.parent)) {
                        if (ts.isLet(node.declarationList)) {
                            return grammarErrorOnNode(node, ts.Diagnostics.let_declarations_can_only_be_declared_inside_a_block);
                        }
                        else if (ts.isConst(node.declarationList)) {
                            return grammarErrorOnNode(node, ts.Diagnostics.const_declarations_can_only_be_declared_inside_a_block);
                        }
                    }
                }
                function isIntegerLiteral(expression) {
                    if (expression.kind === 167 /* PrefixUnaryExpression */) {
                        var unaryExpression = expression;
                        if (unaryExpression.operator === 33 /* PlusToken */ || unaryExpression.operator === 34 /* MinusToken */) {
                            expression = unaryExpression.operand;
                        }
                    }
                    if (expression.kind === 7 /* NumericLiteral */) {
                        // Allows for scientific notation since literalExpression.text was formed by
                        // coercing a number to a string. Sometimes this coercion can yield a string
                        // in scientific notation.
                        // We also don't need special logic for hex because a hex integer is converted
                        // to decimal when it is coerced.
                        return /^[0-9]+([eE]\+?[0-9]+)?$/.test(expression.text);
                    }
                    return false;
                }
                function checkGrammarEnumDeclaration(enumDecl) {
                    var enumIsConst = (enumDecl.flags & 8192 /* Const */) !== 0;
                    var hasError = false;
                    // skip checks below for const enums  - they allow arbitrary initializers as long as they can be evaluated to constant expressions.
                    // since all values are known in compile time - it is not necessary to check that constant enum section precedes computed enum members.
                    if (!enumIsConst) {
                        var inConstantEnumMemberSection = true;
                        var inAmbientContext = ts.isInAmbientContext(enumDecl);
                        for (var _i = 0, _a = enumDecl.members; _i < _a.length; _i++) {
                            var node = _a[_i];
                            // Do not use hasDynamicName here, because that returns false for well known symbols.
                            // We want to perform checkComputedPropertyName for all computed properties, including
                            // well known symbols.
                            if (node.name.kind === 127 /* ComputedPropertyName */) {
                                hasError = grammarErrorOnNode(node.name, ts.Diagnostics.Computed_property_names_are_not_allowed_in_enums);
                            }
                            else if (inAmbientContext) {
                                if (node.initializer && !isIntegerLiteral(node.initializer)) {
                                    hasError = grammarErrorOnNode(node.name, ts.Diagnostics.Ambient_enum_elements_can_only_have_integer_literal_initializers) || hasError;
                                }
                            }
                            else if (node.initializer) {
                                inConstantEnumMemberSection = isIntegerLiteral(node.initializer);
                            }
                            else if (!inConstantEnumMemberSection) {
                                hasError = grammarErrorOnNode(node.name, ts.Diagnostics.Enum_member_must_have_initializer) || hasError;
                            }
                        }
                    }
                    return hasError;
                }
                function hasParseDiagnostics(sourceFile) {
                    return sourceFile.parseDiagnostics.length > 0;
                }
                function grammarErrorOnFirstToken(node, message, arg0, arg1, arg2) {
                    var sourceFile = ts.getSourceFileOfNode(node);
                    if (!hasParseDiagnostics(sourceFile)) {
                        var span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos);
                        diagnostics.add(ts.createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2));
                        return true;
                    }
                }
                function grammarErrorAtPos(sourceFile, start, length, message, arg0, arg1, arg2) {
                    if (!hasParseDiagnostics(sourceFile)) {
                        diagnostics.add(ts.createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2));
                        return true;
                    }
                }
                function grammarErrorOnNode(node, message, arg0, arg1, arg2) {
                    var sourceFile = ts.getSourceFileOfNode(node);
                    if (!hasParseDiagnostics(sourceFile)) {
                        diagnostics.add(ts.createDiagnosticForNode(node, message, arg0, arg1, arg2));
                        return true;
                    }
                }
                function checkGrammarEvalOrArgumentsInStrictMode(contextNode, name) {
                    if (name && name.kind === 65 /* Identifier */) {
                        var identifier = name;
                        if (contextNode && (contextNode.parserContextFlags & 1 /* StrictMode */) && isEvalOrArgumentsIdentifier(identifier)) {
                            var nameText = ts.declarationNameToString(identifier);
                            // We check first if the name is inside class declaration or class expression; if so give explicit message
                            // otherwise report generic error message.
                            // reportGrammarErrorInClassDeclaration only return true if grammar error is successfully reported and false otherwise
                            var reportErrorInClassDeclaration = reportStrictModeGrammarErrorInClassDeclaration(identifier, ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode, nameText);
                            if (!reportErrorInClassDeclaration) {
                                return grammarErrorOnNode(identifier, ts.Diagnostics.Invalid_use_of_0_in_strict_mode, nameText);
                            }
                            return reportErrorInClassDeclaration;
                        }
                    }
                }
                function isEvalOrArgumentsIdentifier(node) {
                    return node.kind === 65 /* Identifier */ &&
                        (node.text === "eval" || node.text === "arguments");
                }
                function checkGrammarConstructorTypeParameters(node) {
                    if (node.typeParameters) {
                        return grammarErrorAtPos(ts.getSourceFileOfNode(node), node.typeParameters.pos, node.typeParameters.end - node.typeParameters.pos, ts.Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration);
                    }
                }
                function checkGrammarConstructorTypeAnnotation(node) {
                    if (node.type) {
                        return grammarErrorOnNode(node.type, ts.Diagnostics.Type_annotation_cannot_appear_on_a_constructor_declaration);
                    }
                }
                function checkGrammarProperty(node) {
                    if (node.parent.kind === 201 /* ClassDeclaration */) {
                        if (checkGrammarForInvalidQuestionMark(node, node.questionToken, ts.Diagnostics.A_class_member_cannot_be_declared_optional) ||
                            checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol)) {
                            return true;
                        }
                    }
                    else if (node.parent.kind === 202 /* InterfaceDeclaration */) {
                        if (checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol)) {
                            return true;
                        }
                    }
                    else if (node.parent.kind === 145 /* TypeLiteral */) {
                        if (checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol)) {
                            return true;
                        }
                    }
                    if (ts.isInAmbientContext(node) && node.initializer) {
                        return grammarErrorOnFirstToken(node.initializer, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
                    }
                }
                function checkGrammarTopLevelElementForRequiredDeclareModifier(node) {
                    // A declare modifier is required for any top level .d.ts declaration except export=, export default,
                    // interfaces and imports categories:
                    //
                    //  DeclarationElement:
                    //     ExportAssignment
                    //     export_opt   InterfaceDeclaration
                    //     export_opt   ImportDeclaration
                    //     export_opt   ExternalImportDeclaration
                    //     export_opt   AmbientDeclaration
                    //
                    if (node.kind === 202 /* InterfaceDeclaration */ ||
                        node.kind === 209 /* ImportDeclaration */ ||
                        node.kind === 208 /* ImportEqualsDeclaration */ ||
                        node.kind === 215 /* ExportDeclaration */ ||
                        node.kind === 214 /* ExportAssignment */ ||
                        (node.flags & 2 /* Ambient */) ||
                        (node.flags & (1 /* Export */ | 256 /* Default */))) {
                        return false;
                    }
                    return grammarErrorOnFirstToken(node, ts.Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file);
                }
                function checkGrammarTopLevelElementsForRequiredDeclareModifier(file) {
                    for (var _i = 0, _a = file.statements; _i < _a.length; _i++) {
                        var decl = _a[_i];
                        if (ts.isDeclaration(decl) || decl.kind === 180 /* VariableStatement */) {
                            if (checkGrammarTopLevelElementForRequiredDeclareModifier(decl)) {
                                return true;
                            }
                        }
                    }
                }
                function checkGrammarSourceFile(node) {
                    return ts.isInAmbientContext(node) && checkGrammarTopLevelElementsForRequiredDeclareModifier(node);
                }
                function checkGrammarStatementInAmbientContext(node) {
                    if (ts.isInAmbientContext(node)) {
                        // An accessors is already reported about the ambient context
                        if (isAccessor(node.parent.kind)) {
                            return getNodeLinks(node).hasReportedStatementInAmbientContext = true;
                        }
                        // Find containing block which is either Block, ModuleBlock, SourceFile
                        var links = getNodeLinks(node);
                        if (!links.hasReportedStatementInAmbientContext && ts.isFunctionLike(node.parent)) {
                            return getNodeLinks(node).hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, ts.Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts);
                        }
                        // We are either parented by another statement, or some sort of block.
                        // If we're in a block, we only want to really report an error once
                        // to prevent noisyness.  So use a bit on the block to indicate if
                        // this has already been reported, and don't report if it has.
                        //
                        if (node.parent.kind === 179 /* Block */ || node.parent.kind === 206 /* ModuleBlock */ || node.parent.kind === 227 /* SourceFile */) {
                            var links_1 = getNodeLinks(node.parent);
                            // Check if the containing block ever report this error
                            if (!links_1.hasReportedStatementInAmbientContext) {
                                return links_1.hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, ts.Diagnostics.Statements_are_not_allowed_in_ambient_contexts);
                            }
                        }
                        else {
                        }
                    }
                }
                function checkGrammarNumericLiteral(node) {
                    // Grammar checking
                    if (node.flags & 16384 /* OctalLiteral */) {
                        if (node.parserContextFlags & 1 /* StrictMode */) {
                            return grammarErrorOnNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode);
                        }
                        else if (languageVersion >= 1 /* ES5 */) {
                            return grammarErrorOnNode(node, ts.Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher);
                        }
                    }
                }
                function grammarErrorAfterFirstToken(node, message, arg0, arg1, arg2) {
                    var sourceFile = ts.getSourceFileOfNode(node);
                    if (!hasParseDiagnostics(sourceFile)) {
                        var span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos);
                        diagnostics.add(ts.createFileDiagnostic(sourceFile, ts.textSpanEnd(span), 0, message, arg0, arg1, arg2));
                        return true;
                    }
                }
                initializeTypeChecker();
                return checker;
            }
            ts.createTypeChecker = createTypeChecker;
        })(ts || (ts = {}));
        /// <reference path="checker.ts"/>
        /* @internal */
        var ts;
        (function (ts) {
            function getDeclarationDiagnostics(host, resolver, targetSourceFile) {
                var diagnostics = [];
                var jsFilePath = ts.getOwnEmitOutputFilePath(targetSourceFile, host, ".js");
                emitDeclarations(host, resolver, diagnostics, jsFilePath, targetSourceFile);
                return diagnostics;
            }
            ts.getDeclarationDiagnostics = getDeclarationDiagnostics;
            function emitDeclarations(host, resolver, diagnostics, jsFilePath, root) {
                var newLine = host.getNewLine();
                var compilerOptions = host.getCompilerOptions();
                var languageVersion = compilerOptions.target || 0 /* ES3 */;
                var write;
                var writeLine;
                var increaseIndent;
                var decreaseIndent;
                var writeTextOfNode;
                var writer = createAndSetNewTextWriterWithSymbolWriter();
                var enclosingDeclaration;
                var currentSourceFile;
                var reportedDeclarationError = false;
                var emitJsDocComments = compilerOptions.removeComments ? function (declaration) { } : writeJsDocComments;
                var emit = compilerOptions.stripInternal ? stripInternal : emitNode;
                var moduleElementDeclarationEmitInfo = [];
                var asynchronousSubModuleDeclarationEmitInfo;
                // Contains the reference paths that needs to go in the declaration file.
                // Collecting this separately because reference paths need to be first thing in the declaration file
                // and we could be collecting these paths from multiple files into single one with --out option
                var referencePathsOutput = "";
                if (root) {
                    // Emitting just a single file, so emit references in this file only
                    if (!compilerOptions.noResolve) {
                        var addedGlobalFileReference = false;
                        ts.forEach(root.referencedFiles, function (fileReference) {
                            var referencedFile = ts.tryResolveScriptReference(host, root, fileReference);
                            // All the references that are not going to be part of same file
                            if (referencedFile && ((referencedFile.flags & 2048 /* DeclarationFile */) ||
                                ts.shouldEmitToOwnFile(referencedFile, compilerOptions) ||
                                !addedGlobalFileReference)) {
                                writeReferencePath(referencedFile);
                                if (!ts.isExternalModuleOrDeclarationFile(referencedFile)) {
                                    addedGlobalFileReference = true;
                                }
                            }
                        });
                    }
                    emitSourceFile(root);
                    // create asynchronous output for the importDeclarations
                    if (moduleElementDeclarationEmitInfo.length) {
                        var oldWriter = writer;
                        ts.forEach(moduleElementDeclarationEmitInfo, function (aliasEmitInfo) {
                            if (aliasEmitInfo.isVisible) {
                                ts.Debug.assert(aliasEmitInfo.node.kind === 209 /* ImportDeclaration */);
                                createAndSetNewTextWriterWithSymbolWriter();
                                ts.Debug.assert(aliasEmitInfo.indent === 0);
                                writeImportDeclaration(aliasEmitInfo.node);
                                aliasEmitInfo.asynchronousOutput = writer.getText();
                            }
                        });
                        setWriter(oldWriter);
                    }
                }
                else {
                    // Emit references corresponding to this file
                    var emittedReferencedFiles = [];
                    ts.forEach(host.getSourceFiles(), function (sourceFile) {
                        if (!ts.isExternalModuleOrDeclarationFile(sourceFile)) {
                            // Check what references need to be added
                            if (!compilerOptions.noResolve) {
                                ts.forEach(sourceFile.referencedFiles, function (fileReference) {
                                    var referencedFile = ts.tryResolveScriptReference(host, sourceFile, fileReference);
                                    // If the reference file is a declaration file or an external module, emit that reference
                                    if (referencedFile && (ts.isExternalModuleOrDeclarationFile(referencedFile) &&
                                        !ts.contains(emittedReferencedFiles, referencedFile))) {
                                        writeReferencePath(referencedFile);
                                        emittedReferencedFiles.push(referencedFile);
                                    }
                                });
                            }
                            emitSourceFile(sourceFile);
                        }
                    });
                }
                return {
                    reportedDeclarationError: reportedDeclarationError,
                    moduleElementDeclarationEmitInfo: moduleElementDeclarationEmitInfo,
                    synchronousDeclarationOutput: writer.getText(),
                    referencePathsOutput: referencePathsOutput
                };
                function hasInternalAnnotation(range) {
                    var text = currentSourceFile.text;
                    var comment = text.substring(range.pos, range.end);
                    return comment.indexOf("@internal") >= 0;
                }
                function stripInternal(node) {
                    if (node) {
                        var leadingCommentRanges = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos);
                        if (ts.forEach(leadingCommentRanges, hasInternalAnnotation)) {
                            return;
                        }
                        emitNode(node);
                    }
                }
                function createAndSetNewTextWriterWithSymbolWriter() {
                    var writer = ts.createTextWriter(newLine);
                    writer.trackSymbol = trackSymbol;
                    writer.writeKeyword = writer.write;
                    writer.writeOperator = writer.write;
                    writer.writePunctuation = writer.write;
                    writer.writeSpace = writer.write;
                    writer.writeStringLiteral = writer.writeLiteral;
                    writer.writeParameter = writer.write;
                    writer.writeSymbol = writer.write;
                    setWriter(writer);
                    return writer;
                }
                function setWriter(newWriter) {
                    writer = newWriter;
                    write = newWriter.write;
                    writeTextOfNode = newWriter.writeTextOfNode;
                    writeLine = newWriter.writeLine;
                    increaseIndent = newWriter.increaseIndent;
                    decreaseIndent = newWriter.decreaseIndent;
                }
                function writeAsynchronousModuleElements(nodes) {
                    var oldWriter = writer;
                    ts.forEach(nodes, function (declaration) {
                        var nodeToCheck;
                        if (declaration.kind === 198 /* VariableDeclaration */) {
                            nodeToCheck = declaration.parent.parent;
                        }
                        else if (declaration.kind === 212 /* NamedImports */ || declaration.kind === 213 /* ImportSpecifier */ || declaration.kind === 210 /* ImportClause */) {
                            ts.Debug.fail("We should be getting ImportDeclaration instead to write");
                        }
                        else {
                            nodeToCheck = declaration;
                        }
                        var moduleElementEmitInfo = ts.forEach(moduleElementDeclarationEmitInfo, function (declEmitInfo) { return declEmitInfo.node === nodeToCheck ? declEmitInfo : undefined; });
                        if (!moduleElementEmitInfo && asynchronousSubModuleDeclarationEmitInfo) {
                            moduleElementEmitInfo = ts.forEach(asynchronousSubModuleDeclarationEmitInfo, function (declEmitInfo) { return declEmitInfo.node === nodeToCheck ? declEmitInfo : undefined; });
                        }
                        // If the alias was marked as not visible when we saw its declaration, we would have saved the aliasEmitInfo, but if we haven't yet visited the alias declaration
                        // then we don't need to write it at this point. We will write it when we actually see its declaration
                        // Eg.
                        // export function bar(a: foo.Foo) { }
                        // import foo = require("foo");
                        // Writing of function bar would mark alias declaration foo as visible but we haven't yet visited that declaration so do nothing,
                        // we would write alias foo declaration when we visit it since it would now be marked as visible
                        if (moduleElementEmitInfo) {
                            if (moduleElementEmitInfo.node.kind === 209 /* ImportDeclaration */) {
                                // we have to create asynchronous output only after we have collected complete information 
                                // because it is possible to enable multiple bindings as asynchronously visible
                                moduleElementEmitInfo.isVisible = true;
                            }
                            else {
                                createAndSetNewTextWriterWithSymbolWriter();
                                for (var declarationIndent = moduleElementEmitInfo.indent; declarationIndent; declarationIndent--) {
                                    increaseIndent();
                                }
                                if (nodeToCheck.kind === 205 /* ModuleDeclaration */) {
                                    ts.Debug.assert(asynchronousSubModuleDeclarationEmitInfo === undefined);
                                    asynchronousSubModuleDeclarationEmitInfo = [];
                                }
                                writeModuleElement(nodeToCheck);
                                if (nodeToCheck.kind === 205 /* ModuleDeclaration */) {
                                    moduleElementEmitInfo.subModuleElementDeclarationEmitInfo = asynchronousSubModuleDeclarationEmitInfo;
                                    asynchronousSubModuleDeclarationEmitInfo = undefined;
                                }
                                moduleElementEmitInfo.asynchronousOutput = writer.getText();
                            }
                        }
                    });
                    setWriter(oldWriter);
                }
                function handleSymbolAccessibilityError(symbolAccesibilityResult) {
                    if (symbolAccesibilityResult.accessibility === 0 /* Accessible */) {
                        // write the aliases
                        if (symbolAccesibilityResult && symbolAccesibilityResult.aliasesToMakeVisible) {
                            writeAsynchronousModuleElements(symbolAccesibilityResult.aliasesToMakeVisible);
                        }
                    }
                    else {
                        // Report error
                        reportedDeclarationError = true;
                        var errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccesibilityResult);
                        if (errorInfo) {
                            if (errorInfo.typeName) {
                                diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, errorInfo.typeName), symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName));
                            }
                            else {
                                diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName));
                            }
                        }
                    }
                }
                function trackSymbol(symbol, enclosingDeclaration, meaning) {
                    handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning));
                }
                function writeTypeOfDeclaration(declaration, type, getSymbolAccessibilityDiagnostic) {
                    writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
                    write(": ");
                    if (type) {
                        // Write the type
                        emitType(type);
                    }
                    else {
                        resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, 2 /* UseTypeOfFunction */, writer);
                    }
                }
                function writeReturnTypeAtSignature(signature, getSymbolAccessibilityDiagnostic) {
                    writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
                    write(": ");
                    if (signature.type) {
                        // Write the type
                        emitType(signature.type);
                    }
                    else {
                        resolver.writeReturnTypeOfSignatureDeclaration(signature, enclosingDeclaration, 2 /* UseTypeOfFunction */, writer);
                    }
                }
                function emitLines(nodes) {
                    for (var _i = 0; _i < nodes.length; _i++) {
                        var node = nodes[_i];
                        emit(node);
                    }
                }
                function emitSeparatedList(nodes, separator, eachNodeEmitFn, canEmitFn) {
                    var currentWriterPos = writer.getTextPos();
                    for (var _i = 0; _i < nodes.length; _i++) {
                        var node = nodes[_i];
                        if (!canEmitFn || canEmitFn(node)) {
                            if (currentWriterPos !== writer.getTextPos()) {
                                write(separator);
                            }
                            currentWriterPos = writer.getTextPos();
                            eachNodeEmitFn(node);
                        }
                    }
                }
                function emitCommaList(nodes, eachNodeEmitFn, canEmitFn) {
                    emitSeparatedList(nodes, ", ", eachNodeEmitFn, canEmitFn);
                }
                function writeJsDocComments(declaration) {
                    if (declaration) {
                        var jsDocComments = ts.getJsDocComments(declaration, currentSourceFile);
                        ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, declaration, jsDocComments);
                        // jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space
                        ts.emitComments(currentSourceFile, writer, jsDocComments, true, newLine, ts.writeCommentRange);
                    }
                }
                function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type, getSymbolAccessibilityDiagnostic) {
                    writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
                    emitType(type);
                }
                function emitType(type) {
                    switch (type.kind) {
                        case 112 /* AnyKeyword */:
                        case 121 /* StringKeyword */:
                        case 119 /* NumberKeyword */:
                        case 113 /* BooleanKeyword */:
                        case 122 /* SymbolKeyword */:
                        case 99 /* VoidKeyword */:
                        case 8 /* StringLiteral */:
                            return writeTextOfNode(currentSourceFile, type);
                        case 177 /* HeritageClauseElement */:
                            return emitHeritageClauseElement(type);
                        case 141 /* TypeReference */:
                            return emitTypeReference(type);
                        case 144 /* TypeQuery */:
                            return emitTypeQuery(type);
                        case 146 /* ArrayType */:
                            return emitArrayType(type);
                        case 147 /* TupleType */:
                            return emitTupleType(type);
                        case 148 /* UnionType */:
                            return emitUnionType(type);
                        case 149 /* ParenthesizedType */:
                            return emitParenType(type);
                        case 142 /* FunctionType */:
                        case 143 /* ConstructorType */:
                            return emitSignatureDeclarationWithJsDocComments(type);
                        case 145 /* TypeLiteral */:
                            return emitTypeLiteral(type);
                        case 65 /* Identifier */:
                            return emitEntityName(type);
                        case 126 /* QualifiedName */:
                            return emitEntityName(type);
                    }
                    function emitEntityName(entityName) {
                        var visibilityResult = resolver.isEntityNameVisible(entityName, 
                        // Aliases can be written asynchronously so use correct enclosing declaration
                        entityName.parent.kind === 208 /* ImportEqualsDeclaration */ ? entityName.parent : enclosingDeclaration);
                        handleSymbolAccessibilityError(visibilityResult);
                        writeEntityName(entityName);
                        function writeEntityName(entityName) {
                            if (entityName.kind === 65 /* Identifier */) {
                                writeTextOfNode(currentSourceFile, entityName);
                            }
                            else {
                                var left = entityName.kind === 126 /* QualifiedName */ ? entityName.left : entityName.expression;
                                var right = entityName.kind === 126 /* QualifiedName */ ? entityName.right : entityName.name;
                                writeEntityName(left);
                                write(".");
                                writeTextOfNode(currentSourceFile, right);
                            }
                        }
                    }
                    function emitHeritageClauseElement(node) {
                        if (ts.isSupportedHeritageClauseElement(node)) {
                            ts.Debug.assert(node.expression.kind === 65 /* Identifier */ || node.expression.kind === 155 /* PropertyAccessExpression */);
                            emitEntityName(node.expression);
                            if (node.typeArguments) {
                                write("<");
                                emitCommaList(node.typeArguments, emitType);
                                write(">");
                            }
                        }
                    }
                    function emitTypeReference(type) {
                        emitEntityName(type.typeName);
                        if (type.typeArguments) {
                            write("<");
                            emitCommaList(type.typeArguments, emitType);
                            write(">");
                        }
                    }
                    function emitTypeQuery(type) {
                        write("typeof ");
                        emitEntityName(type.exprName);
                    }
                    function emitArrayType(type) {
                        emitType(type.elementType);
                        write("[]");
                    }
                    function emitTupleType(type) {
                        write("[");
                        emitCommaList(type.elementTypes, emitType);
                        write("]");
                    }
                    function emitUnionType(type) {
                        emitSeparatedList(type.types, " | ", emitType);
                    }
                    function emitParenType(type) {
                        write("(");
                        emitType(type.type);
                        write(")");
                    }
                    function emitTypeLiteral(type) {
                        write("{");
                        if (type.members.length) {
                            writeLine();
                            increaseIndent();
                            // write members
                            emitLines(type.members);
                            decreaseIndent();
                        }
                        write("}");
                    }
                }
                function emitSourceFile(node) {
                    currentSourceFile = node;
                    enclosingDeclaration = node;
                    emitLines(node.statements);
                }
                // Return a temp variable name to be used in `export default` statements.
                // The temp name will be of the form _default_counter.
                // Note that export default is only allowed at most once in a module, so we
                // do not need to keep track of created temp names.
                function getExportDefaultTempVariableName() {
                    var baseName = "_default";
                    if (!ts.hasProperty(currentSourceFile.identifiers, baseName)) {
                        return baseName;
                    }
                    var count = 0;
                    while (true) {
                        var name_14 = baseName + "_" + (++count);
                        if (!ts.hasProperty(currentSourceFile.identifiers, name_14)) {
                            return name_14;
                        }
                    }
                }
                function emitExportAssignment(node) {
                    if (node.expression.kind === 65 /* Identifier */) {
                        write(node.isExportEquals ? "export = " : "export default ");
                        writeTextOfNode(currentSourceFile, node.expression);
                    }
                    else {
                        // Expression
                        var tempVarName = getExportDefaultTempVariableName();
                        write("declare var ");
                        write(tempVarName);
                        write(": ");
                        writer.getSymbolAccessibilityDiagnostic = getDefaultExportAccessibilityDiagnostic;
                        resolver.writeTypeOfExpression(node.expression, enclosingDeclaration, 2 /* UseTypeOfFunction */, writer);
                        write(";");
                        writeLine();
                        write(node.isExportEquals ? "export = " : "export default ");
                        write(tempVarName);
                    }
                    write(";");
                    writeLine();
                    // Make all the declarations visible for the export name
                    if (node.expression.kind === 65 /* Identifier */) {
                        var nodes = resolver.collectLinkedAliases(node.expression);
                        // write each of these declarations asynchronously
                        writeAsynchronousModuleElements(nodes);
                    }
                    function getDefaultExportAccessibilityDiagnostic(diagnostic) {
                        return {
                            diagnosticMessage: ts.Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0,
                            errorNode: node
                        };
                    }
                }
                function isModuleElementVisible(node) {
                    return resolver.isDeclarationVisible(node);
                }
                function emitModuleElement(node, isModuleElementVisible) {
                    if (isModuleElementVisible) {
                        writeModuleElement(node);
                    }
                    else if (node.kind === 208 /* ImportEqualsDeclaration */ ||
                        (node.parent.kind === 227 /* SourceFile */ && ts.isExternalModule(currentSourceFile))) {
                        var isVisible;
                        if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== 227 /* SourceFile */) {
                            // Import declaration of another module that is visited async so lets put it in right spot
                            asynchronousSubModuleDeclarationEmitInfo.push({
                                node: node,
                                outputPos: writer.getTextPos(),
                                indent: writer.getIndent(),
                                isVisible: isVisible
                            });
                        }
                        else {
                            if (node.kind === 209 /* ImportDeclaration */) {
                                var importDeclaration = node;
                                if (importDeclaration.importClause) {
                                    isVisible = (importDeclaration.importClause.name && resolver.isDeclarationVisible(importDeclaration.importClause)) ||
                                        isVisibleNamedBinding(importDeclaration.importClause.namedBindings);
                                }
                            }
                            moduleElementDeclarationEmitInfo.push({
                                node: node,
                                outputPos: writer.getTextPos(),
                                indent: writer.getIndent(),
                                isVisible: isVisible
                            });
                        }
                    }
                }
                function writeModuleElement(node) {
                    switch (node.kind) {
                        case 200 /* FunctionDeclaration */:
                            return writeFunctionDeclaration(node);
                        case 180 /* VariableStatement */:
                            return writeVariableStatement(node);
                        case 202 /* InterfaceDeclaration */:
                            return writeInterfaceDeclaration(node);
                        case 201 /* ClassDeclaration */:
                            return writeClassDeclaration(node);
                        case 203 /* TypeAliasDeclaration */:
                            return writeTypeAliasDeclaration(node);
                        case 204 /* EnumDeclaration */:
                            return writeEnumDeclaration(node);
                        case 205 /* ModuleDeclaration */:
                            return writeModuleDeclaration(node);
                        case 208 /* ImportEqualsDeclaration */:
                            return writeImportEqualsDeclaration(node);
                        case 209 /* ImportDeclaration */:
                            return writeImportDeclaration(node);
                        default:
                            ts.Debug.fail("Unknown symbol kind");
                    }
                }
                function emitModuleElementDeclarationFlags(node) {
                    // If the node is parented in the current source file we need to emit export declare or just export
                    if (node.parent === currentSourceFile) {
                        // If the node is exported
                        if (node.flags & 1 /* Export */) {
                            write("export ");
                        }
                        if (node.flags & 256 /* Default */) {
                            write("default ");
                        }
                        else if (node.kind !== 202 /* InterfaceDeclaration */) {
                            write("declare ");
                        }
                    }
                }
                function emitClassMemberDeclarationFlags(node) {
                    if (node.flags & 32 /* Private */) {
                        write("private ");
                    }
                    else if (node.flags & 64 /* Protected */) {
                        write("protected ");
                    }
                    if (node.flags & 128 /* Static */) {
                        write("static ");
                    }
                }
                function writeImportEqualsDeclaration(node) {
                    // note usage of writer. methods instead of aliases created, just to make sure we are using 
                    // correct writer especially to handle asynchronous alias writing
                    emitJsDocComments(node);
                    if (node.flags & 1 /* Export */) {
                        write("export ");
                    }
                    write("import ");
                    writeTextOfNode(currentSourceFile, node.name);
                    write(" = ");
                    if (ts.isInternalModuleImportEqualsDeclaration(node)) {
                        emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.moduleReference, getImportEntityNameVisibilityError);
                        write(";");
                    }
                    else {
                        write("require(");
                        writeTextOfNode(currentSourceFile, ts.getExternalModuleImportEqualsDeclarationExpression(node));
                        write(");");
                    }
                    writer.writeLine();
                    function getImportEntityNameVisibilityError(symbolAccesibilityResult) {
                        return {
                            diagnosticMessage: ts.Diagnostics.Import_declaration_0_is_using_private_name_1,
                            errorNode: node,
                            typeName: node.name
                        };
                    }
                }
                function isVisibleNamedBinding(namedBindings) {
                    if (namedBindings) {
                        if (namedBindings.kind === 211 /* NamespaceImport */) {
                            return resolver.isDeclarationVisible(namedBindings);
                        }
                        else {
                            return ts.forEach(namedBindings.elements, function (namedImport) { return resolver.isDeclarationVisible(namedImport); });
                        }
                    }
                }
                function writeImportDeclaration(node) {
                    if (!node.importClause && !(node.flags & 1 /* Export */)) {
                        // do not write non-exported import declarations that don't have import clauses 
                        return;
                    }
                    emitJsDocComments(node);
                    if (node.flags & 1 /* Export */) {
                        write("export ");
                    }
                    write("import ");
                    if (node.importClause) {
                        var currentWriterPos = writer.getTextPos();
                        if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) {
                            writeTextOfNode(currentSourceFile, node.importClause.name);
                        }
                        if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) {
                            if (currentWriterPos !== writer.getTextPos()) {
                                // If the default binding was emitted, write the separated
                                write(", ");
                            }
                            if (node.importClause.namedBindings.kind === 211 /* NamespaceImport */) {
                                write("* as ");
                                writeTextOfNode(currentSourceFile, node.importClause.namedBindings.name);
                            }
                            else {
                                write("{ ");
                                emitCommaList(node.importClause.namedBindings.elements, emitImportOrExportSpecifier, resolver.isDeclarationVisible);
                                write(" }");
                            }
                        }
                        write(" from ");
                    }
                    writeTextOfNode(currentSourceFile, node.moduleSpecifier);
                    write(";");
                    writer.writeLine();
                }
                function emitImportOrExportSpecifier(node) {
                    if (node.propertyName) {
                        writeTextOfNode(currentSourceFile, node.propertyName);
                        write(" as ");
                    }
                    writeTextOfNode(currentSourceFile, node.name);
                }
                function emitExportSpecifier(node) {
                    emitImportOrExportSpecifier(node);
                    // Make all the declarations visible for the export name
                    var nodes = resolver.collectLinkedAliases(node.propertyName || node.name);
                    // write each of these declarations asynchronously
                    writeAsynchronousModuleElements(nodes);
                }
                function emitExportDeclaration(node) {
                    emitJsDocComments(node);
                    write("export ");
                    if (node.exportClause) {
                        write("{ ");
                        emitCommaList(node.exportClause.elements, emitExportSpecifier);
                        write(" }");
                    }
                    else {
                        write("*");
                    }
                    if (node.moduleSpecifier) {
                        write(" from ");
                        writeTextOfNode(currentSourceFile, node.moduleSpecifier);
                    }
                    write(";");
                    writer.writeLine();
                }
                function writeModuleDeclaration(node) {
                    emitJsDocComments(node);
                    emitModuleElementDeclarationFlags(node);
                    write("module ");
                    writeTextOfNode(currentSourceFile, node.name);
                    while (node.body.kind !== 206 /* ModuleBlock */) {
                        node = node.body;
                        write(".");
                        writeTextOfNode(currentSourceFile, node.name);
                    }
                    var prevEnclosingDeclaration = enclosingDeclaration;
                    enclosingDeclaration = node;
                    write(" {");
                    writeLine();
                    increaseIndent();
                    emitLines(node.body.statements);
                    decreaseIndent();
                    write("}");
                    writeLine();
                    enclosingDeclaration = prevEnclosingDeclaration;
                }
                function writeTypeAliasDeclaration(node) {
                    emitJsDocComments(node);
                    emitModuleElementDeclarationFlags(node);
                    write("type ");
                    writeTextOfNode(currentSourceFile, node.name);
                    write(" = ");
                    emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError);
                    write(";");
                    writeLine();
                    function getTypeAliasDeclarationVisibilityError(symbolAccesibilityResult) {
                        return {
                            diagnosticMessage: ts.Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1,
                            errorNode: node.type,
                            typeName: node.name
                        };
                    }
                }
                function writeEnumDeclaration(node) {
                    emitJsDocComments(node);
                    emitModuleElementDeclarationFlags(node);
                    if (ts.isConst(node)) {
                        write("const ");
                    }
                    write("enum ");
                    writeTextOfNode(currentSourceFile, node.name);
                    write(" {");
                    writeLine();
                    increaseIndent();
                    emitLines(node.members);
                    decreaseIndent();
                    write("}");
                    writeLine();
                }
                function emitEnumMemberDeclaration(node) {
                    emitJsDocComments(node);
                    writeTextOfNode(currentSourceFile, node.name);
                    var enumMemberValue = resolver.getConstantValue(node);
                    if (enumMemberValue !== undefined) {
                        write(" = ");
                        write(enumMemberValue.toString());
                    }
                    write(",");
                    writeLine();
                }
                function isPrivateMethodTypeParameter(node) {
                    return node.parent.kind === 134 /* MethodDeclaration */ && (node.parent.flags & 32 /* Private */);
                }
                function emitTypeParameters(typeParameters) {
                    function emitTypeParameter(node) {
                        increaseIndent();
                        emitJsDocComments(node);
                        decreaseIndent();
                        writeTextOfNode(currentSourceFile, node.name);
                        // If there is constraint present and this is not a type parameter of the private method emit the constraint
                        if (node.constraint && !isPrivateMethodTypeParameter(node)) {
                            write(" extends ");
                            if (node.parent.kind === 142 /* FunctionType */ ||
                                node.parent.kind === 143 /* ConstructorType */ ||
                                (node.parent.parent && node.parent.parent.kind === 145 /* TypeLiteral */)) {
                                ts.Debug.assert(node.parent.kind === 134 /* MethodDeclaration */ ||
                                    node.parent.kind === 133 /* MethodSignature */ ||
                                    node.parent.kind === 142 /* FunctionType */ ||
                                    node.parent.kind === 143 /* ConstructorType */ ||
                                    node.parent.kind === 138 /* CallSignature */ ||
                                    node.parent.kind === 139 /* ConstructSignature */);
                                emitType(node.constraint);
                            }
                            else {
                                emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.constraint, getTypeParameterConstraintVisibilityError);
                            }
                        }
                        function getTypeParameterConstraintVisibilityError(symbolAccesibilityResult) {
                            // Type parameter constraints are named by user so we should always be able to name it
                            var diagnosticMessage;
                            switch (node.parent.kind) {
                                case 201 /* ClassDeclaration */:
                                    diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1;
                                    break;
                                case 202 /* InterfaceDeclaration */:
                                    diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1;
                                    break;
                                case 139 /* ConstructSignature */:
                                    diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1;
                                    break;
                                case 138 /* CallSignature */:
                                    diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1;
                                    break;
                                case 134 /* MethodDeclaration */:
                                case 133 /* MethodSignature */:
                                    if (node.parent.flags & 128 /* Static */) {
                                        diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1;
                                    }
                                    else if (node.parent.parent.kind === 201 /* ClassDeclaration */) {
                                        diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1;
                                    }
                                    else {
                                        diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1;
                                    }
                                    break;
                                case 200 /* FunctionDeclaration */:
                                    diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1;
                                    break;
                                default:
                                    ts.Debug.fail("This is unknown parent for type parameter: " + node.parent.kind);
                            }
                            return {
                                diagnosticMessage: diagnosticMessage,
                                errorNode: node,
                                typeName: node.name
                            };
                        }
                    }
                    if (typeParameters) {
                        write("<");
                        emitCommaList(typeParameters, emitTypeParameter);
                        write(">");
                    }
                }
                function emitHeritageClause(typeReferences, isImplementsList) {
                    if (typeReferences) {
                        write(isImplementsList ? " implements " : " extends ");
                        emitCommaList(typeReferences, emitTypeOfTypeReference);
                    }
                    function emitTypeOfTypeReference(node) {
                        if (ts.isSupportedHeritageClauseElement(node)) {
                            emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError);
                        }
                        function getHeritageClauseVisibilityError(symbolAccesibilityResult) {
                            var diagnosticMessage;
                            // Heritage clause is written by user so it can always be named
                            if (node.parent.parent.kind === 201 /* ClassDeclaration */) {
                                // Class or Interface implemented/extended is inaccessible
                                diagnosticMessage = isImplementsList ?
                                    ts.Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 :
                                    ts.Diagnostics.Extends_clause_of_exported_class_0_has_or_is_using_private_name_1;
                            }
                            else {
                                // interface is inaccessible
                                diagnosticMessage = ts.Diagnostics.Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1;
                            }
                            return {
                                diagnosticMessage: diagnosticMessage,
                                errorNode: node,
                                typeName: node.parent.parent.name
                            };
                        }
                    }
                }
                function writeClassDeclaration(node) {
                    function emitParameterProperties(constructorDeclaration) {
                        if (constructorDeclaration) {
                            ts.forEach(constructorDeclaration.parameters, function (param) {
                                if (param.flags & 112 /* AccessibilityModifier */) {
                                    emitPropertyDeclaration(param);
                                }
                            });
                        }
                    }
                    emitJsDocComments(node);
                    emitModuleElementDeclarationFlags(node);
                    write("class ");
                    writeTextOfNode(currentSourceFile, node.name);
                    var prevEnclosingDeclaration = enclosingDeclaration;
                    enclosingDeclaration = node;
                    emitTypeParameters(node.typeParameters);
                    var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node);
                    if (baseTypeNode) {
                        emitHeritageClause([baseTypeNode], false);
                    }
                    emitHeritageClause(ts.getClassImplementsHeritageClauseElements(node), true);
                    write(" {");
                    writeLine();
                    increaseIndent();
                    emitParameterProperties(ts.getFirstConstructorWithBody(node));
                    emitLines(node.members);
                    decreaseIndent();
                    write("}");
                    writeLine();
                    enclosingDeclaration = prevEnclosingDeclaration;
                }
                function writeInterfaceDeclaration(node) {
                    emitJsDocComments(node);
                    emitModuleElementDeclarationFlags(node);
                    write("interface ");
                    writeTextOfNode(currentSourceFile, node.name);
                    var prevEnclosingDeclaration = enclosingDeclaration;
                    enclosingDeclaration = node;
                    emitTypeParameters(node.typeParameters);
                    emitHeritageClause(ts.getInterfaceBaseTypeNodes(node), false);
                    write(" {");
                    writeLine();
                    increaseIndent();
                    emitLines(node.members);
                    decreaseIndent();
                    write("}");
                    writeLine();
                    enclosingDeclaration = prevEnclosingDeclaration;
                }
                function emitPropertyDeclaration(node) {
                    if (ts.hasDynamicName(node)) {
                        return;
                    }
                    emitJsDocComments(node);
                    emitClassMemberDeclarationFlags(node);
                    emitVariableDeclaration(node);
                    write(";");
                    writeLine();
                }
                function emitVariableDeclaration(node) {
                    // If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted
                    // so there is no check needed to see if declaration is visible
                    if (node.kind !== 198 /* VariableDeclaration */ || resolver.isDeclarationVisible(node)) {
                        if (ts.isBindingPattern(node.name)) {
                            emitBindingPattern(node.name);
                        }
                        else {
                            // If this node is a computed name, it can only be a symbol, because we've already skipped
                            // it if it's not a well known symbol. In that case, the text of the name will be exactly
                            // what we want, namely the name expression enclosed in brackets.
                            writeTextOfNode(currentSourceFile, node.name);
                            // If optional property emit ?
                            if ((node.kind === 132 /* PropertyDeclaration */ || node.kind === 131 /* PropertySignature */) && ts.hasQuestionToken(node)) {
                                write("?");
                            }
                            if ((node.kind === 132 /* PropertyDeclaration */ || node.kind === 131 /* PropertySignature */) && node.parent.kind === 145 /* TypeLiteral */) {
                                emitTypeOfVariableDeclarationFromTypeLiteral(node);
                            }
                            else if (!(node.flags & 32 /* Private */)) {
                                writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError);
                            }
                        }
                    }
                    function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult) {
                        if (node.kind === 198 /* VariableDeclaration */) {
                            return symbolAccesibilityResult.errorModuleName ?
                                symbolAccesibilityResult.accessibility === 2 /* CannotBeNamed */ ?
                                    ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
                                    ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 :
                                ts.Diagnostics.Exported_variable_0_has_or_is_using_private_name_1;
                        }
                        else if (node.kind === 132 /* PropertyDeclaration */ || node.kind === 131 /* PropertySignature */) {
                            // TODO(jfreeman): Deal with computed properties in error reporting.
                            if (node.flags & 128 /* Static */) {
                                return symbolAccesibilityResult.errorModuleName ?
                                    symbolAccesibilityResult.accessibility === 2 /* CannotBeNamed */ ?
                                        ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
                                        ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 :
                                    ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1;
                            }
                            else if (node.parent.kind === 201 /* ClassDeclaration */) {
                                return symbolAccesibilityResult.errorModuleName ?
                                    symbolAccesibilityResult.accessibility === 2 /* CannotBeNamed */ ?
                                        ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
                                        ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 :
                                    ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1;
                            }
                            else {
                                // Interfaces cannot have types that cannot be named
                                return symbolAccesibilityResult.errorModuleName ?
                                    ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 :
                                    ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1;
                            }
                        }
                    }
                    function getVariableDeclarationTypeVisibilityError(symbolAccesibilityResult) {
                        var diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
                        return diagnosticMessage !== undefined ? {
                            diagnosticMessage: diagnosticMessage,
                            errorNode: node,
                            typeName: node.name
                        } : undefined;
                    }
                    function emitBindingPattern(bindingPattern) {
                        // Only select non-omitted expression from the bindingPattern's elements.
                        // We have to do this to avoid emitting trailing commas.
                        // For example:
                        //      original: var [, c,,] = [ 2,3,4]
                        //      emitted: declare var c: number; // instead of declare var c:number, ;
                        var elements = [];
                        for (var _i = 0, _a = bindingPattern.elements; _i < _a.length; _i++) {
                            var element = _a[_i];
                            if (element.kind !== 175 /* OmittedExpression */) {
                                elements.push(element);
                            }
                        }
                        emitCommaList(elements, emitBindingElement);
                    }
                    function emitBindingElement(bindingElement) {
                        function getBindingElementTypeVisibilityError(symbolAccesibilityResult) {
                            var diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
                            return diagnosticMessage !== undefined ? {
                                diagnosticMessage: diagnosticMessage,
                                errorNode: bindingElement,
                                typeName: bindingElement.name
                            } : undefined;
                        }
                        if (bindingElement.name) {
                            if (ts.isBindingPattern(bindingElement.name)) {
                                emitBindingPattern(bindingElement.name);
                            }
                            else {
                                writeTextOfNode(currentSourceFile, bindingElement.name);
                                writeTypeOfDeclaration(bindingElement, undefined, getBindingElementTypeVisibilityError);
                            }
                        }
                    }
                }
                function emitTypeOfVariableDeclarationFromTypeLiteral(node) {
                    // if this is property of type literal,
                    // or is parameter of method/call/construct/index signature of type literal
                    // emit only if type is specified
                    if (node.type) {
                        write(": ");
                        emitType(node.type);
                    }
                }
                function isVariableStatementVisible(node) {
                    return ts.forEach(node.declarationList.declarations, function (varDeclaration) { return resolver.isDeclarationVisible(varDeclaration); });
                }
                function writeVariableStatement(node) {
                    emitJsDocComments(node);
                    emitModuleElementDeclarationFlags(node);
                    if (ts.isLet(node.declarationList)) {
                        write("let ");
                    }
                    else if (ts.isConst(node.declarationList)) {
                        write("const ");
                    }
                    else {
                        write("var ");
                    }
                    emitCommaList(node.declarationList.declarations, emitVariableDeclaration, resolver.isDeclarationVisible);
                    write(";");
                    writeLine();
                }
                function emitAccessorDeclaration(node) {
                    if (ts.hasDynamicName(node)) {
                        return;
                    }
                    var accessors = ts.getAllAccessorDeclarations(node.parent.members, node);
                    var accessorWithTypeAnnotation;
                    if (node === accessors.firstAccessor) {
                        emitJsDocComments(accessors.getAccessor);
                        emitJsDocComments(accessors.setAccessor);
                        emitClassMemberDeclarationFlags(node);
                        writeTextOfNode(currentSourceFile, node.name);
                        if (!(node.flags & 32 /* Private */)) {
                            accessorWithTypeAnnotation = node;
                            var type = getTypeAnnotationFromAccessor(node);
                            if (!type) {
                                // couldn't get type for the first accessor, try the another one
                                var anotherAccessor = node.kind === 136 /* GetAccessor */ ? accessors.setAccessor : accessors.getAccessor;
                                type = getTypeAnnotationFromAccessor(anotherAccessor);
                                if (type) {
                                    accessorWithTypeAnnotation = anotherAccessor;
                                }
                            }
                            writeTypeOfDeclaration(node, type, getAccessorDeclarationTypeVisibilityError);
                        }
                        write(";");
                        writeLine();
                    }
                    function getTypeAnnotationFromAccessor(accessor) {
                        if (accessor) {
                            return accessor.kind === 136 /* GetAccessor */
                                ? accessor.type // Getter - return type
                                : accessor.parameters.length > 0
                                    ? accessor.parameters[0].type // Setter parameter type
                                    : undefined;
                        }
                    }
                    function getAccessorDeclarationTypeVisibilityError(symbolAccesibilityResult) {
                        var diagnosticMessage;
                        if (accessorWithTypeAnnotation.kind === 137 /* SetAccessor */) {
                            // Setters have to have type named and cannot infer it so, the type should always be named
                            if (accessorWithTypeAnnotation.parent.flags & 128 /* Static */) {
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
                                    ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
                                    ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1;
                            }
                            else {
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
                                    ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
                                    ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1;
                            }
                            return {
                                diagnosticMessage: diagnosticMessage,
                                errorNode: accessorWithTypeAnnotation.parameters[0],
                                // TODO(jfreeman): Investigate why we are passing node.name instead of node.parameters[0].name
                                typeName: accessorWithTypeAnnotation.name
                            };
                        }
                        else {
                            if (accessorWithTypeAnnotation.flags & 128 /* Static */) {
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
                                    symbolAccesibilityResult.accessibility === 2 /* CannotBeNamed */ ?
                                        ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
                                        ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 :
                                    ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0;
                            }
                            else {
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
                                    symbolAccesibilityResult.accessibility === 2 /* CannotBeNamed */ ?
                                        ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
                                        ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 :
                                    ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0;
                            }
                            return {
                                diagnosticMessage: diagnosticMessage,
                                errorNode: accessorWithTypeAnnotation.name,
                                typeName: undefined
                            };
                        }
                    }
                }
                function writeFunctionDeclaration(node) {
                    if (ts.hasDynamicName(node)) {
                        return;
                    }
                    // If we are emitting Method/Constructor it isn't moduleElement and hence already determined to be emitting
                    // so no need to verify if the declaration is visible
                    if (!resolver.isImplementationOfOverload(node)) {
                        emitJsDocComments(node);
                        if (node.kind === 200 /* FunctionDeclaration */) {
                            emitModuleElementDeclarationFlags(node);
                        }
                        else if (node.kind === 134 /* MethodDeclaration */) {
                            emitClassMemberDeclarationFlags(node);
                        }
                        if (node.kind === 200 /* FunctionDeclaration */) {
                            write("function ");
                            writeTextOfNode(currentSourceFile, node.name);
                        }
                        else if (node.kind === 135 /* Constructor */) {
                            write("constructor");
                        }
                        else {
                            writeTextOfNode(currentSourceFile, node.name);
                            if (ts.hasQuestionToken(node)) {
                                write("?");
                            }
                        }
                        emitSignatureDeclaration(node);
                    }
                }
                function emitSignatureDeclarationWithJsDocComments(node) {
                    emitJsDocComments(node);
                    emitSignatureDeclaration(node);
                }
                function emitSignatureDeclaration(node) {
                    // Construct signature or constructor type write new Signature
                    if (node.kind === 139 /* ConstructSignature */ || node.kind === 143 /* ConstructorType */) {
                        write("new ");
                    }
                    emitTypeParameters(node.typeParameters);
                    if (node.kind === 140 /* IndexSignature */) {
                        write("[");
                    }
                    else {
                        write("(");
                    }
                    var prevEnclosingDeclaration = enclosingDeclaration;
                    enclosingDeclaration = node;
                    // Parameters
                    emitCommaList(node.parameters, emitParameterDeclaration);
                    if (node.kind === 140 /* IndexSignature */) {
                        write("]");
                    }
                    else {
                        write(")");
                    }
                    // If this is not a constructor and is not private, emit the return type
                    var isFunctionTypeOrConstructorType = node.kind === 142 /* FunctionType */ || node.kind === 143 /* ConstructorType */;
                    if (isFunctionTypeOrConstructorType || node.parent.kind === 145 /* TypeLiteral */) {
                        // Emit type literal signature return type only if specified
                        if (node.type) {
                            write(isFunctionTypeOrConstructorType ? " => " : ": ");
                            emitType(node.type);
                        }
                    }
                    else if (node.kind !== 135 /* Constructor */ && !(node.flags & 32 /* Private */)) {
                        writeReturnTypeAtSignature(node, getReturnTypeVisibilityError);
                    }
                    enclosingDeclaration = prevEnclosingDeclaration;
                    if (!isFunctionTypeOrConstructorType) {
                        write(";");
                        writeLine();
                    }
                    function getReturnTypeVisibilityError(symbolAccesibilityResult) {
                        var diagnosticMessage;
                        switch (node.kind) {
                            case 139 /* ConstructSignature */:
                                // Interfaces cannot have return types that cannot be named
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
                                    ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 :
                                    ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0;
                                break;
                            case 138 /* CallSignature */:
                                // Interfaces cannot have return types that cannot be named
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
                                    ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 :
                                    ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0;
                                break;
                            case 140 /* IndexSignature */:
                                // Interfaces cannot have return types that cannot be named
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
                                    ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 :
                                    ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0;
                                break;
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                                if (node.flags & 128 /* Static */) {
                                    diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
                                        symbolAccesibilityResult.accessibility === 2 /* CannotBeNamed */ ?
                                            ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
                                            ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 :
                                        ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0;
                                }
                                else if (node.parent.kind === 201 /* ClassDeclaration */) {
                                    diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
                                        symbolAccesibilityResult.accessibility === 2 /* CannotBeNamed */ ?
                                            ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
                                            ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 :
                                        ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0;
                                }
                                else {
                                    // Interfaces cannot have return types that cannot be named
                                    diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
                                        ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 :
                                        ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0;
                                }
                                break;
                            case 200 /* FunctionDeclaration */:
                                diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
                                    symbolAccesibilityResult.accessibility === 2 /* CannotBeNamed */ ?
                                        ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
                                        ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 :
                                    ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0;
                                break;
                            default:
                                ts.Debug.fail("This is unknown kind for signature: " + node.kind);
                        }
                        return {
                            diagnosticMessage: diagnosticMessage,
                            errorNode: node.name || node
                        };
                    }
                }
                function emitParameterDeclaration(node) {
                    increaseIndent();
                    emitJsDocComments(node);
                    if (node.dotDotDotToken) {
                        write("...");
                    }
                    if (ts.isBindingPattern(node.name)) {
                        // For bindingPattern, we can't simply writeTextOfNode from the source file
                        // because we want to omit the initializer and using writeTextOfNode will result in initializer get emitted.
                        // Therefore, we will have to recursively emit each element in the bindingPattern.
                        emitBindingPattern(node.name);
                    }
                    else {
                        writeTextOfNode(currentSourceFile, node.name);
                    }
                    if (node.initializer || ts.hasQuestionToken(node)) {
                        write("?");
                    }
                    decreaseIndent();
                    if (node.parent.kind === 142 /* FunctionType */ ||
                        node.parent.kind === 143 /* ConstructorType */ ||
                        node.parent.parent.kind === 145 /* TypeLiteral */) {
                        emitTypeOfVariableDeclarationFromTypeLiteral(node);
                    }
                    else if (!(node.parent.flags & 32 /* Private */)) {
                        writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError);
                    }
                    function getParameterDeclarationTypeVisibilityError(symbolAccesibilityResult) {
                        var diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
                        return diagnosticMessage !== undefined ? {
                            diagnosticMessage: diagnosticMessage,
                            errorNode: node,
                            typeName: node.name
                        } : undefined;
                    }
                    function getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult) {
                        switch (node.parent.kind) {
                            case 135 /* Constructor */:
                                return symbolAccesibilityResult.errorModuleName ?
                                    symbolAccesibilityResult.accessibility === 2 /* CannotBeNamed */ ?
                                        ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
                                        ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
                                    ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1;
                            case 139 /* ConstructSignature */:
                                // Interfaces cannot have parameter types that cannot be named
                                return symbolAccesibilityResult.errorModuleName ?
                                    ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 :
                                    ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1;
                            case 138 /* CallSignature */:
                                // Interfaces cannot have parameter types that cannot be named
                                return symbolAccesibilityResult.errorModuleName ?
                                    ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 :
                                    ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1;
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                                if (node.parent.flags & 128 /* Static */) {
                                    return symbolAccesibilityResult.errorModuleName ?
                                        symbolAccesibilityResult.accessibility === 2 /* CannotBeNamed */ ?
                                            ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
                                            ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
                                        ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1;
                                }
                                else if (node.parent.parent.kind === 201 /* ClassDeclaration */) {
                                    return symbolAccesibilityResult.errorModuleName ?
                                        symbolAccesibilityResult.accessibility === 2 /* CannotBeNamed */ ?
                                            ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
                                            ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
                                        ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1;
                                }
                                else {
                                    // Interfaces cannot have parameter types that cannot be named
                                    return symbolAccesibilityResult.errorModuleName ?
                                        ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 :
                                        ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1;
                                }
                            case 200 /* FunctionDeclaration */:
                                return symbolAccesibilityResult.errorModuleName ?
                                    symbolAccesibilityResult.accessibility === 2 /* CannotBeNamed */ ?
                                        ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
                                        ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 :
                                    ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1;
                            default:
                                ts.Debug.fail("This is unknown parent for parameter: " + node.parent.kind);
                        }
                    }
                    function emitBindingPattern(bindingPattern) {
                        // We have to explicitly emit square bracket and bracket because these tokens are not store inside the node.
                        if (bindingPattern.kind === 150 /* ObjectBindingPattern */) {
                            write("{");
                            emitCommaList(bindingPattern.elements, emitBindingElement);
                            write("}");
                        }
                        else if (bindingPattern.kind === 151 /* ArrayBindingPattern */) {
                            write("[");
                            var elements = bindingPattern.elements;
                            emitCommaList(elements, emitBindingElement);
                            if (elements && elements.hasTrailingComma) {
                                write(", ");
                            }
                            write("]");
                        }
                    }
                    function emitBindingElement(bindingElement) {
                        function getBindingElementTypeVisibilityError(symbolAccesibilityResult) {
                            var diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
                            return diagnosticMessage !== undefined ? {
                                diagnosticMessage: diagnosticMessage,
                                errorNode: bindingElement,
                                typeName: bindingElement.name
                            } : undefined;
                        }
                        if (bindingElement.kind === 175 /* OmittedExpression */) {
                            // If bindingElement is an omittedExpression (i.e. containing elision),
                            // we will emit blank space (although this may differ from users' original code,
                            // it allows emitSeparatedList to write separator appropriately)
                            // Example:
                            //      original: function foo([, x, ,]) {}
                            //      emit    : function foo([ , x,  , ]) {}
                            write(" ");
                        }
                        else if (bindingElement.kind === 152 /* BindingElement */) {
                            if (bindingElement.propertyName) {
                                // bindingElement has propertyName property in the following case:
                                //      { y: [a,b,c] ...} -> bindingPattern will have a property called propertyName for "y"
                                // We have to explicitly emit the propertyName before descending into its binding elements.
                                // Example:
                                //      original: function foo({y: [a,b,c]}) {}
                                //      emit    : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void;
                                writeTextOfNode(currentSourceFile, bindingElement.propertyName);
                                write(": ");
                                // If bindingElement has propertyName property, then its name must be another bindingPattern of SyntaxKind.ObjectBindingPattern
                                emitBindingPattern(bindingElement.name);
                            }
                            else if (bindingElement.name) {
                                if (ts.isBindingPattern(bindingElement.name)) {
                                    // If it is a nested binding pattern, we will recursively descend into each element and emit each one separately.
                                    // In the case of rest element, we will omit rest element.
                                    // Example:
                                    //      original: function foo([a, [[b]], c] = [1,[["string"]], 3]) {}
                                    //      emit    : declare function foo([a, [[b]], c]: [number, [[string]], number]): void;
                                    //      original with rest: function foo([a, ...c]) {}
                                    //      emit              : declare function foo([a, ...c]): void;
                                    emitBindingPattern(bindingElement.name);
                                }
                                else {
                                    ts.Debug.assert(bindingElement.name.kind === 65 /* Identifier */);
                                    // If the node is just an identifier, we will simply emit the text associated with the node's name
                                    // Example:
                                    //      original: function foo({y = 10, x}) {}
                                    //      emit    : declare function foo({y, x}: {number, any}): void;
                                    if (bindingElement.dotDotDotToken) {
                                        write("...");
                                    }
                                    writeTextOfNode(currentSourceFile, bindingElement.name);
                                }
                            }
                        }
                    }
                }
                function emitNode(node) {
                    switch (node.kind) {
                        case 200 /* FunctionDeclaration */:
                        case 205 /* ModuleDeclaration */:
                        case 208 /* ImportEqualsDeclaration */:
                        case 202 /* InterfaceDeclaration */:
                        case 201 /* ClassDeclaration */:
                        case 203 /* TypeAliasDeclaration */:
                        case 204 /* EnumDeclaration */:
                            return emitModuleElement(node, isModuleElementVisible(node));
                        case 180 /* VariableStatement */:
                            return emitModuleElement(node, isVariableStatementVisible(node));
                        case 209 /* ImportDeclaration */:
                            // Import declaration without import clause is visible, otherwise it is not visible
                            return emitModuleElement(node, !node.importClause);
                        case 215 /* ExportDeclaration */:
                            return emitExportDeclaration(node);
                        case 135 /* Constructor */:
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                            return writeFunctionDeclaration(node);
                        case 139 /* ConstructSignature */:
                        case 138 /* CallSignature */:
                        case 140 /* IndexSignature */:
                            return emitSignatureDeclarationWithJsDocComments(node);
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                            return emitAccessorDeclaration(node);
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                            return emitPropertyDeclaration(node);
                        case 226 /* EnumMember */:
                            return emitEnumMemberDeclaration(node);
                        case 214 /* ExportAssignment */:
                            return emitExportAssignment(node);
                        case 227 /* SourceFile */:
                            return emitSourceFile(node);
                    }
                }
                function writeReferencePath(referencedFile) {
                    var declFileName = referencedFile.flags & 2048 /* DeclarationFile */
                        ? referencedFile.fileName // Declaration file, use declaration file name
                        : ts.shouldEmitToOwnFile(referencedFile, compilerOptions)
                            ? ts.getOwnEmitOutputFilePath(referencedFile, host, ".d.ts") // Own output file so get the .d.ts file
                            : ts.removeFileExtension(compilerOptions.out) + ".d.ts"; // Global out file
                    declFileName = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizeSlashes(jsFilePath)), declFileName, host.getCurrentDirectory(), host.getCanonicalFileName, 
                    /*isAbsolutePathAnUrl*/ false);
                    referencePathsOutput += "/// <reference path=\"" + declFileName + "\" />" + newLine;
                }
            }
            /* @internal */
            function writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics) {
                var emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, jsFilePath, sourceFile);
                // TODO(shkamat): Should we not write any declaration file if any of them can produce error,
                // or should we just not write this file like we are doing now
                if (!emitDeclarationResult.reportedDeclarationError) {
                    var declarationOutput = emitDeclarationResult.referencePathsOutput
                        + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
                    ts.writeFile(host, diagnostics, ts.removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, host.getCompilerOptions().emitBOM);
                }
                function getDeclarationOutput(synchronousDeclarationOutput, moduleElementDeclarationEmitInfo) {
                    var appliedSyncOutputPos = 0;
                    var declarationOutput = "";
                    // apply asynchronous additions to the synchronous output
                    ts.forEach(moduleElementDeclarationEmitInfo, function (aliasEmitInfo) {
                        if (aliasEmitInfo.asynchronousOutput) {
                            declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos);
                            declarationOutput += getDeclarationOutput(aliasEmitInfo.asynchronousOutput, aliasEmitInfo.subModuleElementDeclarationEmitInfo);
                            appliedSyncOutputPos = aliasEmitInfo.outputPos;
                        }
                    });
                    declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos);
                    return declarationOutput;
                }
            }
            ts.writeDeclarationFile = writeDeclarationFile;
        })(ts || (ts = {}));
        /// <reference path="checker.ts"/>
        /// <reference path="declarationEmitter.ts"/>
        /* @internal */
        var ts;
        (function (ts) {
            function isExternalModuleOrDeclarationFile(sourceFile) {
                return ts.isExternalModule(sourceFile) || ts.isDeclarationFile(sourceFile);
            }
            ts.isExternalModuleOrDeclarationFile = isExternalModuleOrDeclarationFile;
            // Flags enum to track count of temp variables and a few dedicated names
            var TempFlags;
            (function (TempFlags) {
                TempFlags[TempFlags["Auto"] = 0] = "Auto";
                TempFlags[TempFlags["CountMask"] = 268435455] = "CountMask";
                TempFlags[TempFlags["_i"] = 268435456] = "_i";
                TempFlags[TempFlags["_n"] = 536870912] = "_n";
            })(TempFlags || (TempFlags = {}));
            // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
            function emitFiles(resolver, host, targetSourceFile) {
                // emit output for the __extends helper function
                var extendsHelper = "\nvar __extends = this.__extends || function (d, b) {\n    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n    function __() { this.constructor = d; }\n    __.prototype = b.prototype;\n    d.prototype = new __();\n};";
                // emit output for the __decorate helper function
                var decorateHelper = "\nif (typeof __decorate !== \"function\") __decorate = function (decorators, target, key, desc) {\n    if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") return Reflect.decorate(decorators, target, key, desc);\n    switch (arguments.length) {\n        case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);\n        case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);\n        case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);\n    }\n};";
                // emit output for the __metadata helper function
                var metadataHelper = "\nif (typeof __metadata !== \"function\") __metadata = function (k, v) {\n    if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};";
                // emit output for the __param helper function
                var paramHelper = "\nif (typeof __param !== \"function\") __param = function (paramIndex, decorator) {\n    return function (target, key) { decorator(target, key, paramIndex); }\n};";
                var compilerOptions = host.getCompilerOptions();
                var languageVersion = compilerOptions.target || 0 /* ES3 */;
                var sourceMapDataList = compilerOptions.sourceMap ? [] : undefined;
                var diagnostics = [];
                var newLine = host.getNewLine();
                if (targetSourceFile === undefined) {
                    ts.forEach(host.getSourceFiles(), function (sourceFile) {
                        if (ts.shouldEmitToOwnFile(sourceFile, compilerOptions)) {
                            var jsFilePath = ts.getOwnEmitOutputFilePath(sourceFile, host, ".js");
                            emitFile(jsFilePath, sourceFile);
                        }
                    });
                    if (compilerOptions.out) {
                        emitFile(compilerOptions.out);
                    }
                }
                else {
                    // targetSourceFile is specified (e.g calling emitter from language service or calling getSemanticDiagnostic from language service)
                    if (ts.shouldEmitToOwnFile(targetSourceFile, compilerOptions)) {
                        var jsFilePath = ts.getOwnEmitOutputFilePath(targetSourceFile, host, ".js");
                        emitFile(jsFilePath, targetSourceFile);
                    }
                    else if (!ts.isDeclarationFile(targetSourceFile) && compilerOptions.out) {
                        emitFile(compilerOptions.out);
                    }
                }
                // Sort and make the unique list of diagnostics
                diagnostics = ts.sortAndDeduplicateDiagnostics(diagnostics);
                return {
                    emitSkipped: false,
                    diagnostics: diagnostics,
                    sourceMaps: sourceMapDataList
                };
                function isNodeDescendentOf(node, ancestor) {
                    while (node) {
                        if (node === ancestor)
                            return true;
                        node = node.parent;
                    }
                    return false;
                }
                function isUniqueLocalName(name, container) {
                    for (var node = container; isNodeDescendentOf(node, container); node = node.nextContainer) {
                        if (node.locals && ts.hasProperty(node.locals, name)) {
                            // We conservatively include alias symbols to cover cases where they're emitted as locals
                            if (node.locals[name].flags & (107455 /* Value */ | 1048576 /* ExportValue */ | 8388608 /* Alias */)) {
                                return false;
                            }
                        }
                    }
                    return true;
                }
                function emitJavaScript(jsFilePath, root) {
                    var writer = ts.createTextWriter(newLine);
                    var write = writer.write;
                    var writeTextOfNode = writer.writeTextOfNode;
                    var writeLine = writer.writeLine;
                    var increaseIndent = writer.increaseIndent;
                    var decreaseIndent = writer.decreaseIndent;
                    var currentSourceFile;
                    var generatedNameSet = {};
                    var nodeToGeneratedName = [];
                    var blockScopedVariableToGeneratedName;
                    var computedPropertyNamesToGeneratedNames;
                    var extendsEmitted = false;
                    var decorateEmitted = false;
                    var paramEmitted = false;
                    var tempFlags = 0;
                    var tempVariables;
                    var tempParameters;
                    var externalImports;
                    var exportSpecifiers;
                    var exportEquals;
                    var hasExportStars;
                    /** write emitted output to disk*/
                    var writeEmittedFiles = writeJavaScriptFile;
                    var detachedCommentsInfo;
                    var writeComment = ts.writeCommentRange;
                    /** Emit a node */
                    var emit = emitNodeWithoutSourceMap;
                    /** Called just before starting emit of a node */
                    var emitStart = function (node) { };
                    /** Called once the emit of the node is done */
                    var emitEnd = function (node) { };
                    /** Emit the text for the given token that comes after startPos
                      * This by default writes the text provided with the given tokenKind
                      * but if optional emitFn callback is provided the text is emitted using the callback instead of default text
                      * @param tokenKind the kind of the token to search and emit
                      * @param startPos the position in the source to start searching for the token
                      * @param emitFn if given will be invoked to emit the text instead of actual token emit */
                    var emitToken = emitTokenText;
                    /** Called to before starting the lexical scopes as in function/class in the emitted code because of node
                      * @param scopeDeclaration node that starts the lexical scope
                      * @param scopeName Optional name of this scope instead of deducing one from the declaration node */
                    var scopeEmitStart = function (scopeDeclaration, scopeName) { };
                    /** Called after coming out of the scope */
                    var scopeEmitEnd = function () { };
                    /** Sourcemap data that will get encoded */
                    var sourceMapData;
                    if (compilerOptions.sourceMap) {
                        initializeEmitterWithSourceMaps();
                    }
                    if (root) {
                        // Do not call emit directly. It does not set the currentSourceFile.
                        emitSourceFile(root);
                    }
                    else {
                        ts.forEach(host.getSourceFiles(), function (sourceFile) {
                            if (!isExternalModuleOrDeclarationFile(sourceFile)) {
                                emitSourceFile(sourceFile);
                            }
                        });
                    }
                    writeLine();
                    writeEmittedFiles(writer.getText(), compilerOptions.emitBOM);
                    return;
                    function emitSourceFile(sourceFile) {
                        currentSourceFile = sourceFile;
                        emit(sourceFile);
                    }
                    function isUniqueName(name) {
                        return !resolver.hasGlobalName(name) &&
                            !ts.hasProperty(currentSourceFile.identifiers, name) &&
                            !ts.hasProperty(generatedNameSet, name);
                    }
                    // Return the next available name in the pattern _a ... _z, _0, _1, ...
                    // TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name.
                    // Note that names generated by makeTempVariableName and makeUniqueName will never conflict.
                    function makeTempVariableName(flags) {
                        if (flags && !(tempFlags & flags)) {
                            var name = flags === 268435456 /* _i */ ? "_i" : "_n";
                            if (isUniqueName(name)) {
                                tempFlags |= flags;
                                return name;
                            }
                        }
                        while (true) {
                            var count = tempFlags & 268435455 /* CountMask */;
                            tempFlags++;
                            // Skip over 'i' and 'n'
                            if (count !== 8 && count !== 13) {
                                var name_15 = count < 26 ? "_" + String.fromCharCode(97 /* a */ + count) : "_" + (count - 26);
                                if (isUniqueName(name_15)) {
                                    return name_15;
                                }
                            }
                        }
                    }
                    // Generate a name that is unique within the current file and doesn't conflict with any names
                    // in global scope. The name is formed by adding an '_n' suffix to the specified base name,
                    // where n is a positive integer. Note that names generated by makeTempVariableName and
                    // makeUniqueName are guaranteed to never conflict.
                    function makeUniqueName(baseName) {
                        // Find the first unique 'name_n', where n is a positive number
                        if (baseName.charCodeAt(baseName.length - 1) !== 95 /* _ */) {
                            baseName += "_";
                        }
                        var i = 1;
                        while (true) {
                            var generatedName = baseName + i;
                            if (isUniqueName(generatedName)) {
                                return generatedNameSet[generatedName] = generatedName;
                            }
                            i++;
                        }
                    }
                    function assignGeneratedName(node, name) {
                        nodeToGeneratedName[ts.getNodeId(node)] = ts.unescapeIdentifier(name);
                    }
                    function generateNameForFunctionOrClassDeclaration(node) {
                        if (!node.name) {
                            assignGeneratedName(node, makeUniqueName("default"));
                        }
                    }
                    function generateNameForModuleOrEnum(node) {
                        if (node.name.kind === 65 /* Identifier */) {
                            var name_16 = node.name.text;
                            // Use module/enum name itself if it is unique, otherwise make a unique variation
                            assignGeneratedName(node, isUniqueLocalName(name_16, node) ? name_16 : makeUniqueName(name_16));
                        }
                    }
                    function generateNameForImportOrExportDeclaration(node) {
                        var expr = ts.getExternalModuleName(node);
                        var baseName = expr.kind === 8 /* StringLiteral */ ?
                            ts.escapeIdentifier(ts.makeIdentifierFromModuleName(expr.text)) : "module";
                        assignGeneratedName(node, makeUniqueName(baseName));
                    }
                    function generateNameForImportDeclaration(node) {
                        if (node.importClause) {
                            generateNameForImportOrExportDeclaration(node);
                        }
                    }
                    function generateNameForExportDeclaration(node) {
                        if (node.moduleSpecifier) {
                            generateNameForImportOrExportDeclaration(node);
                        }
                    }
                    function generateNameForExportAssignment(node) {
                        if (node.expression && node.expression.kind !== 65 /* Identifier */) {
                            assignGeneratedName(node, makeUniqueName("default"));
                        }
                    }
                    function generateNameForNode(node) {
                        switch (node.kind) {
                            case 200 /* FunctionDeclaration */:
                            case 201 /* ClassDeclaration */:
                            case 174 /* ClassExpression */:
                                generateNameForFunctionOrClassDeclaration(node);
                                break;
                            case 205 /* ModuleDeclaration */:
                                generateNameForModuleOrEnum(node);
                                generateNameForNode(node.body);
                                break;
                            case 204 /* EnumDeclaration */:
                                generateNameForModuleOrEnum(node);
                                break;
                            case 209 /* ImportDeclaration */:
                                generateNameForImportDeclaration(node);
                                break;
                            case 215 /* ExportDeclaration */:
                                generateNameForExportDeclaration(node);
                                break;
                            case 214 /* ExportAssignment */:
                                generateNameForExportAssignment(node);
                                break;
                        }
                    }
                    function getGeneratedNameForNode(node) {
                        var nodeId = ts.getNodeId(node);
                        if (!nodeToGeneratedName[nodeId]) {
                            generateNameForNode(node);
                        }
                        return nodeToGeneratedName[nodeId];
                    }
                    function initializeEmitterWithSourceMaps() {
                        var sourceMapDir; // The directory in which sourcemap will be
                        // Current source map file and its index in the sources list
                        var sourceMapSourceIndex = -1;
                        // Names and its index map
                        var sourceMapNameIndexMap = {};
                        var sourceMapNameIndices = [];
                        function getSourceMapNameIndex() {
                            return sourceMapNameIndices.length ? sourceMapNameIndices[sourceMapNameIndices.length - 1] : -1;
                        }
                        // Last recorded and encoded spans
                        var lastRecordedSourceMapSpan;
                        var lastEncodedSourceMapSpan = {
                            emittedLine: 1,
                            emittedColumn: 1,
                            sourceLine: 1,
                            sourceColumn: 1,
                            sourceIndex: 0
                        };
                        var lastEncodedNameIndex = 0;
                        // Encoding for sourcemap span
                        function encodeLastRecordedSourceMapSpan() {
                            if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) {
                                return;
                            }
                            var prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn;
                            // Line/Comma delimiters
                            if (lastEncodedSourceMapSpan.emittedLine == lastRecordedSourceMapSpan.emittedLine) {
                                // Emit comma to separate the entry
                                if (sourceMapData.sourceMapMappings) {
                                    sourceMapData.sourceMapMappings += ",";
                                }
                            }
                            else {
                                // Emit line delimiters
                                for (var encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
                                    sourceMapData.sourceMapMappings += ";";
                                }
                                prevEncodedEmittedColumn = 1;
                            }
                            // 1. Relative Column 0 based
                            sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn);
                            // 2. Relative sourceIndex
                            sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex);
                            // 3. Relative sourceLine 0 based
                            sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine);
                            // 4. Relative sourceColumn 0 based
                            sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn);
                            // 5. Relative namePosition 0 based
                            if (lastRecordedSourceMapSpan.nameIndex >= 0) {
                                sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex);
                                lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex;
                            }
                            lastEncodedSourceMapSpan = lastRecordedSourceMapSpan;
                            sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan);
                            function base64VLQFormatEncode(inValue) {
                                function base64FormatEncode(inValue) {
                                    if (inValue < 64) {
                                        return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.charAt(inValue);
                                    }
                                    throw TypeError(inValue + ": not a 64 based value");
                                }
                                // Add a new least significant bit that has the sign of the value.
                                // if negative number the least significant bit that gets added to the number has value 1
                                // else least significant bit value that gets added is 0
                                // eg. -1 changes to binary : 01 [1] => 3
                                //     +1 changes to binary : 01 [0] => 2
                                if (inValue < 0) {
                                    inValue = ((-inValue) << 1) + 1;
                                }
                                else {
                                    inValue = inValue << 1;
                                }
                                // Encode 5 bits at a time starting from least significant bits
                                var encodedStr = "";
                                do {
                                    var currentDigit = inValue & 31; // 11111
                                    inValue = inValue >> 5;
                                    if (inValue > 0) {
                                        // There are still more digits to decode, set the msb (6th bit)
                                        currentDigit = currentDigit | 32;
                                    }
                                    encodedStr = encodedStr + base64FormatEncode(currentDigit);
                                } while (inValue > 0);
                                return encodedStr;
                            }
                        }
                        function recordSourceMapSpan(pos) {
                            var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSourceFile, pos);
                            // Convert the location to be one-based.
                            sourceLinePos.line++;
                            sourceLinePos.character++;
                            var emittedLine = writer.getLine();
                            var emittedColumn = writer.getColumn();
                            // If this location wasn't recorded or the location in source is going backwards, record the span
                            if (!lastRecordedSourceMapSpan ||
                                lastRecordedSourceMapSpan.emittedLine != emittedLine ||
                                lastRecordedSourceMapSpan.emittedColumn != emittedColumn ||
                                (lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex &&
                                    (lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line ||
                                        (lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) {
                                // Encode the last recordedSpan before assigning new
                                encodeLastRecordedSourceMapSpan();
                                // New span
                                lastRecordedSourceMapSpan = {
                                    emittedLine: emittedLine,
                                    emittedColumn: emittedColumn,
                                    sourceLine: sourceLinePos.line,
                                    sourceColumn: sourceLinePos.character,
                                    nameIndex: getSourceMapNameIndex(),
                                    sourceIndex: sourceMapSourceIndex
                                };
                            }
                            else {
                                // Take the new pos instead since there is no change in emittedLine and column since last location
                                lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line;
                                lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character;
                                lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex;
                            }
                        }
                        function recordEmitNodeStartSpan(node) {
                            // Get the token pos after skipping to the token (ignoring the leading trivia)
                            recordSourceMapSpan(ts.skipTrivia(currentSourceFile.text, node.pos));
                        }
                        function recordEmitNodeEndSpan(node) {
                            recordSourceMapSpan(node.end);
                        }
                        function writeTextWithSpanRecord(tokenKind, startPos, emitFn) {
                            var tokenStartPos = ts.skipTrivia(currentSourceFile.text, startPos);
                            recordSourceMapSpan(tokenStartPos);
                            var tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn);
                            recordSourceMapSpan(tokenEndPos);
                            return tokenEndPos;
                        }
                        function recordNewSourceFileStart(node) {
                            // Add the file to tsFilePaths
                            // If sourceroot option: Use the relative path corresponding to the common directory path
                            // otherwise source locations relative to map file location
                            var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir;
                            sourceMapData.sourceMapSources.push(ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, node.fileName, host.getCurrentDirectory(), host.getCanonicalFileName, 
                            /*isAbsolutePathAnUrl*/ true));
                            sourceMapSourceIndex = sourceMapData.sourceMapSources.length - 1;
                            // The one that can be used from program to get the actual source file
                            sourceMapData.inputSourceFileNames.push(node.fileName);
                        }
                        function recordScopeNameOfNode(node, scopeName) {
                            function recordScopeNameIndex(scopeNameIndex) {
                                sourceMapNameIndices.push(scopeNameIndex);
                            }
                            function recordScopeNameStart(scopeName) {
                                var scopeNameIndex = -1;
                                if (scopeName) {
                                    var parentIndex = getSourceMapNameIndex();
                                    if (parentIndex !== -1) {
                                        // Child scopes are always shown with a dot (even if they have no name),
                                        // unless it is a computed property. Then it is shown with brackets,
                                        // but the brackets are included in the name.
                                        var name_17 = node.name;
                                        if (!name_17 || name_17.kind !== 127 /* ComputedPropertyName */) {
                                            scopeName = "." + scopeName;
                                        }
                                        scopeName = sourceMapData.sourceMapNames[parentIndex] + scopeName;
                                    }
                                    scopeNameIndex = ts.getProperty(sourceMapNameIndexMap, scopeName);
                                    if (scopeNameIndex === undefined) {
                                        scopeNameIndex = sourceMapData.sourceMapNames.length;
                                        sourceMapData.sourceMapNames.push(scopeName);
                                        sourceMapNameIndexMap[scopeName] = scopeNameIndex;
                                    }
                                }
                                recordScopeNameIndex(scopeNameIndex);
                            }
                            if (scopeName) {
                                // The scope was already given a name  use it
                                recordScopeNameStart(scopeName);
                            }
                            else if (node.kind === 200 /* FunctionDeclaration */ ||
                                node.kind === 162 /* FunctionExpression */ ||
                                node.kind === 134 /* MethodDeclaration */ ||
                                node.kind === 133 /* MethodSignature */ ||
                                node.kind === 136 /* GetAccessor */ ||
                                node.kind === 137 /* SetAccessor */ ||
                                node.kind === 205 /* ModuleDeclaration */ ||
                                node.kind === 201 /* ClassDeclaration */ ||
                                node.kind === 204 /* EnumDeclaration */) {
                                // Declaration and has associated name use it
                                if (node.name) {
                                    var name_18 = node.name;
                                    // For computed property names, the text will include the brackets
                                    scopeName = name_18.kind === 127 /* ComputedPropertyName */
                                        ? ts.getTextOfNode(name_18)
                                        : node.name.text;
                                }
                                recordScopeNameStart(scopeName);
                            }
                            else {
                                // Block just use the name from upper level scope
                                recordScopeNameIndex(getSourceMapNameIndex());
                            }
                        }
                        function recordScopeNameEnd() {
                            sourceMapNameIndices.pop();
                        }
                        ;
                        function writeCommentRangeWithMap(curentSourceFile, writer, comment, newLine) {
                            recordSourceMapSpan(comment.pos);
                            ts.writeCommentRange(currentSourceFile, writer, comment, newLine);
                            recordSourceMapSpan(comment.end);
                        }
                        function serializeSourceMapContents(version, file, sourceRoot, sources, names, mappings) {
                            if (typeof JSON !== "undefined") {
                                return JSON.stringify({
                                    version: version,
                                    file: file,
                                    sourceRoot: sourceRoot,
                                    sources: sources,
                                    names: names,
                                    mappings: mappings
                                });
                            }
                            return "{\"version\":" + version + ",\"file\":\"" + ts.escapeString(file) + "\",\"sourceRoot\":\"" + ts.escapeString(sourceRoot) + "\",\"sources\":[" + serializeStringArray(sources) + "],\"names\":[" + serializeStringArray(names) + "],\"mappings\":\"" + ts.escapeString(mappings) + "\"}";
                            function serializeStringArray(list) {
                                var output = "";
                                for (var i = 0, n = list.length; i < n; i++) {
                                    if (i) {
                                        output += ",";
                                    }
                                    output += "\"" + ts.escapeString(list[i]) + "\"";
                                }
                                return output;
                            }
                        }
                        function writeJavaScriptAndSourceMapFile(emitOutput, writeByteOrderMark) {
                            // Write source map file
                            encodeLastRecordedSourceMapSpan();
                            ts.writeFile(host, diagnostics, sourceMapData.sourceMapFilePath, serializeSourceMapContents(3, sourceMapData.sourceMapFile, sourceMapData.sourceMapSourceRoot, sourceMapData.sourceMapSources, sourceMapData.sourceMapNames, sourceMapData.sourceMapMappings), false);
                            sourceMapDataList.push(sourceMapData);
                            // Write sourcemap url to the js file and write the js file
                            writeJavaScriptFile(emitOutput + "//# sourceMappingURL=" + sourceMapData.jsSourceMappingURL, writeByteOrderMark);
                        }
                        // Initialize source map data
                        var sourceMapJsFile = ts.getBaseFileName(ts.normalizeSlashes(jsFilePath));
                        sourceMapData = {
                            sourceMapFilePath: jsFilePath + ".map",
                            jsSourceMappingURL: sourceMapJsFile + ".map",
                            sourceMapFile: sourceMapJsFile,
                            sourceMapSourceRoot: compilerOptions.sourceRoot || "",
                            sourceMapSources: [],
                            inputSourceFileNames: [],
                            sourceMapNames: [],
                            sourceMapMappings: "",
                            sourceMapDecodedMappings: []
                        };
                        // Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the
                        // relative paths of the sources list in the sourcemap
                        sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot);
                        if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== 47 /* slash */) {
                            sourceMapData.sourceMapSourceRoot += ts.directorySeparator;
                        }
                        if (compilerOptions.mapRoot) {
                            sourceMapDir = ts.normalizeSlashes(compilerOptions.mapRoot);
                            if (root) {
                                // For modules or multiple emit files the mapRoot will have directory structure like the sources
                                // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map
                                sourceMapDir = ts.getDirectoryPath(ts.getSourceFilePathInNewDir(root, host, sourceMapDir));
                            }
                            if (!ts.isRootedDiskPath(sourceMapDir) && !ts.isUrl(sourceMapDir)) {
                                // The relative paths are relative to the common directory
                                sourceMapDir = ts.combinePaths(host.getCommonSourceDirectory(), sourceMapDir);
                                sourceMapData.jsSourceMappingURL = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizePath(jsFilePath)), ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), host.getCurrentDirectory(), host.getCanonicalFileName, 
                                /*isAbsolutePathAnUrl*/ true);
                            }
                            else {
                                sourceMapData.jsSourceMappingURL = ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL);
                            }
                        }
                        else {
                            sourceMapDir = ts.getDirectoryPath(ts.normalizePath(jsFilePath));
                        }
                        function emitNodeWithSourceMap(node, allowGeneratedIdentifiers) {
                            if (node) {
                                if (ts.nodeIsSynthesized(node)) {
                                    return emitNodeWithoutSourceMap(node, false);
                                }
                                if (node.kind != 227 /* SourceFile */) {
                                    recordEmitNodeStartSpan(node);
                                    emitNodeWithoutSourceMap(node, allowGeneratedIdentifiers);
                                    recordEmitNodeEndSpan(node);
                                }
                                else {
                                    recordNewSourceFileStart(node);
                                    emitNodeWithoutSourceMap(node, false);
                                }
                            }
                        }
                        writeEmittedFiles = writeJavaScriptAndSourceMapFile;
                        emit = emitNodeWithSourceMap;
                        emitStart = recordEmitNodeStartSpan;
                        emitEnd = recordEmitNodeEndSpan;
                        emitToken = writeTextWithSpanRecord;
                        scopeEmitStart = recordScopeNameOfNode;
                        scopeEmitEnd = recordScopeNameEnd;
                        writeComment = writeCommentRangeWithMap;
                    }
                    function writeJavaScriptFile(emitOutput, writeByteOrderMark) {
                        ts.writeFile(host, diagnostics, jsFilePath, emitOutput, writeByteOrderMark);
                    }
                    // Create a temporary variable with a unique unused name.
                    function createTempVariable(flags) {
                        var result = ts.createSynthesizedNode(65 /* Identifier */);
                        result.text = makeTempVariableName(flags);
                        return result;
                    }
                    function recordTempDeclaration(name) {
                        if (!tempVariables) {
                            tempVariables = [];
                        }
                        tempVariables.push(name);
                    }
                    function createAndRecordTempVariable(flags) {
                        var temp = createTempVariable(flags);
                        recordTempDeclaration(temp);
                        return temp;
                    }
                    function emitTempDeclarations(newLine) {
                        if (tempVariables) {
                            if (newLine) {
                                writeLine();
                            }
                            else {
                                write(" ");
                            }
                            write("var ");
                            emitCommaList(tempVariables);
                            write(";");
                        }
                    }
                    function emitTokenText(tokenKind, startPos, emitFn) {
                        var tokenString = ts.tokenToString(tokenKind);
                        if (emitFn) {
                            emitFn();
                        }
                        else {
                            write(tokenString);
                        }
                        return startPos + tokenString.length;
                    }
                    function emitOptional(prefix, node) {
                        if (node) {
                            write(prefix);
                            emit(node);
                        }
                    }
                    function emitParenthesizedIf(node, parenthesized) {
                        if (parenthesized) {
                            write("(");
                        }
                        emit(node);
                        if (parenthesized) {
                            write(")");
                        }
                    }
                    function emitTrailingCommaIfPresent(nodeList) {
                        if (nodeList.hasTrailingComma) {
                            write(",");
                        }
                    }
                    function emitLinePreservingList(parent, nodes, allowTrailingComma, spacesBetweenBraces) {
                        ts.Debug.assert(nodes.length > 0);
                        increaseIndent();
                        if (nodeStartPositionsAreOnSameLine(parent, nodes[0])) {
                            if (spacesBetweenBraces) {
                                write(" ");
                            }
                        }
                        else {
                            writeLine();
                        }
                        for (var i = 0, n = nodes.length; i < n; i++) {
                            if (i) {
                                if (nodeEndIsOnSameLineAsNodeStart(nodes[i - 1], nodes[i])) {
                                    write(", ");
                                }
                                else {
                                    write(",");
                                    writeLine();
                                }
                            }
                            emit(nodes[i]);
                        }
                        if (nodes.hasTrailingComma && allowTrailingComma) {
                            write(",");
                        }
                        decreaseIndent();
                        if (nodeEndPositionsAreOnSameLine(parent, ts.lastOrUndefined(nodes))) {
                            if (spacesBetweenBraces) {
                                write(" ");
                            }
                        }
                        else {
                            writeLine();
                        }
                    }
                    function emitList(nodes, start, count, multiLine, trailingComma, leadingComma, noTrailingNewLine, emitNode) {
                        if (!emitNode) {
                            emitNode = emit;
                        }
                        for (var i = 0; i < count; i++) {
                            if (multiLine) {
                                if (i || leadingComma) {
                                    write(",");
                                }
                                writeLine();
                            }
                            else {
                                if (i || leadingComma) {
                                    write(", ");
                                }
                            }
                            emitNode(nodes[start + i]);
                            leadingComma = true;
                        }
                        if (trailingComma) {
                            write(",");
                        }
                        if (multiLine && !noTrailingNewLine) {
                            writeLine();
                        }
                        return count;
                    }
                    function emitCommaList(nodes) {
                        if (nodes) {
                            emitList(nodes, 0, nodes.length, false, false);
                        }
                    }
                    function emitLines(nodes) {
                        emitLinesStartingAt(nodes, 0);
                    }
                    function emitLinesStartingAt(nodes, startIndex) {
                        for (var i = startIndex; i < nodes.length; i++) {
                            writeLine();
                            emit(nodes[i]);
                        }
                    }
                    function isBinaryOrOctalIntegerLiteral(node, text) {
                        if (node.kind === 7 /* NumericLiteral */ && text.length > 1) {
                            switch (text.charCodeAt(1)) {
                                case 98 /* b */:
                                case 66 /* B */:
                                case 111 /* o */:
                                case 79 /* O */:
                                    return true;
                            }
                        }
                        return false;
                    }
                    function emitLiteral(node) {
                        var text = getLiteralText(node);
                        if (compilerOptions.sourceMap && (node.kind === 8 /* StringLiteral */ || ts.isTemplateLiteralKind(node.kind))) {
                            writer.writeLiteral(text);
                        }
                        else if (languageVersion < 2 /* ES6 */ && isBinaryOrOctalIntegerLiteral(node, text)) {
                            write(node.text);
                        }
                        else {
                            write(text);
                        }
                    }
                    function getLiteralText(node) {
                        // Any template literal or string literal with an extended escape
                        // (e.g. "\u{0067}") will need to be downleveled as a escaped string literal.
                        if (languageVersion < 2 /* ES6 */ && (ts.isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) {
                            return getQuotedEscapedLiteralText('"', node.text, '"');
                        }
                        // If we don't need to downlevel and we can reach the original source text using
                        // the node's parent reference, then simply get the text as it was originally written.
                        if (node.parent) {
                            return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
                        }
                        // If we can't reach the original source text, use the canonical form if it's a number,
                        // or an escaped quoted form of the original text if it's string-like.
                        switch (node.kind) {
                            case 8 /* StringLiteral */:
                                return getQuotedEscapedLiteralText('"', node.text, '"');
                            case 10 /* NoSubstitutionTemplateLiteral */:
                                return getQuotedEscapedLiteralText('`', node.text, '`');
                            case 11 /* TemplateHead */:
                                return getQuotedEscapedLiteralText('`', node.text, '${');
                            case 12 /* TemplateMiddle */:
                                return getQuotedEscapedLiteralText('}', node.text, '${');
                            case 13 /* TemplateTail */:
                                return getQuotedEscapedLiteralText('}', node.text, '`');
                            case 7 /* NumericLiteral */:
                                return node.text;
                        }
                        ts.Debug.fail("Literal kind '" + node.kind + "' not accounted for.");
                    }
                    function getQuotedEscapedLiteralText(leftQuote, text, rightQuote) {
                        return leftQuote + ts.escapeNonAsciiCharacters(ts.escapeString(text)) + rightQuote;
                    }
                    function emitDownlevelRawTemplateLiteral(node) {
                        // Find original source text, since we need to emit the raw strings of the tagged template.
                        // The raw strings contain the (escaped) strings of what the user wrote.
                        // Examples: `\n` is converted to "\\n", a template string with a newline to "\n".
                        var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
                        // text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"),
                        // thus we need to remove those characters.
                        // First template piece starts with "`", others with "}"
                        // Last template piece ends with "`", others with "${"
                        var isLast = node.kind === 10 /* NoSubstitutionTemplateLiteral */ || node.kind === 13 /* TemplateTail */;
                        text = text.substring(1, text.length - (isLast ? 1 : 2));
                        // Newline normalization:
                        // ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's
                        // <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> for both TV and TRV.
                        text = text.replace(/\r\n?/g, "\n");
                        text = ts.escapeString(text);
                        write('"' + text + '"');
                    }
                    function emitDownlevelTaggedTemplateArray(node, literalEmitter) {
                        write("[");
                        if (node.template.kind === 10 /* NoSubstitutionTemplateLiteral */) {
                            literalEmitter(node.template);
                        }
                        else {
                            literalEmitter(node.template.head);
                            ts.forEach(node.template.templateSpans, function (child) {
                                write(", ");
                                literalEmitter(child.literal);
                            });
                        }
                        write("]");
                    }
                    function emitDownlevelTaggedTemplate(node) {
                        var tempVariable = createAndRecordTempVariable(0 /* Auto */);
                        write("(");
                        emit(tempVariable);
                        write(" = ");
                        emitDownlevelTaggedTemplateArray(node, emit);
                        write(", ");
                        emit(tempVariable);
                        write(".raw = ");
                        emitDownlevelTaggedTemplateArray(node, emitDownlevelRawTemplateLiteral);
                        write(", ");
                        emitParenthesizedIf(node.tag, needsParenthesisForPropertyAccessOrInvocation(node.tag));
                        write("(");
                        emit(tempVariable);
                        // Now we emit the expressions
                        if (node.template.kind === 171 /* TemplateExpression */) {
                            ts.forEach(node.template.templateSpans, function (templateSpan) {
                                write(", ");
                                var needsParens = templateSpan.expression.kind === 169 /* BinaryExpression */
                                    && templateSpan.expression.operatorToken.kind === 23 /* CommaToken */;
                                emitParenthesizedIf(templateSpan.expression, needsParens);
                            });
                        }
                        write("))");
                    }
                    function emitTemplateExpression(node) {
                        // In ES6 mode and above, we can simply emit each portion of a template in order, but in
                        // ES3 & ES5 we must convert the template expression into a series of string concatenations.
                        if (languageVersion >= 2 /* ES6 */) {
                            ts.forEachChild(node, emit);
                            return;
                        }
                        var emitOuterParens = ts.isExpression(node.parent)
                            && templateNeedsParens(node, node.parent);
                        if (emitOuterParens) {
                            write("(");
                        }
                        var headEmitted = false;
                        if (shouldEmitTemplateHead()) {
                            emitLiteral(node.head);
                            headEmitted = true;
                        }
                        for (var i = 0, n = node.templateSpans.length; i < n; i++) {
                            var templateSpan = node.templateSpans[i];
                            // Check if the expression has operands and binds its operands less closely than binary '+'.
                            // If it does, we need to wrap the expression in parentheses. Otherwise, something like
                            //    `abc${ 1 << 2 }`
                            // becomes
                            //    "abc" + 1 << 2 + ""
                            // which is really
                            //    ("abc" + 1) << (2 + "")
                            // rather than
                            //    "abc" + (1 << 2) + ""
                            var needsParens = templateSpan.expression.kind !== 161 /* ParenthesizedExpression */
                                && comparePrecedenceToBinaryPlus(templateSpan.expression) !== 1 /* GreaterThan */;
                            if (i > 0 || headEmitted) {
                                // If this is the first span and the head was not emitted, then this templateSpan's
                                // expression will be the first to be emitted. Don't emit the preceding ' + ' in that
                                // case.
                                write(" + ");
                            }
                            emitParenthesizedIf(templateSpan.expression, needsParens);
                            // Only emit if the literal is non-empty.
                            // The binary '+' operator is left-associative, so the first string concatenation
                            // with the head will force the result up to this point to be a string.
                            // Emitting a '+ ""' has no semantic effect for middles and tails.
                            if (templateSpan.literal.text.length !== 0) {
                                write(" + ");
                                emitLiteral(templateSpan.literal);
                            }
                        }
                        if (emitOuterParens) {
                            write(")");
                        }
                        function shouldEmitTemplateHead() {
                            // If this expression has an empty head literal and the first template span has a non-empty
                            // literal, then emitting the empty head literal is not necessary.
                            //     `${ foo } and ${ bar }`
                            // can be emitted as
                            //     foo + " and " + bar
                            // This is because it is only required that one of the first two operands in the emit
                            // output must be a string literal, so that the other operand and all following operands
                            // are forced into strings.
                            //
                            // If the first template span has an empty literal, then the head must still be emitted.
                            //     `${ foo }${ bar }`
                            // must still be emitted as
                            //     "" + foo + bar
                            // There is always atleast one templateSpan in this code path, since
                            // NoSubstitutionTemplateLiterals are directly emitted via emitLiteral()
                            ts.Debug.assert(node.templateSpans.length !== 0);
                            return node.head.text.length !== 0 || node.templateSpans[0].literal.text.length === 0;
                        }
                        function templateNeedsParens(template, parent) {
                            switch (parent.kind) {
                                case 157 /* CallExpression */:
                                case 158 /* NewExpression */:
                                    return parent.expression === template;
                                case 159 /* TaggedTemplateExpression */:
                                case 161 /* ParenthesizedExpression */:
                                    return false;
                                default:
                                    return comparePrecedenceToBinaryPlus(parent) !== -1 /* LessThan */;
                            }
                        }
                        /**
                         * Returns whether the expression has lesser, greater,
                         * or equal precedence to the binary '+' operator
                         */
                        function comparePrecedenceToBinaryPlus(expression) {
                            // All binary expressions have lower precedence than '+' apart from '*', '/', and '%'
                            // which have greater precedence and '-' which has equal precedence.
                            // All unary operators have a higher precedence apart from yield.
                            // Arrow functions and conditionals have a lower precedence,
                            // although we convert the former into regular function expressions in ES5 mode,
                            // and in ES6 mode this function won't get called anyway.
                            //
                            // TODO (drosen): Note that we need to account for the upcoming 'yield' and
                            //                spread ('...') unary operators that are anticipated for ES6.
                            switch (expression.kind) {
                                case 169 /* BinaryExpression */:
                                    switch (expression.operatorToken.kind) {
                                        case 35 /* AsteriskToken */:
                                        case 36 /* SlashToken */:
                                        case 37 /* PercentToken */:
                                            return 1 /* GreaterThan */;
                                        case 33 /* PlusToken */:
                                        case 34 /* MinusToken */:
                                            return 0 /* EqualTo */;
                                        default:
                                            return -1 /* LessThan */;
                                    }
                                case 172 /* YieldExpression */:
                                case 170 /* ConditionalExpression */:
                                    return -1 /* LessThan */;
                                default:
                                    return 1 /* GreaterThan */;
                            }
                        }
                    }
                    function emitTemplateSpan(span) {
                        emit(span.expression);
                        emit(span.literal);
                    }
                    // This function specifically handles numeric/string literals for enum and accessor 'identifiers'.
                    // In a sense, it does not actually emit identifiers as much as it declares a name for a specific property.
                    // For example, this is utilized when feeding in a result to Object.defineProperty.
                    function emitExpressionForPropertyName(node) {
                        ts.Debug.assert(node.kind !== 152 /* BindingElement */);
                        if (node.kind === 8 /* StringLiteral */) {
                            emitLiteral(node);
                        }
                        else if (node.kind === 127 /* ComputedPropertyName */) {
                            // if this is a decorated computed property, we will need to capture the result
                            // of the property expression so that we can apply decorators later. This is to ensure 
                            // we don't introduce unintended side effects:
                            //
                            //   class C {
                            //     [_a = x]() { }
                            //   }
                            //
                            // The emit for the decorated computed property decorator is:
                            //
                            //   Object.defineProperty(C.prototype, _a, __decorate([dec], C.prototype, _a, Object.getOwnPropertyDescriptor(C.prototype, _a)));
                            //
                            if (ts.nodeIsDecorated(node.parent)) {
                                if (!computedPropertyNamesToGeneratedNames) {
                                    computedPropertyNamesToGeneratedNames = [];
                                }
                                var generatedName = computedPropertyNamesToGeneratedNames[ts.getNodeId(node)];
                                if (generatedName) {
                                    // we have already generated a variable for this node, write that value instead.
                                    write(generatedName);
                                    return;
                                }
                                generatedName = createAndRecordTempVariable(0 /* Auto */).text;
                                computedPropertyNamesToGeneratedNames[ts.getNodeId(node)] = generatedName;
                                write(generatedName);
                                write(" = ");
                            }
                            emit(node.expression);
                        }
                        else {
                            write("\"");
                            if (node.kind === 7 /* NumericLiteral */) {
                                write(node.text);
                            }
                            else {
                                writeTextOfNode(currentSourceFile, node);
                            }
                            write("\"");
                        }
                    }
                    function isNotExpressionIdentifier(node) {
                        var parent = node.parent;
                        switch (parent.kind) {
                            case 129 /* Parameter */:
                            case 198 /* VariableDeclaration */:
                            case 152 /* BindingElement */:
                            case 132 /* PropertyDeclaration */:
                            case 131 /* PropertySignature */:
                            case 224 /* PropertyAssignment */:
                            case 225 /* ShorthandPropertyAssignment */:
                            case 226 /* EnumMember */:
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                            case 200 /* FunctionDeclaration */:
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                            case 162 /* FunctionExpression */:
                            case 201 /* ClassDeclaration */:
                            case 202 /* InterfaceDeclaration */:
                            case 204 /* EnumDeclaration */:
                            case 205 /* ModuleDeclaration */:
                            case 208 /* ImportEqualsDeclaration */:
                            case 210 /* ImportClause */:
                            case 211 /* NamespaceImport */:
                                return parent.name === node;
                            case 213 /* ImportSpecifier */:
                            case 217 /* ExportSpecifier */:
                                return parent.name === node || parent.propertyName === node;
                            case 190 /* BreakStatement */:
                            case 189 /* ContinueStatement */:
                            case 214 /* ExportAssignment */:
                                return false;
                            case 194 /* LabeledStatement */:
                                return node.parent.label === node;
                        }
                    }
                    function emitExpressionIdentifier(node) {
                        var substitution = resolver.getExpressionNameSubstitution(node, getGeneratedNameForNode);
                        if (substitution) {
                            write(substitution);
                        }
                        else {
                            writeTextOfNode(currentSourceFile, node);
                        }
                    }
                    function getGeneratedNameForIdentifier(node) {
                        if (ts.nodeIsSynthesized(node) || !blockScopedVariableToGeneratedName) {
                            return undefined;
                        }
                        var variableId = resolver.getBlockScopedVariableId(node);
                        if (variableId === undefined) {
                            return undefined;
                        }
                        return blockScopedVariableToGeneratedName[variableId];
                    }
                    function emitIdentifier(node, allowGeneratedIdentifiers) {
                        if (allowGeneratedIdentifiers) {
                            var generatedName = getGeneratedNameForIdentifier(node);
                            if (generatedName) {
                                write(generatedName);
                                return;
                            }
                        }
                        if (!node.parent) {
                            write(node.text);
                        }
                        else if (!isNotExpressionIdentifier(node)) {
                            emitExpressionIdentifier(node);
                        }
                        else {
                            writeTextOfNode(currentSourceFile, node);
                        }
                    }
                    function emitThis(node) {
                        if (resolver.getNodeCheckFlags(node) & 2 /* LexicalThis */) {
                            write("_this");
                        }
                        else {
                            write("this");
                        }
                    }
                    function emitSuper(node) {
                        if (languageVersion >= 2 /* ES6 */) {
                            write("super");
                        }
                        else {
                            var flags = resolver.getNodeCheckFlags(node);
                            if (flags & 16 /* SuperInstance */) {
                                write("_super.prototype");
                            }
                            else {
                                write("_super");
                            }
                        }
                    }
                    function emitObjectBindingPattern(node) {
                        write("{ ");
                        var elements = node.elements;
                        emitList(elements, 0, elements.length, false, elements.hasTrailingComma);
                        write(" }");
                    }
                    function emitArrayBindingPattern(node) {
                        write("[");
                        var elements = node.elements;
                        emitList(elements, 0, elements.length, false, elements.hasTrailingComma);
                        write("]");
                    }
                    function emitBindingElement(node) {
                        if (node.propertyName) {
                            emit(node.propertyName, false);
                            write(": ");
                        }
                        if (node.dotDotDotToken) {
                            write("...");
                        }
                        if (ts.isBindingPattern(node.name)) {
                            emit(node.name);
                        }
                        else {
                            emitModuleMemberName(node);
                        }
                        emitOptional(" = ", node.initializer);
                    }
                    function emitSpreadElementExpression(node) {
                        write("...");
                        emit(node.expression);
                    }
                    function emitYieldExpression(node) {
                        write(ts.tokenToString(110 /* YieldKeyword */));
                        if (node.asteriskToken) {
                            write("*");
                        }
                        if (node.expression) {
                            write(" ");
                            emit(node.expression);
                        }
                    }
                    function needsParenthesisForPropertyAccessOrInvocation(node) {
                        switch (node.kind) {
                            case 65 /* Identifier */:
                            case 153 /* ArrayLiteralExpression */:
                            case 155 /* PropertyAccessExpression */:
                            case 156 /* ElementAccessExpression */:
                            case 157 /* CallExpression */:
                            case 161 /* ParenthesizedExpression */:
                                // This list is not exhaustive and only includes those cases that are relevant
                                // to the check in emitArrayLiteral. More cases can be added as needed.
                                return false;
                        }
                        return true;
                    }
                    function emitListWithSpread(elements, multiLine, trailingComma) {
                        var pos = 0;
                        var group = 0;
                        var length = elements.length;
                        while (pos < length) {
                            // Emit using the pattern <group0>.concat(<group1>, <group2>, ...)
                            if (group === 1) {
                                write(".concat(");
                            }
                            else if (group > 1) {
                                write(", ");
                            }
                            var e = elements[pos];
                            if (e.kind === 173 /* SpreadElementExpression */) {
                                e = e.expression;
                                emitParenthesizedIf(e, group === 0 && needsParenthesisForPropertyAccessOrInvocation(e));
                                pos++;
                            }
                            else {
                                var i = pos;
                                while (i < length && elements[i].kind !== 173 /* SpreadElementExpression */) {
                                    i++;
                                }
                                write("[");
                                if (multiLine) {
                                    increaseIndent();
                                }
                                emitList(elements, pos, i - pos, multiLine, trailingComma && i === length);
                                if (multiLine) {
                                    decreaseIndent();
                                }
                                write("]");
                                pos = i;
                            }
                            group++;
                        }
                        if (group > 1) {
                            write(")");
                        }
                    }
                    function isSpreadElementExpression(node) {
                        return node.kind === 173 /* SpreadElementExpression */;
                    }
                    function emitArrayLiteral(node) {
                        var elements = node.elements;
                        if (elements.length === 0) {
                            write("[]");
                        }
                        else if (languageVersion >= 2 /* ES6 */ || !ts.forEach(elements, isSpreadElementExpression)) {
                            write("[");
                            emitLinePreservingList(node, node.elements, elements.hasTrailingComma, false);
                            write("]");
                        }
                        else {
                            emitListWithSpread(elements, (node.flags & 512 /* MultiLine */) !== 0, 
                            /*trailingComma*/ elements.hasTrailingComma);
                        }
                    }
                    function emitObjectLiteralBody(node, numElements) {
                        if (numElements === 0) {
                            write("{}");
                            return;
                        }
                        write("{");
                        if (numElements > 0) {
                            var properties = node.properties;
                            // If we are not doing a downlevel transformation for object literals,
                            // then try to preserve the original shape of the object literal.
                            // Otherwise just try to preserve the formatting.
                            if (numElements === properties.length) {
                                emitLinePreservingList(node, properties, languageVersion >= 1 /* ES5 */, true);
                            }
                            else {
                                var multiLine = (node.flags & 512 /* MultiLine */) !== 0;
                                if (!multiLine) {
                                    write(" ");
                                }
                                else {
                                    increaseIndent();
                                }
                                emitList(properties, 0, numElements, multiLine, false);
                                if (!multiLine) {
                                    write(" ");
                                }
                                else {
                                    decreaseIndent();
                                }
                            }
                        }
                        write("}");
                    }
                    function emitDownlevelObjectLiteralWithComputedProperties(node, firstComputedPropertyIndex) {
                        var multiLine = (node.flags & 512 /* MultiLine */) !== 0;
                        var properties = node.properties;
                        write("(");
                        if (multiLine) {
                            increaseIndent();
                        }
                        // For computed properties, we need to create a unique handle to the object
                        // literal so we can modify it without risking internal assignments tainting the object.
                        var tempVar = createAndRecordTempVariable(0 /* Auto */);
                        // Write out the first non-computed properties
                        // (or all properties if none of them are computed),
                        // then emit the rest through indexing on the temp variable.
                        emit(tempVar);
                        write(" = ");
                        emitObjectLiteralBody(node, firstComputedPropertyIndex);
                        for (var i = firstComputedPropertyIndex, n = properties.length; i < n; i++) {
                            writeComma();
                            var property = properties[i];
                            emitStart(property);
                            if (property.kind === 136 /* GetAccessor */ || property.kind === 137 /* SetAccessor */) {
                                // TODO (drosen): Reconcile with 'emitMemberFunctions'.
                                var accessors = ts.getAllAccessorDeclarations(node.properties, property);
                                if (property !== accessors.firstAccessor) {
                                    continue;
                                }
                                write("Object.defineProperty(");
                                emit(tempVar);
                                write(", ");
                                emitStart(node.name);
                                emitExpressionForPropertyName(property.name);
                                emitEnd(property.name);
                                write(", {");
                                increaseIndent();
                                if (accessors.getAccessor) {
                                    writeLine();
                                    emitLeadingComments(accessors.getAccessor);
                                    write("get: ");
                                    emitStart(accessors.getAccessor);
                                    write("function ");
                                    emitSignatureAndBody(accessors.getAccessor);
                                    emitEnd(accessors.getAccessor);
                                    emitTrailingComments(accessors.getAccessor);
                                    write(",");
                                }
                                if (accessors.setAccessor) {
                                    writeLine();
                                    emitLeadingComments(accessors.setAccessor);
                                    write("set: ");
                                    emitStart(accessors.setAccessor);
                                    write("function ");
                                    emitSignatureAndBody(accessors.setAccessor);
                                    emitEnd(accessors.setAccessor);
                                    emitTrailingComments(accessors.setAccessor);
                                    write(",");
                                }
                                writeLine();
                                write("enumerable: true,");
                                writeLine();
                                write("configurable: true");
                                decreaseIndent();
                                writeLine();
                                write("})");
                                emitEnd(property);
                            }
                            else {
                                emitLeadingComments(property);
                                emitStart(property.name);
                                emit(tempVar);
                                emitMemberAccessForPropertyName(property.name);
                                emitEnd(property.name);
                                write(" = ");
                                if (property.kind === 224 /* PropertyAssignment */) {
                                    emit(property.initializer);
                                }
                                else if (property.kind === 225 /* ShorthandPropertyAssignment */) {
                                    emitExpressionIdentifier(property.name);
                                }
                                else if (property.kind === 134 /* MethodDeclaration */) {
                                    emitFunctionDeclaration(property);
                                }
                                else {
                                    ts.Debug.fail("ObjectLiteralElement type not accounted for: " + property.kind);
                                }
                            }
                            emitEnd(property);
                        }
                        writeComma();
                        emit(tempVar);
                        if (multiLine) {
                            decreaseIndent();
                            writeLine();
                        }
                        write(")");
                        function writeComma() {
                            if (multiLine) {
                                write(",");
                                writeLine();
                            }
                            else {
                                write(", ");
                            }
                        }
                    }
                    function emitObjectLiteral(node) {
                        var properties = node.properties;
                        if (languageVersion < 2 /* ES6 */) {
                            var numProperties = properties.length;
                            // Find the first computed property.
                            // Everything until that point can be emitted as part of the initial object literal.
                            var numInitialNonComputedProperties = numProperties;
                            for (var i = 0, n = properties.length; i < n; i++) {
                                if (properties[i].name.kind === 127 /* ComputedPropertyName */) {
                                    numInitialNonComputedProperties = i;
                                    break;
                                }
                            }
                            var hasComputedProperty = numInitialNonComputedProperties !== properties.length;
                            if (hasComputedProperty) {
                                emitDownlevelObjectLiteralWithComputedProperties(node, numInitialNonComputedProperties);
                                return;
                            }
                        }
                        // Ordinary case: either the object has no computed properties
                        // or we're compiling with an ES6+ target.
                        emitObjectLiteralBody(node, properties.length);
                    }
                    function createBinaryExpression(left, operator, right, startsOnNewLine) {
                        var result = ts.createSynthesizedNode(169 /* BinaryExpression */, startsOnNewLine);
                        result.operatorToken = ts.createSynthesizedNode(operator);
                        result.left = left;
                        result.right = right;
                        return result;
                    }
                    function createPropertyAccessExpression(expression, name) {
                        var result = ts.createSynthesizedNode(155 /* PropertyAccessExpression */);
                        result.expression = parenthesizeForAccess(expression);
                        result.dotToken = ts.createSynthesizedNode(20 /* DotToken */);
                        result.name = name;
                        return result;
                    }
                    function createElementAccessExpression(expression, argumentExpression) {
                        var result = ts.createSynthesizedNode(156 /* ElementAccessExpression */);
                        result.expression = parenthesizeForAccess(expression);
                        result.argumentExpression = argumentExpression;
                        return result;
                    }
                    function parenthesizeForAccess(expr) {
                        // isLeftHandSideExpression is almost the correct criterion for when it is not necessary
                        // to parenthesize the expression before a dot. The known exceptions are:
                        //
                        //    NewExpression:
                        //       new C.x        -> not the same as (new C).x
                        //    NumberLiteral
                        //       1.x            -> not the same as (1).x
                        //
                        if (ts.isLeftHandSideExpression(expr) && expr.kind !== 158 /* NewExpression */ && expr.kind !== 7 /* NumericLiteral */) {
                            return expr;
                        }
                        var node = ts.createSynthesizedNode(161 /* ParenthesizedExpression */);
                        node.expression = expr;
                        return node;
                    }
                    function emitComputedPropertyName(node) {
                        write("[");
                        emitExpressionForPropertyName(node);
                        write("]");
                    }
                    function emitMethod(node) {
                        if (languageVersion >= 2 /* ES6 */ && node.asteriskToken) {
                            write("*");
                        }
                        emit(node.name, false);
                        if (languageVersion < 2 /* ES6 */) {
                            write(": function ");
                        }
                        emitSignatureAndBody(node);
                    }
                    function emitPropertyAssignment(node) {
                        emit(node.name, false);
                        write(": ");
                        emit(node.initializer);
                    }
                    function emitShorthandPropertyAssignment(node) {
                        emit(node.name, false);
                        // If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment. For example:
                        //  module m {
                        //      export let y;
                        //  }
                        //  module m {
                        //      export let obj = { y };
                        //  }
                        //  The short-hand property in obj need to emit as such ... = { y : m.y } regardless of the TargetScript version
                        if (languageVersion < 2 /* ES6 */) {
                            // Emit identifier as an identifier
                            write(": ");
                            var generatedName = getGeneratedNameForIdentifier(node.name);
                            if (generatedName) {
                                write(generatedName);
                            }
                            else {
                                // Even though this is stored as identifier treat it as an expression
                                // Short-hand, { x }, is equivalent of normal form { x: x }
                                emitExpressionIdentifier(node.name);
                            }
                        }
                        else if (resolver.getExpressionNameSubstitution(node.name, getGeneratedNameForNode)) {
                            // Emit identifier as an identifier
                            write(": ");
                            // Even though this is stored as identifier treat it as an expression
                            // Short-hand, { x }, is equivalent of normal form { x: x }
                            emitExpressionIdentifier(node.name);
                        }
                    }
                    function tryEmitConstantValue(node) {
                        if (compilerOptions.separateCompilation) {
                            // do not inline enum values in separate compilation mode
                            return false;
                        }
                        var constantValue = resolver.getConstantValue(node);
                        if (constantValue !== undefined) {
                            write(constantValue.toString());
                            if (!compilerOptions.removeComments) {
                                var propertyName = node.kind === 155 /* PropertyAccessExpression */ ? ts.declarationNameToString(node.name) : ts.getTextOfNode(node.argumentExpression);
                                write(" /* " + propertyName + " */");
                            }
                            return true;
                        }
                        return false;
                    }
                    // Returns 'true' if the code was actually indented, false otherwise. 
                    // If the code is not indented, an optional valueToWriteWhenNotIndenting will be 
                    // emitted instead.
                    function indentIfOnDifferentLines(parent, node1, node2, valueToWriteWhenNotIndenting) {
                        var realNodesAreOnDifferentLines = !ts.nodeIsSynthesized(parent) && !nodeEndIsOnSameLineAsNodeStart(node1, node2);
                        // Always use a newline for synthesized code if the synthesizer desires it.
                        var synthesizedNodeIsOnDifferentLine = synthesizedNodeStartsOnNewLine(node2);
                        if (realNodesAreOnDifferentLines || synthesizedNodeIsOnDifferentLine) {
                            increaseIndent();
                            writeLine();
                            return true;
                        }
                        else {
                            if (valueToWriteWhenNotIndenting) {
                                write(valueToWriteWhenNotIndenting);
                            }
                            return false;
                        }
                    }
                    function emitPropertyAccess(node) {
                        if (tryEmitConstantValue(node)) {
                            return;
                        }
                        emit(node.expression);
                        var indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken);
                        write(".");
                        var indentedAfterDot = indentIfOnDifferentLines(node, node.dotToken, node.name);
                        emit(node.name, false);
                        decreaseIndentIf(indentedBeforeDot, indentedAfterDot);
                    }
                    function emitQualifiedName(node) {
                        emit(node.left);
                        write(".");
                        emit(node.right);
                    }
                    function emitIndexedAccess(node) {
                        if (tryEmitConstantValue(node)) {
                            return;
                        }
                        emit(node.expression);
                        write("[");
                        emit(node.argumentExpression);
                        write("]");
                    }
                    function hasSpreadElement(elements) {
                        return ts.forEach(elements, function (e) { return e.kind === 173 /* SpreadElementExpression */; });
                    }
                    function skipParentheses(node) {
                        while (node.kind === 161 /* ParenthesizedExpression */ || node.kind === 160 /* TypeAssertionExpression */) {
                            node = node.expression;
                        }
                        return node;
                    }
                    function emitCallTarget(node) {
                        if (node.kind === 65 /* Identifier */ || node.kind === 93 /* ThisKeyword */ || node.kind === 91 /* SuperKeyword */) {
                            emit(node);
                            return node;
                        }
                        var temp = createAndRecordTempVariable(0 /* Auto */);
                        write("(");
                        emit(temp);
                        write(" = ");
                        emit(node);
                        write(")");
                        return temp;
                    }
                    function emitCallWithSpread(node) {
                        var target;
                        var expr = skipParentheses(node.expression);
                        if (expr.kind === 155 /* PropertyAccessExpression */) {
                            // Target will be emitted as "this" argument
                            target = emitCallTarget(expr.expression);
                            write(".");
                            emit(expr.name);
                        }
                        else if (expr.kind === 156 /* ElementAccessExpression */) {
                            // Target will be emitted as "this" argument
                            target = emitCallTarget(expr.expression);
                            write("[");
                            emit(expr.argumentExpression);
                            write("]");
                        }
                        else if (expr.kind === 91 /* SuperKeyword */) {
                            target = expr;
                            write("_super");
                        }
                        else {
                            emit(node.expression);
                        }
                        write(".apply(");
                        if (target) {
                            if (target.kind === 91 /* SuperKeyword */) {
                                // Calls of form super(...) and super.foo(...)
                                emitThis(target);
                            }
                            else {
                                // Calls of form obj.foo(...)
                                emit(target);
                            }
                        }
                        else {
                            // Calls of form foo(...)
                            write("void 0");
                        }
                        write(", ");
                        emitListWithSpread(node.arguments, false, false);
                        write(")");
                    }
                    function emitCallExpression(node) {
                        if (languageVersion < 2 /* ES6 */ && hasSpreadElement(node.arguments)) {
                            emitCallWithSpread(node);
                            return;
                        }
                        var superCall = false;
                        if (node.expression.kind === 91 /* SuperKeyword */) {
                            emitSuper(node.expression);
                            superCall = true;
                        }
                        else {
                            emit(node.expression);
                            superCall = node.expression.kind === 155 /* PropertyAccessExpression */ && node.expression.expression.kind === 91 /* SuperKeyword */;
                        }
                        if (superCall && languageVersion < 2 /* ES6 */) {
                            write(".call(");
                            emitThis(node.expression);
                            if (node.arguments.length) {
                                write(", ");
                                emitCommaList(node.arguments);
                            }
                            write(")");
                        }
                        else {
                            write("(");
                            emitCommaList(node.arguments);
                            write(")");
                        }
                    }
                    function emitNewExpression(node) {
                        write("new ");
                        emit(node.expression);
                        if (node.arguments) {
                            write("(");
                            emitCommaList(node.arguments);
                            write(")");
                        }
                    }
                    function emitTaggedTemplateExpression(node) {
                        if (languageVersion >= 2 /* ES6 */) {
                            emit(node.tag);
                            write(" ");
                            emit(node.template);
                        }
                        else {
                            emitDownlevelTaggedTemplate(node);
                        }
                    }
                    function emitParenExpression(node) {
                        if (!node.parent || node.parent.kind !== 163 /* ArrowFunction */) {
                            if (node.expression.kind === 160 /* TypeAssertionExpression */) {
                                var operand = node.expression.expression;
                                // Make sure we consider all nested cast expressions, e.g.:
                                // (<any><number><any>-A).x;
                                while (operand.kind == 160 /* TypeAssertionExpression */) {
                                    operand = operand.expression;
                                }
                                // We have an expression of the form: (<Type>SubExpr)
                                // Emitting this as (SubExpr) is really not desirable. We would like to emit the subexpr as is.
                                // Omitting the parentheses, however, could cause change in the semantics of the generated
                                // code if the casted expression has a lower precedence than the rest of the expression, e.g.:
                                //      (<any>new A).foo should be emitted as (new A).foo and not new A.foo
                                //      (<any>typeof A).toString() should be emitted as (typeof A).toString() and not typeof A.toString()
                                //      new (<any>A()) should be emitted as new (A()) and not new A()
                                //      (<any>function foo() { })() should be emitted as an IIF (function foo(){})() and not declaration function foo(){} ()
                                if (operand.kind !== 167 /* PrefixUnaryExpression */ &&
                                    operand.kind !== 166 /* VoidExpression */ &&
                                    operand.kind !== 165 /* TypeOfExpression */ &&
                                    operand.kind !== 164 /* DeleteExpression */ &&
                                    operand.kind !== 168 /* PostfixUnaryExpression */ &&
                                    operand.kind !== 158 /* NewExpression */ &&
                                    !(operand.kind === 157 /* CallExpression */ && node.parent.kind === 158 /* NewExpression */) &&
                                    !(operand.kind === 162 /* FunctionExpression */ && node.parent.kind === 157 /* CallExpression */)) {
                                    emit(operand);
                                    return;
                                }
                            }
                        }
                        write("(");
                        emit(node.expression);
                        write(")");
                    }
                    function emitDeleteExpression(node) {
                        write(ts.tokenToString(74 /* DeleteKeyword */));
                        write(" ");
                        emit(node.expression);
                    }
                    function emitVoidExpression(node) {
                        write(ts.tokenToString(99 /* VoidKeyword */));
                        write(" ");
                        emit(node.expression);
                    }
                    function emitTypeOfExpression(node) {
                        write(ts.tokenToString(97 /* TypeOfKeyword */));
                        write(" ");
                        emit(node.expression);
                    }
                    function emitPrefixUnaryExpression(node) {
                        write(ts.tokenToString(node.operator));
                        // In some cases, we need to emit a space between the operator and the operand. One obvious case
                        // is when the operator is an identifier, like delete or typeof. We also need to do this for plus
                        // and minus expressions in certain cases. Specifically, consider the following two cases (parens
                        // are just for clarity of exposition, and not part of the source code):
                        //
                        //  (+(+1))
                        //  (+(++1))
                        //
                        // We need to emit a space in both cases. In the first case, the absence of a space will make
                        // the resulting expression a prefix increment operation. And in the second, it will make the resulting
                        // expression a prefix increment whose operand is a plus expression - (++(+x))
                        // The same is true of minus of course.
                        if (node.operand.kind === 167 /* PrefixUnaryExpression */) {
                            var operand = node.operand;
                            if (node.operator === 33 /* PlusToken */ && (operand.operator === 33 /* PlusToken */ || operand.operator === 38 /* PlusPlusToken */)) {
                                write(" ");
                            }
                            else if (node.operator === 34 /* MinusToken */ && (operand.operator === 34 /* MinusToken */ || operand.operator === 39 /* MinusMinusToken */)) {
                                write(" ");
                            }
                        }
                        emit(node.operand);
                    }
                    function emitPostfixUnaryExpression(node) {
                        emit(node.operand);
                        write(ts.tokenToString(node.operator));
                    }
                    function emitBinaryExpression(node) {
                        if (languageVersion < 2 /* ES6 */ && node.operatorToken.kind === 53 /* EqualsToken */ &&
                            (node.left.kind === 154 /* ObjectLiteralExpression */ || node.left.kind === 153 /* ArrayLiteralExpression */)) {
                            emitDestructuring(node, node.parent.kind === 182 /* ExpressionStatement */);
                        }
                        else {
                            emit(node.left);
                            var indentedBeforeOperator = indentIfOnDifferentLines(node, node.left, node.operatorToken, node.operatorToken.kind !== 23 /* CommaToken */ ? " " : undefined);
                            write(ts.tokenToString(node.operatorToken.kind));
                            var indentedAfterOperator = indentIfOnDifferentLines(node, node.operatorToken, node.right, " ");
                            emit(node.right);
                            decreaseIndentIf(indentedBeforeOperator, indentedAfterOperator);
                        }
                    }
                    function synthesizedNodeStartsOnNewLine(node) {
                        return ts.nodeIsSynthesized(node) && node.startsOnNewLine;
                    }
                    function emitConditionalExpression(node) {
                        emit(node.condition);
                        var indentedBeforeQuestion = indentIfOnDifferentLines(node, node.condition, node.questionToken, " ");
                        write("?");
                        var indentedAfterQuestion = indentIfOnDifferentLines(node, node.questionToken, node.whenTrue, " ");
                        emit(node.whenTrue);
                        decreaseIndentIf(indentedBeforeQuestion, indentedAfterQuestion);
                        var indentedBeforeColon = indentIfOnDifferentLines(node, node.whenTrue, node.colonToken, " ");
                        write(":");
                        var indentedAfterColon = indentIfOnDifferentLines(node, node.colonToken, node.whenFalse, " ");
                        emit(node.whenFalse);
                        decreaseIndentIf(indentedBeforeColon, indentedAfterColon);
                    }
                    // Helper function to decrease the indent if we previously indented.  Allows multiple 
                    // previous indent values to be considered at a time.  This also allows caller to just
                    // call this once, passing in all their appropriate indent values, instead of needing
                    // to call this helper function multiple times.
                    function decreaseIndentIf(value1, value2) {
                        if (value1) {
                            decreaseIndent();
                        }
                        if (value2) {
                            decreaseIndent();
                        }
                    }
                    function isSingleLineEmptyBlock(node) {
                        if (node && node.kind === 179 /* Block */) {
                            var block = node;
                            return block.statements.length === 0 && nodeEndIsOnSameLineAsNodeStart(block, block);
                        }
                    }
                    function emitBlock(node) {
                        if (isSingleLineEmptyBlock(node)) {
                            emitToken(14 /* OpenBraceToken */, node.pos);
                            write(" ");
                            emitToken(15 /* CloseBraceToken */, node.statements.end);
                            return;
                        }
                        emitToken(14 /* OpenBraceToken */, node.pos);
                        increaseIndent();
                        scopeEmitStart(node.parent);
                        if (node.kind === 206 /* ModuleBlock */) {
                            ts.Debug.assert(node.parent.kind === 205 /* ModuleDeclaration */);
                            emitCaptureThisForNodeIfNecessary(node.parent);
                        }
                        emitLines(node.statements);
                        if (node.kind === 206 /* ModuleBlock */) {
                            emitTempDeclarations(true);
                        }
                        decreaseIndent();
                        writeLine();
                        emitToken(15 /* CloseBraceToken */, node.statements.end);
                        scopeEmitEnd();
                    }
                    function emitEmbeddedStatement(node) {
                        if (node.kind === 179 /* Block */) {
                            write(" ");
                            emit(node);
                        }
                        else {
                            increaseIndent();
                            writeLine();
                            emit(node);
                            decreaseIndent();
                        }
                    }
                    function emitExpressionStatement(node) {
                        emitParenthesizedIf(node.expression, node.expression.kind === 163 /* ArrowFunction */);
                        write(";");
                    }
                    function emitIfStatement(node) {
                        var endPos = emitToken(84 /* IfKeyword */, node.pos);
                        write(" ");
                        endPos = emitToken(16 /* OpenParenToken */, endPos);
                        emit(node.expression);
                        emitToken(17 /* CloseParenToken */, node.expression.end);
                        emitEmbeddedStatement(node.thenStatement);
                        if (node.elseStatement) {
                            writeLine();
                            emitToken(76 /* ElseKeyword */, node.thenStatement.end);
                            if (node.elseStatement.kind === 183 /* IfStatement */) {
                                write(" ");
                                emit(node.elseStatement);
                            }
                            else {
                                emitEmbeddedStatement(node.elseStatement);
                            }
                        }
                    }
                    function emitDoStatement(node) {
                        write("do");
                        emitEmbeddedStatement(node.statement);
                        if (node.statement.kind === 179 /* Block */) {
                            write(" ");
                        }
                        else {
                            writeLine();
                        }
                        write("while (");
                        emit(node.expression);
                        write(");");
                    }
                    function emitWhileStatement(node) {
                        write("while (");
                        emit(node.expression);
                        write(")");
                        emitEmbeddedStatement(node.statement);
                    }
                    function emitStartOfVariableDeclarationList(decl, startPos) {
                        var tokenKind = 98 /* VarKeyword */;
                        if (decl && languageVersion >= 2 /* ES6 */) {
                            if (ts.isLet(decl)) {
                                tokenKind = 104 /* LetKeyword */;
                            }
                            else if (ts.isConst(decl)) {
                                tokenKind = 70 /* ConstKeyword */;
                            }
                        }
                        if (startPos !== undefined) {
                            emitToken(tokenKind, startPos);
                        }
                        else {
                            switch (tokenKind) {
                                case 98 /* VarKeyword */:
                                    return write("var ");
                                case 104 /* LetKeyword */:
                                    return write("let ");
                                case 70 /* ConstKeyword */:
                                    return write("const ");
                            }
                        }
                    }
                    function emitForStatement(node) {
                        var endPos = emitToken(82 /* ForKeyword */, node.pos);
                        write(" ");
                        endPos = emitToken(16 /* OpenParenToken */, endPos);
                        if (node.initializer && node.initializer.kind === 199 /* VariableDeclarationList */) {
                            var variableDeclarationList = node.initializer;
                            var declarations = variableDeclarationList.declarations;
                            emitStartOfVariableDeclarationList(declarations[0], endPos);
                            write(" ");
                            emitCommaList(declarations);
                        }
                        else if (node.initializer) {
                            emit(node.initializer);
                        }
                        write(";");
                        emitOptional(" ", node.condition);
                        write(";");
                        emitOptional(" ", node.incrementor);
                        write(")");
                        emitEmbeddedStatement(node.statement);
                    }
                    function emitForInOrForOfStatement(node) {
                        if (languageVersion < 2 /* ES6 */ && node.kind === 188 /* ForOfStatement */) {
                            return emitDownLevelForOfStatement(node);
                        }
                        var endPos = emitToken(82 /* ForKeyword */, node.pos);
                        write(" ");
                        endPos = emitToken(16 /* OpenParenToken */, endPos);
                        if (node.initializer.kind === 199 /* VariableDeclarationList */) {
                            var variableDeclarationList = node.initializer;
                            if (variableDeclarationList.declarations.length >= 1) {
                                var decl = variableDeclarationList.declarations[0];
                                emitStartOfVariableDeclarationList(decl, endPos);
                                write(" ");
                                emit(decl);
                            }
                        }
                        else {
                            emit(node.initializer);
                        }
                        if (node.kind === 187 /* ForInStatement */) {
                            write(" in ");
                        }
                        else {
                            write(" of ");
                        }
                        emit(node.expression);
                        emitToken(17 /* CloseParenToken */, node.expression.end);
                        emitEmbeddedStatement(node.statement);
                    }
                    function emitDownLevelForOfStatement(node) {
                        // The following ES6 code:
                        //
                        //    for (let v of expr) { }
                        //
                        // should be emitted as
                        //
                        //    for (let _i = 0, _a = expr; _i < _a.length; _i++) {
                        //        let v = _a[_i];
                        //    }
                        //
                        // where _a and _i are temps emitted to capture the RHS and the counter,
                        // respectively.
                        // When the left hand side is an expression instead of a let declaration,
                        // the "let v" is not emitted.
                        // When the left hand side is a let/const, the v is renamed if there is
                        // another v in scope.
                        // Note that all assignments to the LHS are emitted in the body, including
                        // all destructuring.
                        // Note also that because an extra statement is needed to assign to the LHS,
                        // for-of bodies are always emitted as blocks.
                        var endPos = emitToken(82 /* ForKeyword */, node.pos);
                        write(" ");
                        endPos = emitToken(16 /* OpenParenToken */, endPos);
                        // Do not emit the LHS let declaration yet, because it might contain destructuring.
                        // Do not call recordTempDeclaration because we are declaring the temps
                        // right here. Recording means they will be declared later.
                        // In the case where the user wrote an identifier as the RHS, like this:
                        //
                        //     for (let v of arr) { }
                        //
                        // we don't want to emit a temporary variable for the RHS, just use it directly.
                        var rhsIsIdentifier = node.expression.kind === 65 /* Identifier */;
                        var counter = createTempVariable(268435456 /* _i */);
                        var rhsReference = rhsIsIdentifier ? node.expression : createTempVariable(0 /* Auto */);
                        // This is the let keyword for the counter and rhsReference. The let keyword for
                        // the LHS will be emitted inside the body.
                        emitStart(node.expression);
                        write("var ");
                        // _i = 0
                        emitNodeWithoutSourceMap(counter);
                        write(" = 0");
                        emitEnd(node.expression);
                        if (!rhsIsIdentifier) {
                            // , _a = expr
                            write(", ");
                            emitStart(node.expression);
                            emitNodeWithoutSourceMap(rhsReference);
                            write(" = ");
                            emitNodeWithoutSourceMap(node.expression);
                            emitEnd(node.expression);
                        }
                        write("; ");
                        // _i < _a.length;
                        emitStart(node.initializer);
                        emitNodeWithoutSourceMap(counter);
                        write(" < ");
                        emitNodeWithoutSourceMap(rhsReference);
                        write(".length");
                        emitEnd(node.initializer);
                        write("; ");
                        // _i++)
                        emitStart(node.initializer);
                        emitNodeWithoutSourceMap(counter);
                        write("++");
                        emitEnd(node.initializer);
                        emitToken(17 /* CloseParenToken */, node.expression.end);
                        // Body
                        write(" {");
                        writeLine();
                        increaseIndent();
                        // Initialize LHS
                        // let v = _a[_i];
                        var rhsIterationValue = createElementAccessExpression(rhsReference, counter);
                        emitStart(node.initializer);
                        if (node.initializer.kind === 199 /* VariableDeclarationList */) {
                            write("var ");
                            var variableDeclarationList = node.initializer;
                            if (variableDeclarationList.declarations.length > 0) {
                                var declaration = variableDeclarationList.declarations[0];
                                if (ts.isBindingPattern(declaration.name)) {
                                    // This works whether the declaration is a var, let, or const.
                                    // It will use rhsIterationValue _a[_i] as the initializer.
                                    emitDestructuring(declaration, false, rhsIterationValue);
                                }
                                else {
                                    // The following call does not include the initializer, so we have
                                    // to emit it separately.
                                    emitNodeWithoutSourceMap(declaration);
                                    write(" = ");
                                    emitNodeWithoutSourceMap(rhsIterationValue);
                                }
                            }
                            else {
                                // It's an empty declaration list. This can only happen in an error case, if the user wrote
                                //     for (let of []) {}
                                emitNodeWithoutSourceMap(createTempVariable(0 /* Auto */));
                                write(" = ");
                                emitNodeWithoutSourceMap(rhsIterationValue);
                            }
                        }
                        else {
                            // Initializer is an expression. Emit the expression in the body, so that it's
                            // evaluated on every iteration.
                            var assignmentExpression = createBinaryExpression(node.initializer, 53 /* EqualsToken */, rhsIterationValue, false);
                            if (node.initializer.kind === 153 /* ArrayLiteralExpression */ || node.initializer.kind === 154 /* ObjectLiteralExpression */) {
                                // This is a destructuring pattern, so call emitDestructuring instead of emit. Calling emit will not work, because it will cause
                                // the BinaryExpression to be passed in instead of the expression statement, which will cause emitDestructuring to crash.
                                emitDestructuring(assignmentExpression, true, undefined);
                            }
                            else {
                                emitNodeWithoutSourceMap(assignmentExpression);
                            }
                        }
                        emitEnd(node.initializer);
                        write(";");
                        if (node.statement.kind === 179 /* Block */) {
                            emitLines(node.statement.statements);
                        }
                        else {
                            writeLine();
                            emit(node.statement);
                        }
                        writeLine();
                        decreaseIndent();
                        write("}");
                    }
                    function emitBreakOrContinueStatement(node) {
                        emitToken(node.kind === 190 /* BreakStatement */ ? 66 /* BreakKeyword */ : 71 /* ContinueKeyword */, node.pos);
                        emitOptional(" ", node.label);
                        write(";");
                    }
                    function emitReturnStatement(node) {
                        emitToken(90 /* ReturnKeyword */, node.pos);
                        emitOptional(" ", node.expression);
                        write(";");
                    }
                    function emitWithStatement(node) {
                        write("with (");
                        emit(node.expression);
                        write(")");
                        emitEmbeddedStatement(node.statement);
                    }
                    function emitSwitchStatement(node) {
                        var endPos = emitToken(92 /* SwitchKeyword */, node.pos);
                        write(" ");
                        emitToken(16 /* OpenParenToken */, endPos);
                        emit(node.expression);
                        endPos = emitToken(17 /* CloseParenToken */, node.expression.end);
                        write(" ");
                        emitCaseBlock(node.caseBlock, endPos);
                    }
                    function emitCaseBlock(node, startPos) {
                        emitToken(14 /* OpenBraceToken */, startPos);
                        increaseIndent();
                        emitLines(node.clauses);
                        decreaseIndent();
                        writeLine();
                        emitToken(15 /* CloseBraceToken */, node.clauses.end);
                    }
                    function nodeStartPositionsAreOnSameLine(node1, node2) {
                        return ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node1.pos)) ===
                            ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos));
                    }
                    function nodeEndPositionsAreOnSameLine(node1, node2) {
                        return ts.getLineOfLocalPosition(currentSourceFile, node1.end) ===
                            ts.getLineOfLocalPosition(currentSourceFile, node2.end);
                    }
                    function nodeEndIsOnSameLineAsNodeStart(node1, node2) {
                        return ts.getLineOfLocalPosition(currentSourceFile, node1.end) ===
                            ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos));
                    }
                    function emitCaseOrDefaultClause(node) {
                        if (node.kind === 220 /* CaseClause */) {
                            write("case ");
                            emit(node.expression);
                            write(":");
                        }
                        else {
                            write("default:");
                        }
                        if (node.statements.length === 1 && nodeStartPositionsAreOnSameLine(node, node.statements[0])) {
                            write(" ");
                            emit(node.statements[0]);
                        }
                        else {
                            increaseIndent();
                            emitLines(node.statements);
                            decreaseIndent();
                        }
                    }
                    function emitThrowStatement(node) {
                        write("throw ");
                        emit(node.expression);
                        write(";");
                    }
                    function emitTryStatement(node) {
                        write("try ");
                        emit(node.tryBlock);
                        emit(node.catchClause);
                        if (node.finallyBlock) {
                            writeLine();
                            write("finally ");
                            emit(node.finallyBlock);
                        }
                    }
                    function emitCatchClause(node) {
                        writeLine();
                        var endPos = emitToken(68 /* CatchKeyword */, node.pos);
                        write(" ");
                        emitToken(16 /* OpenParenToken */, endPos);
                        emit(node.variableDeclaration);
                        emitToken(17 /* CloseParenToken */, node.variableDeclaration ? node.variableDeclaration.end : endPos);
                        write(" ");
                        emitBlock(node.block);
                    }
                    function emitDebuggerStatement(node) {
                        emitToken(72 /* DebuggerKeyword */, node.pos);
                        write(";");
                    }
                    function emitLabelledStatement(node) {
                        emit(node.label);
                        write(": ");
                        emit(node.statement);
                    }
                    function getContainingModule(node) {
                        do {
                            node = node.parent;
                        } while (node && node.kind !== 205 /* ModuleDeclaration */);
                        return node;
                    }
                    function emitContainingModuleName(node) {
                        var container = getContainingModule(node);
                        write(container ? getGeneratedNameForNode(container) : "exports");
                    }
                    function emitModuleMemberName(node) {
                        emitStart(node.name);
                        if (ts.getCombinedNodeFlags(node) & 1 /* Export */) {
                            var container = getContainingModule(node);
                            if (container) {
                                write(getGeneratedNameForNode(container));
                                write(".");
                            }
                            else if (languageVersion < 2 /* ES6 */) {
                                write("exports.");
                            }
                        }
                        emitNodeWithoutSourceMap(node.name);
                        emitEnd(node.name);
                    }
                    function createVoidZero() {
                        var zero = ts.createSynthesizedNode(7 /* NumericLiteral */);
                        zero.text = "0";
                        var result = ts.createSynthesizedNode(166 /* VoidExpression */);
                        result.expression = zero;
                        return result;
                    }
                    function emitExportMemberAssignment(node) {
                        if (node.flags & 1 /* Export */) {
                            writeLine();
                            emitStart(node);
                            if (node.flags & 256 /* Default */) {
                                if (languageVersion === 0 /* ES3 */) {
                                    write("exports[\"default\"]");
                                }
                                else {
                                    write("exports.default");
                                }
                            }
                            else {
                                emitModuleMemberName(node);
                            }
                            write(" = ");
                            emitDeclarationName(node);
                            emitEnd(node);
                            write(";");
                        }
                    }
                    function emitExportMemberAssignments(name) {
                        if (!exportEquals && exportSpecifiers && ts.hasProperty(exportSpecifiers, name.text)) {
                            for (var _a = 0, _b = exportSpecifiers[name.text]; _a < _b.length; _a++) {
                                var specifier = _b[_a];
                                writeLine();
                                emitStart(specifier.name);
                                emitContainingModuleName(specifier);
                                write(".");
                                emitNodeWithoutSourceMap(specifier.name);
                                emitEnd(specifier.name);
                                write(" = ");
                                emitExpressionIdentifier(name);
                                write(";");
                            }
                        }
                    }
                    function emitDestructuring(root, isAssignmentExpressionStatement, value) {
                        var emitCount = 0;
                        // An exported declaration is actually emitted as an assignment (to a property on the module object), so
                        // temporary variables in an exported declaration need to have real declarations elsewhere
                        var isDeclaration = (root.kind === 198 /* VariableDeclaration */ && !(ts.getCombinedNodeFlags(root) & 1 /* Export */)) || root.kind === 129 /* Parameter */;
                        if (root.kind === 169 /* BinaryExpression */) {
                            emitAssignmentExpression(root);
                        }
                        else {
                            ts.Debug.assert(!isAssignmentExpressionStatement);
                            emitBindingElement(root, value);
                        }
                        function emitAssignment(name, value) {
                            if (emitCount++) {
                                write(", ");
                            }
                            renameNonTopLevelLetAndConst(name);
                            if (name.parent && (name.parent.kind === 198 /* VariableDeclaration */ || name.parent.kind === 152 /* BindingElement */)) {
                                emitModuleMemberName(name.parent);
                            }
                            else {
                                emit(name);
                            }
                            write(" = ");
                            emit(value);
                        }
                        function ensureIdentifier(expr) {
                            if (expr.kind !== 65 /* Identifier */) {
                                var identifier = createTempVariable(0 /* Auto */);
                                if (!isDeclaration) {
                                    recordTempDeclaration(identifier);
                                }
                                emitAssignment(identifier, expr);
                                expr = identifier;
                            }
                            return expr;
                        }
                        function createDefaultValueCheck(value, defaultValue) {
                            // The value expression will be evaluated twice, so for anything but a simple identifier
                            // we need to generate a temporary variable
                            value = ensureIdentifier(value);
                            // Return the expression 'value === void 0 ? defaultValue : value'
                            var equals = ts.createSynthesizedNode(169 /* BinaryExpression */);
                            equals.left = value;
                            equals.operatorToken = ts.createSynthesizedNode(30 /* EqualsEqualsEqualsToken */);
                            equals.right = createVoidZero();
                            return createConditionalExpression(equals, defaultValue, value);
                        }
                        function createConditionalExpression(condition, whenTrue, whenFalse) {
                            var cond = ts.createSynthesizedNode(170 /* ConditionalExpression */);
                            cond.condition = condition;
                            cond.questionToken = ts.createSynthesizedNode(50 /* QuestionToken */);
                            cond.whenTrue = whenTrue;
                            cond.colonToken = ts.createSynthesizedNode(51 /* ColonToken */);
                            cond.whenFalse = whenFalse;
                            return cond;
                        }
                        function createNumericLiteral(value) {
                            var node = ts.createSynthesizedNode(7 /* NumericLiteral */);
                            node.text = "" + value;
                            return node;
                        }
                        function createPropertyAccessForDestructuringProperty(object, propName) {
                            if (propName.kind !== 65 /* Identifier */) {
                                return createElementAccessExpression(object, propName);
                            }
                            return createPropertyAccessExpression(object, propName);
                        }
                        function createSliceCall(value, sliceIndex) {
                            var call = ts.createSynthesizedNode(157 /* CallExpression */);
                            var sliceIdentifier = ts.createSynthesizedNode(65 /* Identifier */);
                            sliceIdentifier.text = "slice";
                            call.expression = createPropertyAccessExpression(value, sliceIdentifier);
                            call.arguments = ts.createSynthesizedNodeArray();
                            call.arguments[0] = createNumericLiteral(sliceIndex);
                            return call;
                        }
                        function emitObjectLiteralAssignment(target, value) {
                            var properties = target.properties;
                            if (properties.length !== 1) {
                                // For anything but a single element destructuring we need to generate a temporary
                                // to ensure value is evaluated exactly once.
                                value = ensureIdentifier(value);
                            }
                            for (var _a = 0; _a < properties.length; _a++) {
                                var p = properties[_a];
                                if (p.kind === 224 /* PropertyAssignment */ || p.kind === 225 /* ShorthandPropertyAssignment */) {
                                    // TODO(andersh): Computed property support
                                    var propName = (p.name);
                                    emitDestructuringAssignment(p.initializer || propName, createPropertyAccessForDestructuringProperty(value, propName));
                                }
                            }
                        }
                        function emitArrayLiteralAssignment(target, value) {
                            var elements = target.elements;
                            if (elements.length !== 1) {
                                // For anything but a single element destructuring we need to generate a temporary
                                // to ensure value is evaluated exactly once.
                                value = ensureIdentifier(value);
                            }
                            for (var i = 0; i < elements.length; i++) {
                                var e = elements[i];
                                if (e.kind !== 175 /* OmittedExpression */) {
                                    if (e.kind !== 173 /* SpreadElementExpression */) {
                                        emitDestructuringAssignment(e, createElementAccessExpression(value, createNumericLiteral(i)));
                                    }
                                    else if (i === elements.length - 1) {
                                        emitDestructuringAssignment(e.expression, createSliceCall(value, i));
                                    }
                                }
                            }
                        }
                        function emitDestructuringAssignment(target, value) {
                            if (target.kind === 169 /* BinaryExpression */ && target.operatorToken.kind === 53 /* EqualsToken */) {
                                value = createDefaultValueCheck(value, target.right);
                                target = target.left;
                            }
                            if (target.kind === 154 /* ObjectLiteralExpression */) {
                                emitObjectLiteralAssignment(target, value);
                            }
                            else if (target.kind === 153 /* ArrayLiteralExpression */) {
                                emitArrayLiteralAssignment(target, value);
                            }
                            else {
                                emitAssignment(target, value);
                            }
                        }
                        function emitAssignmentExpression(root) {
                            var target = root.left;
                            var value = root.right;
                            if (isAssignmentExpressionStatement) {
                                emitDestructuringAssignment(target, value);
                            }
                            else {
                                if (root.parent.kind !== 161 /* ParenthesizedExpression */) {
                                    write("(");
                                }
                                value = ensureIdentifier(value);
                                emitDestructuringAssignment(target, value);
                                write(", ");
                                emit(value);
                                if (root.parent.kind !== 161 /* ParenthesizedExpression */) {
                                    write(")");
                                }
                            }
                        }
                        function emitBindingElement(target, value) {
                            if (target.initializer) {
                                // Combine value and initializer
                                value = value ? createDefaultValueCheck(value, target.initializer) : target.initializer;
                            }
                            else if (!value) {
                                // Use 'void 0' in absence of value and initializer
                                value = createVoidZero();
                            }
                            if (ts.isBindingPattern(target.name)) {
                                var pattern = target.name;
                                var elements = pattern.elements;
                                if (elements.length !== 1) {
                                    // For anything but a single element destructuring we need to generate a temporary
                                    // to ensure value is evaluated exactly once.
                                    value = ensureIdentifier(value);
                                }
                                for (var i = 0; i < elements.length; i++) {
                                    var element = elements[i];
                                    if (pattern.kind === 150 /* ObjectBindingPattern */) {
                                        // Rewrite element to a declaration with an initializer that fetches property
                                        var propName = element.propertyName || element.name;
                                        emitBindingElement(element, createPropertyAccessForDestructuringProperty(value, propName));
                                    }
                                    else if (element.kind !== 175 /* OmittedExpression */) {
                                        if (!element.dotDotDotToken) {
                                            // Rewrite element to a declaration that accesses array element at index i
                                            emitBindingElement(element, createElementAccessExpression(value, createNumericLiteral(i)));
                                        }
                                        else if (i === elements.length - 1) {
                                            emitBindingElement(element, createSliceCall(value, i));
                                        }
                                    }
                                }
                            }
                            else {
                                emitAssignment(target.name, value);
                            }
                        }
                    }
                    function emitVariableDeclaration(node) {
                        if (ts.isBindingPattern(node.name)) {
                            if (languageVersion < 2 /* ES6 */) {
                                emitDestructuring(node, false);
                            }
                            else {
                                emit(node.name);
                                emitOptional(" = ", node.initializer);
                            }
                        }
                        else {
                            renameNonTopLevelLetAndConst(node.name);
                            emitModuleMemberName(node);
                            var initializer = node.initializer;
                            if (!initializer && languageVersion < 2 /* ES6 */) {
                                // downlevel emit for non-initialized let bindings defined in loops
                                // for (...) {  let x; }
                                // should be
                                // for (...) { var <some-uniqie-name> = void 0; }
                                // this is necessary to preserve ES6 semantic in scenarios like
                                // for (...) { let x; console.log(x); x = 1 } // assignment on one iteration should not affect other iterations
                                var isUninitializedLet = (resolver.getNodeCheckFlags(node) & 256 /* BlockScopedBindingInLoop */) &&
                                    (getCombinedFlagsForIdentifier(node.name) & 4096 /* Let */);
                                // NOTE: default initialization should not be added to let bindings in for-in\for-of statements
                                if (isUninitializedLet &&
                                    node.parent.parent.kind !== 187 /* ForInStatement */ &&
                                    node.parent.parent.kind !== 188 /* ForOfStatement */) {
                                    initializer = createVoidZero();
                                }
                            }
                            emitOptional(" = ", initializer);
                        }
                    }
                    function emitExportVariableAssignments(node) {
                        if (node.kind === 175 /* OmittedExpression */) {
                            return;
                        }
                        var name = node.name;
                        if (name.kind === 65 /* Identifier */) {
                            emitExportMemberAssignments(name);
                        }
                        else if (ts.isBindingPattern(name)) {
                            ts.forEach(name.elements, emitExportVariableAssignments);
                        }
                    }
                    function getCombinedFlagsForIdentifier(node) {
                        if (!node.parent || (node.parent.kind !== 198 /* VariableDeclaration */ && node.parent.kind !== 152 /* BindingElement */)) {
                            return 0;
                        }
                        return ts.getCombinedNodeFlags(node.parent);
                    }
                    function renameNonTopLevelLetAndConst(node) {
                        // do not rename if
                        // - language version is ES6+
                        // - node is synthesized
                        // - node is not identifier (can happen when tree is malformed)
                        // - node is definitely not name of variable declaration. 
                        // it still can be part of parameter declaration, this check will be done next
                        if (languageVersion >= 2 /* ES6 */ ||
                            ts.nodeIsSynthesized(node) ||
                            node.kind !== 65 /* Identifier */ ||
                            (node.parent.kind !== 198 /* VariableDeclaration */ && node.parent.kind !== 152 /* BindingElement */)) {
                            return;
                        }
                        var combinedFlags = getCombinedFlagsForIdentifier(node);
                        if (((combinedFlags & 12288 /* BlockScoped */) === 0) || combinedFlags & 1 /* Export */) {
                            // do not rename exported or non-block scoped variables
                            return;
                        }
                        // here it is known that node is a block scoped variable
                        var list = ts.getAncestor(node, 199 /* VariableDeclarationList */);
                        if (list.parent.kind === 180 /* VariableStatement */) {
                            var isSourceFileLevelBinding = list.parent.parent.kind === 227 /* SourceFile */;
                            var isModuleLevelBinding = list.parent.parent.kind === 206 /* ModuleBlock */;
                            var isFunctionLevelBinding = list.parent.parent.kind === 179 /* Block */ && ts.isFunctionLike(list.parent.parent.parent);
                            if (isSourceFileLevelBinding || isModuleLevelBinding || isFunctionLevelBinding) {
                                return;
                            }
                        }
                        var blockScopeContainer = ts.getEnclosingBlockScopeContainer(node);
                        var parent = blockScopeContainer.kind === 227 /* SourceFile */
                            ? blockScopeContainer
                            : blockScopeContainer.parent;
                        if (resolver.resolvesToSomeValue(parent, node.text)) {
                            var variableId = resolver.getBlockScopedVariableId(node);
                            if (!blockScopedVariableToGeneratedName) {
                                blockScopedVariableToGeneratedName = [];
                            }
                            var generatedName = makeUniqueName(node.text);
                            blockScopedVariableToGeneratedName[variableId] = generatedName;
                        }
                    }
                    function isES6ExportedDeclaration(node) {
                        return !!(node.flags & 1 /* Export */) &&
                            languageVersion >= 2 /* ES6 */ &&
                            node.parent.kind === 227 /* SourceFile */;
                    }
                    function emitVariableStatement(node) {
                        if (!(node.flags & 1 /* Export */)) {
                            emitStartOfVariableDeclarationList(node.declarationList);
                        }
                        else if (isES6ExportedDeclaration(node)) {
                            // Exported ES6 module member
                            write("export ");
                            emitStartOfVariableDeclarationList(node.declarationList);
                        }
                        emitCommaList(node.declarationList.declarations);
                        write(";");
                        if (languageVersion < 2 /* ES6 */ && node.parent === currentSourceFile) {
                            ts.forEach(node.declarationList.declarations, emitExportVariableAssignments);
                        }
                    }
                    function emitParameter(node) {
                        if (languageVersion < 2 /* ES6 */) {
                            if (ts.isBindingPattern(node.name)) {
                                var name_19 = createTempVariable(0 /* Auto */);
                                if (!tempParameters) {
                                    tempParameters = [];
                                }
                                tempParameters.push(name_19);
                                emit(name_19);
                            }
                            else {
                                emit(node.name);
                            }
                        }
                        else {
                            if (node.dotDotDotToken) {
                                write("...");
                            }
                            emit(node.name);
                            emitOptional(" = ", node.initializer);
                        }
                    }
                    function emitDefaultValueAssignments(node) {
                        if (languageVersion < 2 /* ES6 */) {
                            var tempIndex = 0;
                            ts.forEach(node.parameters, function (p) {
                                // A rest parameter cannot have a binding pattern or an initializer,
                                // so let's just ignore it.
                                if (p.dotDotDotToken) {
                                    return;
                                }
                                if (ts.isBindingPattern(p.name)) {
                                    writeLine();
                                    write("var ");
                                    emitDestructuring(p, false, tempParameters[tempIndex]);
                                    write(";");
                                    tempIndex++;
                                }
                                else if (p.initializer) {
                                    writeLine();
                                    emitStart(p);
                                    write("if (");
                                    emitNodeWithoutSourceMap(p.name);
                                    write(" === void 0)");
                                    emitEnd(p);
                                    write(" { ");
                                    emitStart(p);
                                    emitNodeWithoutSourceMap(p.name);
                                    write(" = ");
                                    emitNodeWithoutSourceMap(p.initializer);
                                    emitEnd(p);
                                    write("; }");
                                }
                            });
                        }
                    }
                    function emitRestParameter(node) {
                        if (languageVersion < 2 /* ES6 */ && ts.hasRestParameters(node)) {
                            var restIndex = node.parameters.length - 1;
                            var restParam = node.parameters[restIndex];
                            // A rest parameter cannot have a binding pattern, so let's just ignore it if it does.
                            if (ts.isBindingPattern(restParam.name)) {
                                return;
                            }
                            var tempName = createTempVariable(268435456 /* _i */).text;
                            writeLine();
                            emitLeadingComments(restParam);
                            emitStart(restParam);
                            write("var ");
                            emitNodeWithoutSourceMap(restParam.name);
                            write(" = [];");
                            emitEnd(restParam);
                            emitTrailingComments(restParam);
                            writeLine();
                            write("for (");
                            emitStart(restParam);
                            write("var " + tempName + " = " + restIndex + ";");
                            emitEnd(restParam);
                            write(" ");
                            emitStart(restParam);
                            write(tempName + " < arguments.length;");
                            emitEnd(restParam);
                            write(" ");
                            emitStart(restParam);
                            write(tempName + "++");
                            emitEnd(restParam);
                            write(") {");
                            increaseIndent();
                            writeLine();
                            emitStart(restParam);
                            emitNodeWithoutSourceMap(restParam.name);
                            write("[" + tempName + " - " + restIndex + "] = arguments[" + tempName + "];");
                            emitEnd(restParam);
                            decreaseIndent();
                            writeLine();
                            write("}");
                        }
                    }
                    function emitAccessor(node) {
                        write(node.kind === 136 /* GetAccessor */ ? "get " : "set ");
                        emit(node.name, false);
                        emitSignatureAndBody(node);
                    }
                    function shouldEmitAsArrowFunction(node) {
                        return node.kind === 163 /* ArrowFunction */ && languageVersion >= 2 /* ES6 */;
                    }
                    function emitDeclarationName(node) {
                        if (node.name) {
                            emitNodeWithoutSourceMap(node.name);
                        }
                        else {
                            write(getGeneratedNameForNode(node));
                        }
                    }
                    function shouldEmitFunctionName(node) {
                        if (node.kind === 162 /* FunctionExpression */) {
                            // Emit name if one is present
                            return !!node.name;
                        }
                        if (node.kind === 200 /* FunctionDeclaration */) {
                            // Emit name if one is present, or emit generated name in down-level case (for export default case)
                            return !!node.name || languageVersion < 2 /* ES6 */;
                        }
                    }
                    function emitFunctionDeclaration(node) {
                        if (ts.nodeIsMissing(node.body)) {
                            return emitOnlyPinnedOrTripleSlashComments(node);
                        }
                        if (node.kind !== 134 /* MethodDeclaration */ && node.kind !== 133 /* MethodSignature */) {
                            // Methods will emit the comments as part of emitting method declaration
                            emitLeadingComments(node);
                        }
                        // For targeting below es6, emit functions-like declaration including arrow function using function keyword.
                        // When targeting ES6, emit arrow function natively in ES6 by omitting function keyword and using fat arrow instead
                        if (!shouldEmitAsArrowFunction(node)) {
                            if (isES6ExportedDeclaration(node)) {
                                write("export ");
                                if (node.flags & 256 /* Default */) {
                                    write("default ");
                                }
                            }
                            write("function");
                            if (languageVersion >= 2 /* ES6 */ && node.asteriskToken) {
                                write("*");
                            }
                            write(" ");
                        }
                        if (shouldEmitFunctionName(node)) {
                            emitDeclarationName(node);
                        }
                        emitSignatureAndBody(node);
                        if (languageVersion < 2 /* ES6 */ && node.kind === 200 /* FunctionDeclaration */ && node.parent === currentSourceFile && node.name) {
                            emitExportMemberAssignments(node.name);
                        }
                        if (node.kind !== 134 /* MethodDeclaration */ && node.kind !== 133 /* MethodSignature */) {
                            emitTrailingComments(node);
                        }
                    }
                    function emitCaptureThisForNodeIfNecessary(node) {
                        if (resolver.getNodeCheckFlags(node) & 4 /* CaptureThis */) {
                            writeLine();
                            emitStart(node);
                            write("var _this = this;");
                            emitEnd(node);
                        }
                    }
                    function emitSignatureParameters(node) {
                        increaseIndent();
                        write("(");
                        if (node) {
                            var parameters = node.parameters;
                            var omitCount = languageVersion < 2 /* ES6 */ && ts.hasRestParameters(node) ? 1 : 0;
                            emitList(parameters, 0, parameters.length - omitCount, false, false);
                        }
                        write(")");
                        decreaseIndent();
                    }
                    function emitSignatureParametersForArrow(node) {
                        // Check whether the parameter list needs parentheses and preserve no-parenthesis
                        if (node.parameters.length === 1 && node.pos === node.parameters[0].pos) {
                            emit(node.parameters[0]);
                            return;
                        }
                        emitSignatureParameters(node);
                    }
                    function emitSignatureAndBody(node) {
                        var saveTempFlags = tempFlags;
                        var saveTempVariables = tempVariables;
                        var saveTempParameters = tempParameters;
                        tempFlags = 0;
                        tempVariables = undefined;
                        tempParameters = undefined;
                        // When targeting ES6, emit arrow function natively in ES6
                        if (shouldEmitAsArrowFunction(node)) {
                            emitSignatureParametersForArrow(node);
                            write(" =>");
                        }
                        else {
                            emitSignatureParameters(node);
                        }
                        if (!node.body) {
                            // There can be no body when there are parse errors.  Just emit an empty block 
                            // in that case.
                            write(" { }");
                        }
                        else if (node.body.kind === 179 /* Block */) {
                            emitBlockFunctionBody(node, node.body);
                        }
                        else {
                            emitExpressionFunctionBody(node, node.body);
                        }
                        if (!isES6ExportedDeclaration(node)) {
                            emitExportMemberAssignment(node);
                        }
                        tempFlags = saveTempFlags;
                        tempVariables = saveTempVariables;
                        tempParameters = saveTempParameters;
                    }
                    // Returns true if any preamble code was emitted.
                    function emitFunctionBodyPreamble(node) {
                        emitCaptureThisForNodeIfNecessary(node);
                        emitDefaultValueAssignments(node);
                        emitRestParameter(node);
                    }
                    function emitExpressionFunctionBody(node, body) {
                        if (languageVersion < 2 /* ES6 */) {
                            emitDownLevelExpressionFunctionBody(node, body);
                            return;
                        }
                        // For es6 and higher we can emit the expression as is.  However, in the case 
                        // where the expression might end up looking like a block when emitted, we'll
                        // also wrap it in parentheses first.  For example if you have: a => <foo>{}
                        // then we need to generate: a => ({})
                        write(" ");
                        // Unwrap all type assertions.
                        var current = body;
                        while (current.kind === 160 /* TypeAssertionExpression */) {
                            current = current.expression;
                        }
                        emitParenthesizedIf(body, current.kind === 154 /* ObjectLiteralExpression */);
                    }
                    function emitDownLevelExpressionFunctionBody(node, body) {
                        write(" {");
                        scopeEmitStart(node);
                        increaseIndent();
                        var outPos = writer.getTextPos();
                        emitDetachedComments(node.body);
                        emitFunctionBodyPreamble(node);
                        var preambleEmitted = writer.getTextPos() !== outPos;
                        decreaseIndent();
                        // If we didn't have to emit any preamble code, then attempt to keep the arrow
                        // function on one line.
                        if (!preambleEmitted && nodeStartPositionsAreOnSameLine(node, body)) {
                            write(" ");
                            emitStart(body);
                            write("return ");
                            emit(body);
                            emitEnd(body);
                            write(";");
                            emitTempDeclarations(false);
                            write(" ");
                        }
                        else {
                            increaseIndent();
                            writeLine();
                            emitLeadingComments(node.body);
                            write("return ");
                            emit(body);
                            write(";");
                            emitTrailingComments(node.body);
                            emitTempDeclarations(true);
                            decreaseIndent();
                            writeLine();
                        }
                        emitStart(node.body);
                        write("}");
                        emitEnd(node.body);
                        scopeEmitEnd();
                    }
                    function emitBlockFunctionBody(node, body) {
                        write(" {");
                        scopeEmitStart(node);
                        var initialTextPos = writer.getTextPos();
                        increaseIndent();
                        emitDetachedComments(body.statements);
                        // Emit all the directive prologues (like "use strict").  These have to come before
                        // any other preamble code we write (like parameter initializers).
                        var startIndex = emitDirectivePrologues(body.statements, true);
                        emitFunctionBodyPreamble(node);
                        decreaseIndent();
                        var preambleEmitted = writer.getTextPos() !== initialTextPos;
                        if (!preambleEmitted && nodeEndIsOnSameLineAsNodeStart(body, body)) {
                            for (var _a = 0, _b = body.statements; _a < _b.length; _a++) {
                                var statement = _b[_a];
                                write(" ");
                                emit(statement);
                            }
                            emitTempDeclarations(false);
                            write(" ");
                            emitLeadingCommentsOfPosition(body.statements.end);
                        }
                        else {
                            increaseIndent();
                            emitLinesStartingAt(body.statements, startIndex);
                            emitTempDeclarations(true);
                            writeLine();
                            emitLeadingCommentsOfPosition(body.statements.end);
                            decreaseIndent();
                        }
                        emitToken(15 /* CloseBraceToken */, body.statements.end);
                        scopeEmitEnd();
                    }
                    function findInitialSuperCall(ctor) {
                        if (ctor.body) {
                            var statement = ctor.body.statements[0];
                            if (statement && statement.kind === 182 /* ExpressionStatement */) {
                                var expr = statement.expression;
                                if (expr && expr.kind === 157 /* CallExpression */) {
                                    var func = expr.expression;
                                    if (func && func.kind === 91 /* SuperKeyword */) {
                                        return statement;
                                    }
                                }
                            }
                        }
                    }
                    function emitParameterPropertyAssignments(node) {
                        ts.forEach(node.parameters, function (param) {
                            if (param.flags & 112 /* AccessibilityModifier */) {
                                writeLine();
                                emitStart(param);
                                emitStart(param.name);
                                write("this.");
                                emitNodeWithoutSourceMap(param.name);
                                emitEnd(param.name);
                                write(" = ");
                                emit(param.name);
                                write(";");
                                emitEnd(param);
                            }
                        });
                    }
                    function emitMemberAccessForPropertyName(memberName) {
                        // TODO: (jfreeman,drosen): comment on why this is emitNodeWithoutSourceMap instead of emit here.
                        if (memberName.kind === 8 /* StringLiteral */ || memberName.kind === 7 /* NumericLiteral */) {
                            write("[");
                            emitNodeWithoutSourceMap(memberName);
                            write("]");
                        }
                        else if (memberName.kind === 127 /* ComputedPropertyName */) {
                            emitComputedPropertyName(memberName);
                        }
                        else {
                            write(".");
                            emitNodeWithoutSourceMap(memberName);
                        }
                    }
                    function getInitializedProperties(node, static) {
                        var properties = [];
                        for (var _a = 0, _b = node.members; _a < _b.length; _a++) {
                            var member = _b[_a];
                            if (member.kind === 132 /* PropertyDeclaration */ && static === ((member.flags & 128 /* Static */) !== 0) && member.initializer) {
                                properties.push(member);
                            }
                        }
                        return properties;
                    }
                    function emitPropertyDeclarations(node, properties) {
                        for (var _a = 0; _a < properties.length; _a++) {
                            var property = properties[_a];
                            emitPropertyDeclaration(node, property);
                        }
                    }
                    function emitPropertyDeclaration(node, property, receiver, isExpression) {
                        writeLine();
                        emitLeadingComments(property);
                        emitStart(property);
                        emitStart(property.name);
                        if (receiver) {
                            emit(receiver);
                        }
                        else {
                            if (property.flags & 128 /* Static */) {
                                emitDeclarationName(node);
                            }
                            else {
                                write("this");
                            }
                        }
                        emitMemberAccessForPropertyName(property.name);
                        emitEnd(property.name);
                        write(" = ");
                        emit(property.initializer);
                        if (!isExpression) {
                            write(";");
                        }
                        emitEnd(property);
                        emitTrailingComments(property);
                    }
                    function emitMemberFunctionsForES5AndLower(node) {
                        ts.forEach(node.members, function (member) {
                            if (member.kind === 178 /* SemicolonClassElement */) {
                                writeLine();
                                write(";");
                            }
                            else if (member.kind === 134 /* MethodDeclaration */ || node.kind === 133 /* MethodSignature */) {
                                if (!member.body) {
                                    return emitOnlyPinnedOrTripleSlashComments(member);
                                }
                                writeLine();
                                emitLeadingComments(member);
                                emitStart(member);
                                emitStart(member.name);
                                emitClassMemberPrefix(node, member);
                                emitMemberAccessForPropertyName(member.name);
                                emitEnd(member.name);
                                write(" = ");
                                emitStart(member);
                                emitFunctionDeclaration(member);
                                emitEnd(member);
                                emitEnd(member);
                                write(";");
                                emitTrailingComments(member);
                            }
                            else if (member.kind === 136 /* GetAccessor */ || member.kind === 137 /* SetAccessor */) {
                                var accessors = ts.getAllAccessorDeclarations(node.members, member);
                                if (member === accessors.firstAccessor) {
                                    writeLine();
                                    emitStart(member);
                                    write("Object.defineProperty(");
                                    emitStart(member.name);
                                    emitClassMemberPrefix(node, member);
                                    write(", ");
                                    emitExpressionForPropertyName(member.name);
                                    emitEnd(member.name);
                                    write(", {");
                                    increaseIndent();
                                    if (accessors.getAccessor) {
                                        writeLine();
                                        emitLeadingComments(accessors.getAccessor);
                                        write("get: ");
                                        emitStart(accessors.getAccessor);
                                        write("function ");
                                        emitSignatureAndBody(accessors.getAccessor);
                                        emitEnd(accessors.getAccessor);
                                        emitTrailingComments(accessors.getAccessor);
                                        write(",");
                                    }
                                    if (accessors.setAccessor) {
                                        writeLine();
                                        emitLeadingComments(accessors.setAccessor);
                                        write("set: ");
                                        emitStart(accessors.setAccessor);
                                        write("function ");
                                        emitSignatureAndBody(accessors.setAccessor);
                                        emitEnd(accessors.setAccessor);
                                        emitTrailingComments(accessors.setAccessor);
                                        write(",");
                                    }
                                    writeLine();
                                    write("enumerable: true,");
                                    writeLine();
                                    write("configurable: true");
                                    decreaseIndent();
                                    writeLine();
                                    write("});");
                                    emitEnd(member);
                                }
                            }
                        });
                    }
                    function emitMemberFunctionsForES6AndHigher(node) {
                        for (var _a = 0, _b = node.members; _a < _b.length; _a++) {
                            var member = _b[_a];
                            if ((member.kind === 134 /* MethodDeclaration */ || node.kind === 133 /* MethodSignature */) && !member.body) {
                                emitOnlyPinnedOrTripleSlashComments(member);
                            }
                            else if (member.kind === 134 /* MethodDeclaration */ ||
                                member.kind === 136 /* GetAccessor */ ||
                                member.kind === 137 /* SetAccessor */) {
                                writeLine();
                                emitLeadingComments(member);
                                emitStart(member);
                                if (member.flags & 128 /* Static */) {
                                    write("static ");
                                }
                                if (member.kind === 136 /* GetAccessor */) {
                                    write("get ");
                                }
                                else if (member.kind === 137 /* SetAccessor */) {
                                    write("set ");
                                }
                                if (member.asteriskToken) {
                                    write("*");
                                }
                                emit(member.name);
                                emitSignatureAndBody(member);
                                emitEnd(member);
                                emitTrailingComments(member);
                            }
                            else if (member.kind === 178 /* SemicolonClassElement */) {
                                writeLine();
                                write(";");
                            }
                        }
                    }
                    function emitConstructor(node, baseTypeElement) {
                        var saveTempFlags = tempFlags;
                        var saveTempVariables = tempVariables;
                        var saveTempParameters = tempParameters;
                        tempFlags = 0;
                        tempVariables = undefined;
                        tempParameters = undefined;
                        emitConstructorWorker(node, baseTypeElement);
                        tempFlags = saveTempFlags;
                        tempVariables = saveTempVariables;
                        tempParameters = saveTempParameters;
                    }
                    function emitConstructorWorker(node, baseTypeElement) {
                        // Check if we have property assignment inside class declaration.
                        // If there is property assignment, we need to emit constructor whether users define it or not
                        // If there is no property assignment, we can omit constructor if users do not define it
                        var hasInstancePropertyWithInitializer = false;
                        // Emit the constructor overload pinned comments
                        ts.forEach(node.members, function (member) {
                            if (member.kind === 135 /* Constructor */ && !member.body) {
                                emitOnlyPinnedOrTripleSlashComments(member);
                            }
                            // Check if there is any non-static property assignment
                            if (member.kind === 132 /* PropertyDeclaration */ && member.initializer && (member.flags & 128 /* Static */) === 0) {
                                hasInstancePropertyWithInitializer = true;
                            }
                        });
                        var ctor = ts.getFirstConstructorWithBody(node);
                        // For target ES6 and above, if there is no user-defined constructor and there is no property assignment
                        // do not emit constructor in class declaration.
                        if (languageVersion >= 2 /* ES6 */ && !ctor && !hasInstancePropertyWithInitializer) {
                            return;
                        }
                        if (ctor) {
                            emitLeadingComments(ctor);
                        }
                        emitStart(ctor || node);
                        if (languageVersion < 2 /* ES6 */) {
                            write("function ");
                            emitDeclarationName(node);
                            emitSignatureParameters(ctor);
                        }
                        else {
                            write("constructor");
                            if (ctor) {
                                emitSignatureParameters(ctor);
                            }
                            else {
                                // Based on EcmaScript6 section 14.5.14: Runtime Semantics: ClassDefinitionEvaluation.
                                // If constructor is empty, then,
                                //      If ClassHeritageopt is present, then
                                //          Let constructor be the result of parsing the String "constructor(... args){ super (...args);}" using the syntactic grammar with the goal symbol MethodDefinition.
                                //      Else,
                                //          Let constructor be the result of parsing the String "constructor( ){ }" using the syntactic grammar with the goal symbol MethodDefinition
                                if (baseTypeElement) {
                                    write("(...args)");
                                }
                                else {
                                    write("()");
                                }
                            }
                        }
                        write(" {");
                        scopeEmitStart(node, "constructor");
                        increaseIndent();
                        if (ctor) {
                            emitDetachedComments(ctor.body.statements);
                        }
                        emitCaptureThisForNodeIfNecessary(node);
                        if (ctor) {
                            emitDefaultValueAssignments(ctor);
                            emitRestParameter(ctor);
                            if (baseTypeElement) {
                                var superCall = findInitialSuperCall(ctor);
                                if (superCall) {
                                    writeLine();
                                    emit(superCall);
                                }
                            }
                            emitParameterPropertyAssignments(ctor);
                        }
                        else {
                            if (baseTypeElement) {
                                writeLine();
                                emitStart(baseTypeElement);
                                if (languageVersion < 2 /* ES6 */) {
                                    write("_super.apply(this, arguments);");
                                }
                                else {
                                    write("super(...args);");
                                }
                                emitEnd(baseTypeElement);
                            }
                        }
                        emitPropertyDeclarations(node, getInitializedProperties(node, false));
                        if (ctor) {
                            var statements = ctor.body.statements;
                            if (superCall) {
                                statements = statements.slice(1);
                            }
                            emitLines(statements);
                        }
                        emitTempDeclarations(true);
                        writeLine();
                        if (ctor) {
                            emitLeadingCommentsOfPosition(ctor.body.statements.end);
                        }
                        decreaseIndent();
                        emitToken(15 /* CloseBraceToken */, ctor ? ctor.body.statements.end : node.members.end);
                        scopeEmitEnd();
                        emitEnd(ctor || node);
                        if (ctor) {
                            emitTrailingComments(ctor);
                        }
                    }
                    function emitClassExpression(node) {
                        return emitClassLikeDeclaration(node);
                    }
                    function emitClassDeclaration(node) {
                        return emitClassLikeDeclaration(node);
                    }
                    function emitClassLikeDeclaration(node) {
                        if (languageVersion < 2 /* ES6 */) {
                            emitClassLikeDeclarationBelowES6(node);
                        }
                        else {
                            emitClassLikeDeclarationForES6AndHigher(node);
                        }
                    }
                    function emitClassLikeDeclarationForES6AndHigher(node) {
                        var thisNodeIsDecorated = ts.nodeIsDecorated(node);
                        if (node.kind === 201 /* ClassDeclaration */) {
                            if (thisNodeIsDecorated) {
                                // To preserve the correct runtime semantics when decorators are applied to the class,
                                // the emit needs to follow one of the following rules:
                                //
                                // * For a local class declaration:
                                //
                                //     @dec class C {
                                //     }
                                //
                                //   The emit should be:
                                //
                                //     let C = class {
                                //     };
                                //     Object.defineProperty(C, "name", { value: "C", configurable: true });
                                //     C = __decorate([dec], C);
                                //
                                // * For an exported class declaration:
                                //
                                //     @dec export class C {
                                //     }
                                //
                                //   The emit should be:
                                //
                                //     export let C = class {
                                //     };
                                //     Object.defineProperty(C, "name", { value: "C", configurable: true });
                                //     C = __decorate([dec], C);
                                //
                                // * For a default export of a class declaration with a name:
                                //
                                //     @dec default export class C {
                                //     }
                                //
                                //   The emit should be:
                                //
                                //     let C = class {
                                //     }
                                //     Object.defineProperty(C, "name", { value: "C", configurable: true });
                                //     C = __decorate([dec], C);
                                //     export default C;
                                //
                                // * For a default export of a class declaration without a name:
                                //
                                //     @dec default export class {
                                //     }
                                //
                                //   The emit should be:
                                //
                                //     let _default = class {
                                //     }
                                //     _default = __decorate([dec], _default);
                                //     export default _default;
                                //
                                if (isES6ExportedDeclaration(node) && !(node.flags & 256 /* Default */)) {
                                    write("export ");
                                }
                                write("let ");
                                emitDeclarationName(node);
                                write(" = ");
                            }
                            else if (isES6ExportedDeclaration(node)) {
                                write("export ");
                                if (node.flags & 256 /* Default */) {
                                    write("default ");
                                }
                            }
                        }
                        // If the class has static properties, and it's a class expression, then we'll need
                        // to specialize the emit a bit.  for a class expression of the form: 
                        //
                        //      class C { static a = 1; static b = 2; ... } 
                        //
                        // We'll emit:
                        //
                        //      (_temp = class C { ... }, _temp.a = 1, _temp.b = 2, _temp)
                        //
                        // This keeps the expression as an expression, while ensuring that the static parts
                        // of it have been initialized by the time it is used.
                        var staticProperties = getInitializedProperties(node, true);
                        var isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === 174 /* ClassExpression */;
                        var tempVariable;
                        if (isClassExpressionWithStaticProperties) {
                            tempVariable = createAndRecordTempVariable(0 /* Auto */);
                            write("(");
                            increaseIndent();
                            emit(tempVariable);
                            write(" = ");
                        }
                        write("class");
                        // check if this is an "export default class" as it may not have a name. Do not emit the name if the class is decorated.
                        if ((node.name || !(node.flags & 256 /* Default */)) && !thisNodeIsDecorated) {
                            write(" ");
                            emitDeclarationName(node);
                        }
                        var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node);
                        if (baseTypeNode) {
                            write(" extends ");
                            emit(baseTypeNode.expression);
                        }
                        write(" {");
                        increaseIndent();
                        scopeEmitStart(node);
                        writeLine();
                        emitConstructor(node, baseTypeNode);
                        emitMemberFunctionsForES6AndHigher(node);
                        decreaseIndent();
                        writeLine();
                        emitToken(15 /* CloseBraceToken */, node.members.end);
                        scopeEmitEnd();
                        // For a decorated class, we need to assign its name (if it has one). This is because we emit
                        // the class as a class expression to avoid the double-binding of the identifier:
                        //
                        //   let C = class {
                        //   }
                        //   Object.defineProperty(C, "name", { value: "C", configurable: true });
                        //
                        if (thisNodeIsDecorated) {
                            write(";");
                            if (node.name) {
                                writeLine();
                                write("Object.defineProperty(");
                                emitDeclarationName(node);
                                write(", \"name\", { value: \"");
                                emitDeclarationName(node);
                                write("\", configurable: true });");
                                writeLine();
                            }
                        }
                        // Emit static property assignment. Because classDeclaration is lexically evaluated,
                        // it is safe to emit static property assignment after classDeclaration
                        // From ES6 specification:
                        //      HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using
                        //                                  a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
                        if (isClassExpressionWithStaticProperties) {
                            for (var _a = 0; _a < staticProperties.length; _a++) {
                                var property = staticProperties[_a];
                                write(",");
                                writeLine();
                                emitPropertyDeclaration(node, property, tempVariable, true);
                            }
                            write(",");
                            writeLine();
                            emit(tempVariable);
                            decreaseIndent();
                            write(")");
                        }
                        else {
                            writeLine();
                            emitPropertyDeclarations(node, staticProperties);
                            emitDecoratorsOfClass(node);
                        }
                        // If this is an exported class, but not on the top level (i.e. on an internal
                        // module), export it
                        if (!isES6ExportedDeclaration(node) && (node.flags & 1 /* Export */)) {
                            writeLine();
                            emitStart(node);
                            emitModuleMemberName(node);
                            write(" = ");
                            emitDeclarationName(node);
                            emitEnd(node);
                            write(";");
                        }
                        else if (isES6ExportedDeclaration(node) && (node.flags & 256 /* Default */) && thisNodeIsDecorated) {
                            // if this is a top level default export of decorated class, write the export after the declaration.
                            writeLine();
                            write("export default ");
                            emitDeclarationName(node);
                            write(";");
                        }
                    }
                    function emitClassLikeDeclarationBelowES6(node) {
                        if (node.kind === 201 /* ClassDeclaration */) {
                            write("var ");
                            emitDeclarationName(node);
                            write(" = ");
                        }
                        write("(function (");
                        var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node);
                        if (baseTypeNode) {
                            write("_super");
                        }
                        write(") {");
                        var saveTempFlags = tempFlags;
                        var saveTempVariables = tempVariables;
                        var saveTempParameters = tempParameters;
                        var saveComputedPropertyNamesToGeneratedNames = computedPropertyNamesToGeneratedNames;
                        tempFlags = 0;
                        tempVariables = undefined;
                        tempParameters = undefined;
                        computedPropertyNamesToGeneratedNames = undefined;
                        increaseIndent();
                        scopeEmitStart(node);
                        if (baseTypeNode) {
                            writeLine();
                            emitStart(baseTypeNode);
                            write("__extends(");
                            emitDeclarationName(node);
                            write(", _super);");
                            emitEnd(baseTypeNode);
                        }
                        writeLine();
                        emitConstructor(node, baseTypeNode);
                        emitMemberFunctionsForES5AndLower(node);
                        emitPropertyDeclarations(node, getInitializedProperties(node, true));
                        writeLine();
                        emitDecoratorsOfClass(node);
                        writeLine();
                        emitToken(15 /* CloseBraceToken */, node.members.end, function () {
                            write("return ");
                            emitDeclarationName(node);
                        });
                        write(";");
                        emitTempDeclarations(true);
                        tempFlags = saveTempFlags;
                        tempVariables = saveTempVariables;
                        tempParameters = saveTempParameters;
                        computedPropertyNamesToGeneratedNames = saveComputedPropertyNamesToGeneratedNames;
                        decreaseIndent();
                        writeLine();
                        emitToken(15 /* CloseBraceToken */, node.members.end);
                        scopeEmitEnd();
                        emitStart(node);
                        write(")(");
                        if (baseTypeNode) {
                            emit(baseTypeNode.expression);
                        }
                        write(")");
                        if (node.kind === 201 /* ClassDeclaration */) {
                            write(";");
                        }
                        emitEnd(node);
                        if (node.kind === 201 /* ClassDeclaration */) {
                            emitExportMemberAssignment(node);
                        }
                        if (languageVersion < 2 /* ES6 */ && node.parent === currentSourceFile && node.name) {
                            emitExportMemberAssignments(node.name);
                        }
                    }
                    function emitClassMemberPrefix(node, member) {
                        emitDeclarationName(node);
                        if (!(member.flags & 128 /* Static */)) {
                            write(".prototype");
                        }
                    }
                    function emitDecoratorsOfClass(node) {
                        emitDecoratorsOfMembers(node, 0);
                        emitDecoratorsOfMembers(node, 128 /* Static */);
                        emitDecoratorsOfConstructor(node);
                    }
                    function emitDecoratorsOfConstructor(node) {
                        var decorators = node.decorators;
                        var constructor = ts.getFirstConstructorWithBody(node);
                        var hasDecoratedParameters = constructor && ts.forEach(constructor.parameters, ts.nodeIsDecorated);
                        // skip decoration of the constructor if neither it nor its parameters are decorated
                        if (!decorators && !hasDecoratedParameters) {
                            return;
                        }
                        // Emit the call to __decorate. Given the class:
                        //
                        //   @dec
                        //   class C {
                        //   }
                        //
                        // The emit for the class is:
                        //
                        //   C = __decorate([dec], C);
                        //
                        writeLine();
                        emitStart(node);
                        emitDeclarationName(node);
                        write(" = __decorate([");
                        increaseIndent();
                        writeLine();
                        var decoratorCount = decorators ? decorators.length : 0;
                        var argumentsWritten = emitList(decorators, 0, decoratorCount, true, false, false, true, function (decorator) {
                            emitStart(decorator);
                            emit(decorator.expression);
                            emitEnd(decorator);
                        });
                        argumentsWritten += emitDecoratorsOfParameters(constructor, argumentsWritten > 0);
                        emitSerializedTypeMetadata(node, argumentsWritten >= 0);
                        decreaseIndent();
                        writeLine();
                        write("], ");
                        emitDeclarationName(node);
                        write(");");
                        emitEnd(node);
                        writeLine();
                    }
                    function emitDecoratorsOfMembers(node, staticFlag) {
                        for (var _a = 0, _b = node.members; _a < _b.length; _a++) {
                            var member = _b[_a];
                            // only emit members in the correct group
                            if ((member.flags & 128 /* Static */) !== staticFlag) {
                                continue;
                            }
                            // skip members that cannot be decorated (such as the constructor)
                            if (!ts.nodeCanBeDecorated(member)) {
                                continue;
                            }
                            // skip a member if it or any of its parameters are not decorated
                            if (!ts.nodeOrChildIsDecorated(member)) {
                                continue;
                            }
                            // skip an accessor declaration if it is not the first accessor
                            var decorators = void 0;
                            var functionLikeMember = void 0;
                            if (ts.isAccessor(member)) {
                                var accessors = ts.getAllAccessorDeclarations(node.members, member);
                                if (member !== accessors.firstAccessor) {
                                    continue;
                                }
                                // get the decorators from the first accessor with decorators
                                decorators = accessors.firstAccessor.decorators;
                                if (!decorators && accessors.secondAccessor) {
                                    decorators = accessors.secondAccessor.decorators;
                                }
                                // we only decorate parameters of the set accessor
                                functionLikeMember = accessors.setAccessor;
                            }
                            else {
                                decorators = member.decorators;
                                // we only decorate the parameters here if this is a method
                                if (member.kind === 134 /* MethodDeclaration */) {
                                    functionLikeMember = member;
                                }
                            }
                            // Emit the call to __decorate. Given the following:
                            //
                            //   class C {
                            //     @dec method(@dec2 x) {}
                            //     @dec get accessor() {}
                            //     @dec prop;
                            //   }
                            //
                            // The emit for a method is:
                            //
                            //   Object.defineProperty(C.prototype, "method", 
                            //       __decorate([
                            //           dec,
                            //           __param(0, dec2),
                            //           __metadata("design:type", Function),
                            //           __metadata("design:paramtypes", [Object]),
                            //           __metadata("design:returntype", void 0)
                            //       ], C.prototype, "method", Object.getOwnPropertyDescriptor(C.prototype, "method")));
                            // 
                            // The emit for an accessor is:
                            //
                            //   Object.defineProperty(C.prototype, "accessor", 
                            //       __decorate([
                            //           dec
                            //       ], C.prototype, "accessor", Object.getOwnPropertyDescriptor(C.prototype, "accessor")));
                            //
                            // The emit for a property is:
                            //
                            //   __decorate([
                            //       dec
                            //   ], C.prototype, "prop");
                            //
                            writeLine();
                            emitStart(member);
                            if (member.kind !== 132 /* PropertyDeclaration */) {
                                write("Object.defineProperty(");
                                emitStart(member.name);
                                emitClassMemberPrefix(node, member);
                                write(", ");
                                emitExpressionForPropertyName(member.name);
                                emitEnd(member.name);
                                write(",");
                                increaseIndent();
                                writeLine();
                            }
                            write("__decorate([");
                            increaseIndent();
                            writeLine();
                            var decoratorCount = decorators ? decorators.length : 0;
                            var argumentsWritten = emitList(decorators, 0, decoratorCount, true, false, false, true, function (decorator) {
                                emitStart(decorator);
                                emit(decorator.expression);
                                emitEnd(decorator);
                            });
                            argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0);
                            emitSerializedTypeMetadata(member, argumentsWritten > 0);
                            decreaseIndent();
                            writeLine();
                            write("], ");
                            emitStart(member.name);
                            emitClassMemberPrefix(node, member);
                            write(", ");
                            emitExpressionForPropertyName(member.name);
                            emitEnd(member.name);
                            if (member.kind !== 132 /* PropertyDeclaration */) {
                                write(", Object.getOwnPropertyDescriptor(");
                                emitStart(member.name);
                                emitClassMemberPrefix(node, member);
                                write(", ");
                                emitExpressionForPropertyName(member.name);
                                emitEnd(member.name);
                                write("))");
                                decreaseIndent();
                            }
                            write(");");
                            emitEnd(member);
                            writeLine();
                        }
                    }
                    function emitDecoratorsOfParameters(node, leadingComma) {
                        var argumentsWritten = 0;
                        if (node) {
                            var parameterIndex = 0;
                            for (var _a = 0, _b = node.parameters; _a < _b.length; _a++) {
                                var parameter = _b[_a];
                                if (ts.nodeIsDecorated(parameter)) {
                                    var decorators = parameter.decorators;
                                    argumentsWritten += emitList(decorators, 0, decorators.length, true, false, leadingComma, true, function (decorator) {
                                        emitStart(decorator);
                                        write("__param(" + parameterIndex + ", ");
                                        emit(decorator.expression);
                                        write(")");
                                        emitEnd(decorator);
                                    });
                                    leadingComma = true;
                                }
                                ++parameterIndex;
                            }
                        }
                        return argumentsWritten;
                    }
                    function shouldEmitTypeMetadata(node) {
                        // This method determines whether to emit the "design:type" metadata based on the node's kind.
                        // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata 
                        // compiler option is set.
                        switch (node.kind) {
                            case 134 /* MethodDeclaration */:
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                            case 132 /* PropertyDeclaration */:
                                return true;
                        }
                        return false;
                    }
                    function shouldEmitReturnTypeMetadata(node) {
                        // This method determines whether to emit the "design:returntype" metadata based on the node's kind.
                        // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata 
                        // compiler option is set.
                        switch (node.kind) {
                            case 134 /* MethodDeclaration */:
                                return true;
                        }
                        return false;
                    }
                    function shouldEmitParamTypesMetadata(node) {
                        // This method determines whether to emit the "design:paramtypes" metadata based on the node's kind.
                        // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata 
                        // compiler option is set.
                        switch (node.kind) {
                            case 201 /* ClassDeclaration */:
                            case 134 /* MethodDeclaration */:
                            case 137 /* SetAccessor */:
                                return true;
                        }
                        return false;
                    }
                    function emitSerializedTypeMetadata(node, writeComma) {
                        // This method emits the serialized type metadata for a decorator target.
                        // The caller should have already tested whether the node has decorators.
                        var argumentsWritten = 0;
                        if (compilerOptions.emitDecoratorMetadata) {
                            if (shouldEmitTypeMetadata(node)) {
                                var serializedType = resolver.serializeTypeOfNode(node, getGeneratedNameForNode);
                                if (serializedType) {
                                    if (writeComma) {
                                        write(", ");
                                    }
                                    writeLine();
                                    write("__metadata('design:type', ");
                                    emitSerializedType(node, serializedType);
                                    write(")");
                                    argumentsWritten++;
                                }
                            }
                            if (shouldEmitParamTypesMetadata(node)) {
                                var serializedTypes = resolver.serializeParameterTypesOfNode(node, getGeneratedNameForNode);
                                if (serializedTypes) {
                                    if (writeComma || argumentsWritten) {
                                        write(", ");
                                    }
                                    writeLine();
                                    write("__metadata('design:paramtypes', [");
                                    for (var i = 0; i < serializedTypes.length; ++i) {
                                        if (i > 0) {
                                            write(", ");
                                        }
                                        emitSerializedType(node, serializedTypes[i]);
                                    }
                                    write("])");
                                    argumentsWritten++;
                                }
                            }
                            if (shouldEmitReturnTypeMetadata(node)) {
                                var serializedType = resolver.serializeReturnTypeOfNode(node, getGeneratedNameForNode);
                                if (serializedType) {
                                    if (writeComma || argumentsWritten) {
                                        write(", ");
                                    }
                                    writeLine();
                                    write("__metadata('design:returntype', ");
                                    emitSerializedType(node, serializedType);
                                    write(")");
                                    argumentsWritten++;
                                }
                            }
                        }
                        return argumentsWritten;
                    }
                    function serializeTypeNameSegment(location, path, index) {
                        switch (index) {
                            case 0:
                                return "typeof " + path[index] + " !== 'undefined' && " + path[index];
                            case 1:
                                return serializeTypeNameSegment(location, path, index - 1) + "." + path[index];
                            default:
                                var temp = createAndRecordTempVariable(0 /* Auto */).text;
                                return "(" + temp + " = " + serializeTypeNameSegment(location, path, index - 1) + ") && " + temp + "." + path[index];
                        }
                    }
                    function emitSerializedType(location, name) {
                        if (typeof name === "string") {
                            write(name);
                            return;
                        }
                        else {
                            ts.Debug.assert(name.length > 0, "Invalid serialized type name");
                            write("(" + serializeTypeNameSegment(location, name, name.length - 1) + ") || Object");
                        }
                    }
                    function emitInterfaceDeclaration(node) {
                        emitOnlyPinnedOrTripleSlashComments(node);
                    }
                    function shouldEmitEnumDeclaration(node) {
                        var isConstEnum = ts.isConst(node);
                        return !isConstEnum || compilerOptions.preserveConstEnums || compilerOptions.separateCompilation;
                    }
                    function emitEnumDeclaration(node) {
                        // const enums are completely erased during compilation.
                        if (!shouldEmitEnumDeclaration(node)) {
                            return;
                        }
                        if (!(node.flags & 1 /* Export */) || isES6ExportedDeclaration(node)) {
                            emitStart(node);
                            if (isES6ExportedDeclaration(node)) {
                                write("export ");
                            }
                            write("var ");
                            emit(node.name);
                            emitEnd(node);
                            write(";");
                        }
                        writeLine();
                        emitStart(node);
                        write("(function (");
                        emitStart(node.name);
                        write(getGeneratedNameForNode(node));
                        emitEnd(node.name);
                        write(") {");
                        increaseIndent();
                        scopeEmitStart(node);
                        emitLines(node.members);
                        decreaseIndent();
                        writeLine();
                        emitToken(15 /* CloseBraceToken */, node.members.end);
                        scopeEmitEnd();
                        write(")(");
                        emitModuleMemberName(node);
                        write(" || (");
                        emitModuleMemberName(node);
                        write(" = {}));");
                        emitEnd(node);
                        if (!isES6ExportedDeclaration(node) && node.flags & 1 /* Export */) {
                            writeLine();
                            emitStart(node);
                            write("var ");
                            emit(node.name);
                            write(" = ");
                            emitModuleMemberName(node);
                            emitEnd(node);
                            write(";");
                        }
                        if (languageVersion < 2 /* ES6 */ && node.parent === currentSourceFile) {
                            emitExportMemberAssignments(node.name);
                        }
                    }
                    function emitEnumMember(node) {
                        var enumParent = node.parent;
                        emitStart(node);
                        write(getGeneratedNameForNode(enumParent));
                        write("[");
                        write(getGeneratedNameForNode(enumParent));
                        write("[");
                        emitExpressionForPropertyName(node.name);
                        write("] = ");
                        writeEnumMemberDeclarationValue(node);
                        write("] = ");
                        emitExpressionForPropertyName(node.name);
                        emitEnd(node);
                        write(";");
                    }
                    function writeEnumMemberDeclarationValue(member) {
                        var value = resolver.getConstantValue(member);
                        if (value !== undefined) {
                            write(value.toString());
                            return;
                        }
                        else if (member.initializer) {
                            emit(member.initializer);
                        }
                        else {
                            write("undefined");
                        }
                    }
                    function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration) {
                        if (moduleDeclaration.body.kind === 205 /* ModuleDeclaration */) {
                            var recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body);
                            return recursiveInnerModule || moduleDeclaration.body;
                        }
                    }
                    function shouldEmitModuleDeclaration(node) {
                        return ts.isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.separateCompilation);
                    }
                    function isModuleMergedWithES6Class(node) {
                        return languageVersion === 2 /* ES6 */ && !!(resolver.getNodeCheckFlags(node) & 2048 /* LexicalModuleMergesWithClass */);
                    }
                    function emitModuleDeclaration(node) {
                        // Emit only if this module is non-ambient.
                        var shouldEmit = shouldEmitModuleDeclaration(node);
                        if (!shouldEmit) {
                            return emitOnlyPinnedOrTripleSlashComments(node);
                        }
                        if (!isModuleMergedWithES6Class(node)) {
                            emitStart(node);
                            if (isES6ExportedDeclaration(node)) {
                                write("export ");
                            }
                            write("var ");
                            emit(node.name);
                            write(";");
                            emitEnd(node);
                            writeLine();
                        }
                        emitStart(node);
                        write("(function (");
                        emitStart(node.name);
                        write(getGeneratedNameForNode(node));
                        emitEnd(node.name);
                        write(") ");
                        if (node.body.kind === 206 /* ModuleBlock */) {
                            var saveTempFlags = tempFlags;
                            var saveTempVariables = tempVariables;
                            tempFlags = 0;
                            tempVariables = undefined;
                            emit(node.body);
                            tempFlags = saveTempFlags;
                            tempVariables = saveTempVariables;
                        }
                        else {
                            write("{");
                            increaseIndent();
                            scopeEmitStart(node);
                            emitCaptureThisForNodeIfNecessary(node);
                            writeLine();
                            emit(node.body);
                            decreaseIndent();
                            writeLine();
                            var moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node).body;
                            emitToken(15 /* CloseBraceToken */, moduleBlock.statements.end);
                            scopeEmitEnd();
                        }
                        write(")(");
                        // write moduleDecl = containingModule.m only if it is not exported es6 module member
                        if ((node.flags & 1 /* Export */) && !isES6ExportedDeclaration(node)) {
                            emit(node.name);
                            write(" = ");
                        }
                        emitModuleMemberName(node);
                        write(" || (");
                        emitModuleMemberName(node);
                        write(" = {}));");
                        emitEnd(node);
                        if (!isES6ExportedDeclaration(node) && node.name.kind === 65 /* Identifier */ && node.parent === currentSourceFile) {
                            emitExportMemberAssignments(node.name);
                        }
                    }
                    function emitRequire(moduleName) {
                        if (moduleName.kind === 8 /* StringLiteral */) {
                            write("require(");
                            emitStart(moduleName);
                            emitLiteral(moduleName);
                            emitEnd(moduleName);
                            emitToken(17 /* CloseParenToken */, moduleName.end);
                        }
                        else {
                            write("require()");
                        }
                    }
                    function getNamespaceDeclarationNode(node) {
                        if (node.kind === 208 /* ImportEqualsDeclaration */) {
                            return node;
                        }
                        var importClause = node.importClause;
                        if (importClause && importClause.namedBindings && importClause.namedBindings.kind === 211 /* NamespaceImport */) {
                            return importClause.namedBindings;
                        }
                    }
                    function isDefaultImport(node) {
                        return node.kind === 209 /* ImportDeclaration */ && node.importClause && !!node.importClause.name;
                    }
                    function emitExportImportAssignments(node) {
                        if (ts.isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node)) {
                            emitExportMemberAssignments(node.name);
                        }
                        ts.forEachChild(node, emitExportImportAssignments);
                    }
                    function emitImportDeclaration(node) {
                        if (languageVersion < 2 /* ES6 */) {
                            return emitExternalImportDeclaration(node);
                        }
                        // ES6 import
                        if (node.importClause) {
                            var shouldEmitDefaultBindings = resolver.isReferencedAliasDeclaration(node.importClause);
                            var shouldEmitNamedBindings = node.importClause.namedBindings && resolver.isReferencedAliasDeclaration(node.importClause.namedBindings, true);
                            if (shouldEmitDefaultBindings || shouldEmitNamedBindings) {
                                write("import ");
                                emitStart(node.importClause);
                                if (shouldEmitDefaultBindings) {
                                    emit(node.importClause.name);
                                    if (shouldEmitNamedBindings) {
                                        write(", ");
                                    }
                                }
                                if (shouldEmitNamedBindings) {
                                    emitLeadingComments(node.importClause.namedBindings);
                                    emitStart(node.importClause.namedBindings);
                                    if (node.importClause.namedBindings.kind === 211 /* NamespaceImport */) {
                                        write("* as ");
                                        emit(node.importClause.namedBindings.name);
                                    }
                                    else {
                                        write("{ ");
                                        emitExportOrImportSpecifierList(node.importClause.namedBindings.elements, resolver.isReferencedAliasDeclaration);
                                        write(" }");
                                    }
                                    emitEnd(node.importClause.namedBindings);
                                    emitTrailingComments(node.importClause.namedBindings);
                                }
                                emitEnd(node.importClause);
                                write(" from ");
                                emit(node.moduleSpecifier);
                                write(";");
                            }
                        }
                        else {
                            write("import ");
                            emit(node.moduleSpecifier);
                            write(";");
                        }
                    }
                    function emitExternalImportDeclaration(node) {
                        if (ts.contains(externalImports, node)) {
                            var isExportedImport = node.kind === 208 /* ImportEqualsDeclaration */ && (node.flags & 1 /* Export */) !== 0;
                            var namespaceDeclaration = getNamespaceDeclarationNode(node);
                            if (compilerOptions.module !== 2 /* AMD */) {
                                emitLeadingComments(node);
                                emitStart(node);
                                if (namespaceDeclaration && !isDefaultImport(node)) {
                                    // import x = require("foo")
                                    // import * as x from "foo"
                                    if (!isExportedImport)
                                        write("var ");
                                    emitModuleMemberName(namespaceDeclaration);
                                    write(" = ");
                                }
                                else {
                                    // import "foo"
                                    // import x from "foo"
                                    // import { x, y } from "foo"
                                    // import d, * as x from "foo"
                                    // import d, { x, y } from "foo"
                                    var isNakedImport = 209 /* ImportDeclaration */ && !node.importClause;
                                    if (!isNakedImport) {
                                        write("var ");
                                        write(getGeneratedNameForNode(node));
                                        write(" = ");
                                    }
                                }
                                emitRequire(ts.getExternalModuleName(node));
                                if (namespaceDeclaration && isDefaultImport(node)) {
                                    // import d, * as x from "foo"
                                    write(", ");
                                    emitModuleMemberName(namespaceDeclaration);
                                    write(" = ");
                                    write(getGeneratedNameForNode(node));
                                }
                                write(";");
                                emitEnd(node);
                                emitExportImportAssignments(node);
                                emitTrailingComments(node);
                            }
                            else {
                                if (isExportedImport) {
                                    emitModuleMemberName(namespaceDeclaration);
                                    write(" = ");
                                    emit(namespaceDeclaration.name);
                                    write(";");
                                }
                                else if (namespaceDeclaration && isDefaultImport(node)) {
                                    // import d, * as x from "foo"
                                    write("var ");
                                    emitModuleMemberName(namespaceDeclaration);
                                    write(" = ");
                                    write(getGeneratedNameForNode(node));
                                    write(";");
                                }
                                emitExportImportAssignments(node);
                            }
                        }
                    }
                    function emitImportEqualsDeclaration(node) {
                        if (ts.isExternalModuleImportEqualsDeclaration(node)) {
                            emitExternalImportDeclaration(node);
                            return;
                        }
                        // preserve old compiler's behavior: emit 'var' for import declaration (even if we do not consider them referenced) when
                        // - current file is not external module
                        // - import declaration is top level and target is value imported by entity name
                        if (resolver.isReferencedAliasDeclaration(node) ||
                            (!ts.isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) {
                            emitLeadingComments(node);
                            emitStart(node);
                            if (isES6ExportedDeclaration(node)) {
                                write("export ");
                                write("var ");
                            }
                            else if (!(node.flags & 1 /* Export */)) {
                                write("var ");
                            }
                            emitModuleMemberName(node);
                            write(" = ");
                            emit(node.moduleReference);
                            write(";");
                            emitEnd(node);
                            emitExportImportAssignments(node);
                            emitTrailingComments(node);
                        }
                    }
                    function emitExportDeclaration(node) {
                        if (languageVersion < 2 /* ES6 */) {
                            if (node.moduleSpecifier && (!node.exportClause || resolver.isValueAliasDeclaration(node))) {
                                emitStart(node);
                                var generatedName = getGeneratedNameForNode(node);
                                if (node.exportClause) {
                                    // export { x, y, ... } from "foo"
                                    if (compilerOptions.module !== 2 /* AMD */) {
                                        write("var ");
                                        write(generatedName);
                                        write(" = ");
                                        emitRequire(ts.getExternalModuleName(node));
                                        write(";");
                                    }
                                    for (var _a = 0, _b = node.exportClause.elements; _a < _b.length; _a++) {
                                        var specifier = _b[_a];
                                        if (resolver.isValueAliasDeclaration(specifier)) {
                                            writeLine();
                                            emitStart(specifier);
                                            emitContainingModuleName(specifier);
                                            write(".");
                                            emitNodeWithoutSourceMap(specifier.name);
                                            write(" = ");
                                            write(generatedName);
                                            write(".");
                                            emitNodeWithoutSourceMap(specifier.propertyName || specifier.name);
                                            write(";");
                                            emitEnd(specifier);
                                        }
                                    }
                                }
                                else {
                                    // export * from "foo"
                                    writeLine();
                                    write("__export(");
                                    if (compilerOptions.module !== 2 /* AMD */) {
                                        emitRequire(ts.getExternalModuleName(node));
                                    }
                                    else {
                                        write(generatedName);
                                    }
                                    write(");");
                                }
                                emitEnd(node);
                            }
                        }
                        else {
                            if (!node.exportClause || resolver.isValueAliasDeclaration(node)) {
                                emitStart(node);
                                write("export ");
                                if (node.exportClause) {
                                    // export { x, y, ... }
                                    write("{ ");
                                    emitExportOrImportSpecifierList(node.exportClause.elements, resolver.isValueAliasDeclaration);
                                    write(" }");
                                }
                                else {
                                    write("*");
                                }
                                if (node.moduleSpecifier) {
                                    write(" from ");
                                    emitNodeWithoutSourceMap(node.moduleSpecifier);
                                }
                                write(";");
                                emitEnd(node);
                            }
                        }
                    }
                    function emitExportOrImportSpecifierList(specifiers, shouldEmit) {
                        ts.Debug.assert(languageVersion >= 2 /* ES6 */);
                        var needsComma = false;
                        for (var _a = 0; _a < specifiers.length; _a++) {
                            var specifier = specifiers[_a];
                            if (shouldEmit(specifier)) {
                                if (needsComma) {
                                    write(", ");
                                }
                                emitStart(specifier);
                                if (specifier.propertyName) {
                                    emitNodeWithoutSourceMap(specifier.propertyName);
                                    write(" as ");
                                }
                                emitNodeWithoutSourceMap(specifier.name);
                                emitEnd(specifier);
                                needsComma = true;
                            }
                        }
                    }
                    function emitExportAssignment(node) {
                        if (!node.isExportEquals && resolver.isValueAliasDeclaration(node)) {
                            if (languageVersion >= 2 /* ES6 */) {
                                writeLine();
                                emitStart(node);
                                write("export default ");
                                var expression = node.expression;
                                emit(expression);
                                if (expression.kind !== 200 /* FunctionDeclaration */ &&
                                    expression.kind !== 201 /* ClassDeclaration */) {
                                    write(";");
                                }
                                emitEnd(node);
                            }
                            else {
                                writeLine();
                                emitStart(node);
                                emitContainingModuleName(node);
                                if (languageVersion === 0 /* ES3 */) {
                                    write("[\"default\"] = ");
                                }
                                else {
                                    write(".default = ");
                                }
                                emit(node.expression);
                                write(";");
                                emitEnd(node);
                            }
                        }
                    }
                    function collectExternalModuleInfo(sourceFile) {
                        externalImports = [];
                        exportSpecifiers = {};
                        exportEquals = undefined;
                        hasExportStars = false;
                        for (var _a = 0, _b = sourceFile.statements; _a < _b.length; _a++) {
                            var node = _b[_a];
                            switch (node.kind) {
                                case 209 /* ImportDeclaration */:
                                    if (!node.importClause ||
                                        resolver.isReferencedAliasDeclaration(node.importClause, true)) {
                                        // import "mod"
                                        // import x from "mod" where x is referenced
                                        // import * as x from "mod" where x is referenced
                                        // import { x, y } from "mod" where at least one import is referenced
                                        externalImports.push(node);
                                    }
                                    break;
                                case 208 /* ImportEqualsDeclaration */:
                                    if (node.moduleReference.kind === 219 /* ExternalModuleReference */ && resolver.isReferencedAliasDeclaration(node)) {
                                        // import x = require("mod") where x is referenced
                                        externalImports.push(node);
                                    }
                                    break;
                                case 215 /* ExportDeclaration */:
                                    if (node.moduleSpecifier) {
                                        if (!node.exportClause) {
                                            // export * from "mod"
                                            externalImports.push(node);
                                            hasExportStars = true;
                                        }
                                        else if (resolver.isValueAliasDeclaration(node)) {
                                            // export { x, y } from "mod" where at least one export is a value symbol
                                            externalImports.push(node);
                                        }
                                    }
                                    else {
                                        // export { x, y }
                                        for (var _c = 0, _d = node.exportClause.elements; _c < _d.length; _c++) {
                                            var specifier = _d[_c];
                                            var name_20 = (specifier.propertyName || specifier.name).text;
                                            (exportSpecifiers[name_20] || (exportSpecifiers[name_20] = [])).push(specifier);
                                        }
                                    }
                                    break;
                                case 214 /* ExportAssignment */:
                                    if (node.isExportEquals && !exportEquals) {
                                        // export = x
                                        exportEquals = node;
                                    }
                                    break;
                            }
                        }
                    }
                    function emitExportStarHelper() {
                        if (hasExportStars) {
                            writeLine();
                            write("function __export(m) {");
                            increaseIndent();
                            writeLine();
                            write("for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];");
                            decreaseIndent();
                            writeLine();
                            write("}");
                        }
                    }
                    function emitAMDDependencies(node, includeNonAmdDependencies) {
                        // An AMD define function has the following shape:
                        //     define(id?, dependencies?, factory);
                        //
                        // This has the shape of
                        //     define(name, ["module1", "module2"], function (module1Alias) {
                        // The location of the alias in the parameter list in the factory function needs to
                        // match the position of the module name in the dependency list.
                        //
                        // To ensure this is true in cases of modules with no aliases, e.g.:
                        // `import "module"` or `<amd-dependency path= "a.css" />`
                        // we need to add modules without alias names to the end of the dependencies list
                        var aliasedModuleNames = []; // names of modules with corresponding parameter in the
                        // factory function.
                        var unaliasedModuleNames = []; // names of modules with no corresponding parameters in
                        // factory function.
                        var importAliasNames = []; // names of the parameters in the factory function; these
                        // parameters need to match the indexes of the corresponding
                        // module names in aliasedModuleNames.
                        // Fill in amd-dependency tags
                        for (var _a = 0, _b = node.amdDependencies; _a < _b.length; _a++) {
                            var amdDependency = _b[_a];
                            if (amdDependency.name) {
                                aliasedModuleNames.push("\"" + amdDependency.path + "\"");
                                importAliasNames.push(amdDependency.name);
                            }
                            else {
                                unaliasedModuleNames.push("\"" + amdDependency.path + "\"");
                            }
                        }
                        for (var _c = 0; _c < externalImports.length; _c++) {
                            var importNode = externalImports[_c];
                            // Find the name of the external module
                            var externalModuleName = "";
                            var moduleName = ts.getExternalModuleName(importNode);
                            if (moduleName.kind === 8 /* StringLiteral */) {
                                externalModuleName = getLiteralText(moduleName);
                            }
                            // Find the name of the module alias, if there is one
                            var importAliasName = void 0;
                            var namespaceDeclaration = getNamespaceDeclarationNode(importNode);
                            if (namespaceDeclaration && !isDefaultImport(importNode)) {
                                importAliasName = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name);
                            }
                            else {
                                importAliasName = getGeneratedNameForNode(importNode);
                            }
                            if (includeNonAmdDependencies && importAliasName) {
                                aliasedModuleNames.push(externalModuleName);
                                importAliasNames.push(importAliasName);
                            }
                            else {
                                unaliasedModuleNames.push(externalModuleName);
                            }
                        }
                        write("[\"require\", \"exports\"");
                        if (aliasedModuleNames.length) {
                            write(", ");
                            write(aliasedModuleNames.join(", "));
                        }
                        if (unaliasedModuleNames.length) {
                            write(", ");
                            write(unaliasedModuleNames.join(", "));
                        }
                        write("], function (require, exports");
                        if (importAliasNames.length) {
                            write(", ");
                            write(importAliasNames.join(", "));
                        }
                    }
                    function emitAMDModule(node, startIndex) {
                        collectExternalModuleInfo(node);
                        writeLine();
                        write("define(");
                        if (node.amdModuleName) {
                            write("\"" + node.amdModuleName + "\", ");
                        }
                        emitAMDDependencies(node, true);
                        write(") {");
                        increaseIndent();
                        emitExportStarHelper();
                        emitCaptureThisForNodeIfNecessary(node);
                        emitLinesStartingAt(node.statements, startIndex);
                        emitTempDeclarations(true);
                        emitExportEquals(true);
                        decreaseIndent();
                        writeLine();
                        write("});");
                    }
                    function emitCommonJSModule(node, startIndex) {
                        collectExternalModuleInfo(node);
                        emitExportStarHelper();
                        emitCaptureThisForNodeIfNecessary(node);
                        emitLinesStartingAt(node.statements, startIndex);
                        emitTempDeclarations(true);
                        emitExportEquals(false);
                    }
                    function emitUMDModule(node, startIndex) {
                        collectExternalModuleInfo(node);
                        // Module is detected first to support Browserify users that load into a browser with an AMD loader
                        writeLines("(function (deps, factory) {\n    if (typeof module === 'object' && typeof module.exports === 'object') {\n        var v = factory(require, exports); if (v !== undefined) module.exports = v;\n    }\n    else if (typeof define === 'function' && define.amd) {\n        define(deps, factory);\n    }\n})(");
                        emitAMDDependencies(node, false);
                        write(") {");
                        increaseIndent();
                        emitExportStarHelper();
                        emitCaptureThisForNodeIfNecessary(node);
                        emitLinesStartingAt(node.statements, startIndex);
                        emitTempDeclarations(true);
                        emitExportEquals(true);
                        decreaseIndent();
                        writeLine();
                        write("});");
                    }
                    function emitES6Module(node, startIndex) {
                        externalImports = undefined;
                        exportSpecifiers = undefined;
                        exportEquals = undefined;
                        hasExportStars = false;
                        emitCaptureThisForNodeIfNecessary(node);
                        emitLinesStartingAt(node.statements, startIndex);
                        emitTempDeclarations(true);
                        // Emit exportDefault if it exists will happen as part 
                        // or normal statement emit.
                    }
                    function emitExportEquals(emitAsReturn) {
                        if (exportEquals && resolver.isValueAliasDeclaration(exportEquals)) {
                            writeLine();
                            emitStart(exportEquals);
                            write(emitAsReturn ? "return " : "module.exports = ");
                            emit(exportEquals.expression);
                            write(";");
                            emitEnd(exportEquals);
                        }
                    }
                    function emitDirectivePrologues(statements, startWithNewLine) {
                        for (var i = 0; i < statements.length; ++i) {
                            if (ts.isPrologueDirective(statements[i])) {
                                if (startWithNewLine || i > 0) {
                                    writeLine();
                                }
                                emit(statements[i]);
                            }
                            else {
                                // return index of the first non prologue directive
                                return i;
                            }
                        }
                        return statements.length;
                    }
                    function writeLines(text) {
                        var lines = text.split(/\r\n|\r|\n/g);
                        for (var i = 0; i < lines.length; ++i) {
                            var line = lines[i];
                            if (line.length) {
                                writeLine();
                                write(line);
                            }
                        }
                    }
                    function emitSourceFileNode(node) {
                        // Start new file on new line
                        writeLine();
                        emitDetachedComments(node);
                        // emit prologue directives prior to __extends
                        var startIndex = emitDirectivePrologues(node.statements, false);
                        // Only Emit __extends function when target ES5.
                        // For target ES6 and above, we can emit classDeclaration as is.
                        if ((languageVersion < 2 /* ES6 */) && (!extendsEmitted && resolver.getNodeCheckFlags(node) & 8 /* EmitExtends */)) {
                            writeLines(extendsHelper);
                            extendsEmitted = true;
                        }
                        if (!decorateEmitted && resolver.getNodeCheckFlags(node) & 512 /* EmitDecorate */) {
                            writeLines(decorateHelper);
                            if (compilerOptions.emitDecoratorMetadata) {
                                writeLines(metadataHelper);
                            }
                            decorateEmitted = true;
                        }
                        if (!paramEmitted && resolver.getNodeCheckFlags(node) & 1024 /* EmitParam */) {
                            writeLines(paramHelper);
                            paramEmitted = true;
                        }
                        if (ts.isExternalModule(node)) {
                            if (languageVersion >= 2 /* ES6 */) {
                                emitES6Module(node, startIndex);
                            }
                            else if (compilerOptions.module === 2 /* AMD */) {
                                emitAMDModule(node, startIndex);
                            }
                            else if (compilerOptions.module === 3 /* UMD */) {
                                emitUMDModule(node, startIndex);
                            }
                            else {
                                emitCommonJSModule(node, startIndex);
                            }
                        }
                        else {
                            externalImports = undefined;
                            exportSpecifiers = undefined;
                            exportEquals = undefined;
                            hasExportStars = false;
                            emitCaptureThisForNodeIfNecessary(node);
                            emitLinesStartingAt(node.statements, startIndex);
                            emitTempDeclarations(true);
                        }
                        emitLeadingComments(node.endOfFileToken);
                    }
                    function emitNodeWithoutSourceMap(node, allowGeneratedIdentifiers) {
                        if (!node) {
                            return;
                        }
                        if (node.flags & 2 /* Ambient */) {
                            return emitOnlyPinnedOrTripleSlashComments(node);
                        }
                        var emitComments = shouldEmitLeadingAndTrailingComments(node);
                        if (emitComments) {
                            emitLeadingComments(node);
                        }
                        emitJavaScriptWorker(node, allowGeneratedIdentifiers);
                        if (emitComments) {
                            emitTrailingComments(node);
                        }
                    }
                    function shouldEmitLeadingAndTrailingComments(node) {
                        switch (node.kind) {
                            // All of these entities are emitted in a specialized fashion.  As such, we allow
                            // the specialized methods for each to handle the comments on the nodes.
                            case 202 /* InterfaceDeclaration */:
                            case 200 /* FunctionDeclaration */:
                            case 209 /* ImportDeclaration */:
                            case 208 /* ImportEqualsDeclaration */:
                            case 203 /* TypeAliasDeclaration */:
                            case 214 /* ExportAssignment */:
                                return false;
                            case 205 /* ModuleDeclaration */:
                                // Only emit the leading/trailing comments for a module if we're actually
                                // emitting the module as well.
                                return shouldEmitModuleDeclaration(node);
                            case 204 /* EnumDeclaration */:
                                // Only emit the leading/trailing comments for an enum if we're actually
                                // emitting the module as well.
                                return shouldEmitEnumDeclaration(node);
                        }
                        // If this is the expression body of an arrow function that we're down-leveling, 
                        // then we don't want to emit comments when we emit the body.  It will have already
                        // been taken care of when we emitted the 'return' statement for the function
                        // expression body.
                        if (node.kind !== 179 /* Block */ &&
                            node.parent &&
                            node.parent.kind === 163 /* ArrowFunction */ &&
                            node.parent.body === node &&
                            compilerOptions.target <= 1 /* ES5 */) {
                            return false;
                        }
                        // Emit comments for everything else.
                        return true;
                    }
                    function emitJavaScriptWorker(node, allowGeneratedIdentifiers) {
                        if (allowGeneratedIdentifiers === void 0) { allowGeneratedIdentifiers = true; }
                        // Check if the node can be emitted regardless of the ScriptTarget
                        switch (node.kind) {
                            case 65 /* Identifier */:
                                return emitIdentifier(node, allowGeneratedIdentifiers);
                            case 129 /* Parameter */:
                                return emitParameter(node);
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                                return emitMethod(node);
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                                return emitAccessor(node);
                            case 93 /* ThisKeyword */:
                                return emitThis(node);
                            case 91 /* SuperKeyword */:
                                return emitSuper(node);
                            case 89 /* NullKeyword */:
                                return write("null");
                            case 95 /* TrueKeyword */:
                                return write("true");
                            case 80 /* FalseKeyword */:
                                return write("false");
                            case 7 /* NumericLiteral */:
                            case 8 /* StringLiteral */:
                            case 9 /* RegularExpressionLiteral */:
                            case 10 /* NoSubstitutionTemplateLiteral */:
                            case 11 /* TemplateHead */:
                            case 12 /* TemplateMiddle */:
                            case 13 /* TemplateTail */:
                                return emitLiteral(node);
                            case 171 /* TemplateExpression */:
                                return emitTemplateExpression(node);
                            case 176 /* TemplateSpan */:
                                return emitTemplateSpan(node);
                            case 126 /* QualifiedName */:
                                return emitQualifiedName(node);
                            case 150 /* ObjectBindingPattern */:
                                return emitObjectBindingPattern(node);
                            case 151 /* ArrayBindingPattern */:
                                return emitArrayBindingPattern(node);
                            case 152 /* BindingElement */:
                                return emitBindingElement(node);
                            case 153 /* ArrayLiteralExpression */:
                                return emitArrayLiteral(node);
                            case 154 /* ObjectLiteralExpression */:
                                return emitObjectLiteral(node);
                            case 224 /* PropertyAssignment */:
                                return emitPropertyAssignment(node);
                            case 225 /* ShorthandPropertyAssignment */:
                                return emitShorthandPropertyAssignment(node);
                            case 127 /* ComputedPropertyName */:
                                return emitComputedPropertyName(node);
                            case 155 /* PropertyAccessExpression */:
                                return emitPropertyAccess(node);
                            case 156 /* ElementAccessExpression */:
                                return emitIndexedAccess(node);
                            case 157 /* CallExpression */:
                                return emitCallExpression(node);
                            case 158 /* NewExpression */:
                                return emitNewExpression(node);
                            case 159 /* TaggedTemplateExpression */:
                                return emitTaggedTemplateExpression(node);
                            case 160 /* TypeAssertionExpression */:
                                return emit(node.expression);
                            case 161 /* ParenthesizedExpression */:
                                return emitParenExpression(node);
                            case 200 /* FunctionDeclaration */:
                            case 162 /* FunctionExpression */:
                            case 163 /* ArrowFunction */:
                                return emitFunctionDeclaration(node);
                            case 164 /* DeleteExpression */:
                                return emitDeleteExpression(node);
                            case 165 /* TypeOfExpression */:
                                return emitTypeOfExpression(node);
                            case 166 /* VoidExpression */:
                                return emitVoidExpression(node);
                            case 167 /* PrefixUnaryExpression */:
                                return emitPrefixUnaryExpression(node);
                            case 168 /* PostfixUnaryExpression */:
                                return emitPostfixUnaryExpression(node);
                            case 169 /* BinaryExpression */:
                                return emitBinaryExpression(node);
                            case 170 /* ConditionalExpression */:
                                return emitConditionalExpression(node);
                            case 173 /* SpreadElementExpression */:
                                return emitSpreadElementExpression(node);
                            case 172 /* YieldExpression */:
                                return emitYieldExpression(node);
                            case 175 /* OmittedExpression */:
                                return;
                            case 179 /* Block */:
                            case 206 /* ModuleBlock */:
                                return emitBlock(node);
                            case 180 /* VariableStatement */:
                                return emitVariableStatement(node);
                            case 181 /* EmptyStatement */:
                                return write(";");
                            case 182 /* ExpressionStatement */:
                                return emitExpressionStatement(node);
                            case 183 /* IfStatement */:
                                return emitIfStatement(node);
                            case 184 /* DoStatement */:
                                return emitDoStatement(node);
                            case 185 /* WhileStatement */:
                                return emitWhileStatement(node);
                            case 186 /* ForStatement */:
                                return emitForStatement(node);
                            case 188 /* ForOfStatement */:
                            case 187 /* ForInStatement */:
                                return emitForInOrForOfStatement(node);
                            case 189 /* ContinueStatement */:
                            case 190 /* BreakStatement */:
                                return emitBreakOrContinueStatement(node);
                            case 191 /* ReturnStatement */:
                                return emitReturnStatement(node);
                            case 192 /* WithStatement */:
                                return emitWithStatement(node);
                            case 193 /* SwitchStatement */:
                                return emitSwitchStatement(node);
                            case 220 /* CaseClause */:
                            case 221 /* DefaultClause */:
                                return emitCaseOrDefaultClause(node);
                            case 194 /* LabeledStatement */:
                                return emitLabelledStatement(node);
                            case 195 /* ThrowStatement */:
                                return emitThrowStatement(node);
                            case 196 /* TryStatement */:
                                return emitTryStatement(node);
                            case 223 /* CatchClause */:
                                return emitCatchClause(node);
                            case 197 /* DebuggerStatement */:
                                return emitDebuggerStatement(node);
                            case 198 /* VariableDeclaration */:
                                return emitVariableDeclaration(node);
                            case 174 /* ClassExpression */:
                                return emitClassExpression(node);
                            case 201 /* ClassDeclaration */:
                                return emitClassDeclaration(node);
                            case 202 /* InterfaceDeclaration */:
                                return emitInterfaceDeclaration(node);
                            case 204 /* EnumDeclaration */:
                                return emitEnumDeclaration(node);
                            case 226 /* EnumMember */:
                                return emitEnumMember(node);
                            case 205 /* ModuleDeclaration */:
                                return emitModuleDeclaration(node);
                            case 209 /* ImportDeclaration */:
                                return emitImportDeclaration(node);
                            case 208 /* ImportEqualsDeclaration */:
                                return emitImportEqualsDeclaration(node);
                            case 215 /* ExportDeclaration */:
                                return emitExportDeclaration(node);
                            case 214 /* ExportAssignment */:
                                return emitExportAssignment(node);
                            case 227 /* SourceFile */:
                                return emitSourceFileNode(node);
                        }
                    }
                    function hasDetachedComments(pos) {
                        return detachedCommentsInfo !== undefined && detachedCommentsInfo[detachedCommentsInfo.length - 1].nodePos === pos;
                    }
                    function getLeadingCommentsWithoutDetachedComments() {
                        // get the leading comments from detachedPos
                        var leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, detachedCommentsInfo[detachedCommentsInfo.length - 1].detachedCommentEndPos);
                        if (detachedCommentsInfo.length - 1) {
                            detachedCommentsInfo.pop();
                        }
                        else {
                            detachedCommentsInfo = undefined;
                        }
                        return leadingComments;
                    }
                    function filterComments(ranges, onlyPinnedOrTripleSlashComments) {
                        // If we're removing comments, then we want to strip out all but the pinned or
                        // triple slash comments.
                        if (ranges && onlyPinnedOrTripleSlashComments) {
                            ranges = ts.filter(ranges, isPinnedOrTripleSlashComment);
                            if (ranges.length === 0) {
                                return undefined;
                            }
                        }
                        return ranges;
                    }
                    function getLeadingCommentsToEmit(node) {
                        // Emit the leading comments only if the parent's pos doesn't match because parent should take care of emitting these comments
                        if (node.parent) {
                            if (node.parent.kind === 227 /* SourceFile */ || node.pos !== node.parent.pos) {
                                if (hasDetachedComments(node.pos)) {
                                    // get comments without detached comments
                                    return getLeadingCommentsWithoutDetachedComments();
                                }
                                else {
                                    // get the leading comments from the node
                                    return ts.getLeadingCommentRangesOfNode(node, currentSourceFile);
                                }
                            }
                        }
                    }
                    function getTrailingCommentsToEmit(node) {
                        // Emit the trailing comments only if the parent's pos doesn't match because parent should take care of emitting these comments
                        if (node.parent) {
                            if (node.parent.kind === 227 /* SourceFile */ || node.end !== node.parent.end) {
                                return ts.getTrailingCommentRanges(currentSourceFile.text, node.end);
                            }
                        }
                    }
                    function emitOnlyPinnedOrTripleSlashComments(node) {
                        emitLeadingCommentsWorker(node, true);
                    }
                    function emitLeadingComments(node) {
                        return emitLeadingCommentsWorker(node, compilerOptions.removeComments);
                    }
                    function emitLeadingCommentsWorker(node, onlyPinnedOrTripleSlashComments) {
                        // If the caller only wants pinned or triple slash comments, then always filter
                        // down to that set.  Otherwise, filter based on the current compiler options.
                        var leadingComments = filterComments(getLeadingCommentsToEmit(node), onlyPinnedOrTripleSlashComments);
                        ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments);
                        // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
                        ts.emitComments(currentSourceFile, writer, leadingComments, true, newLine, writeComment);
                    }
                    function emitTrailingComments(node) {
                        // Emit the trailing comments only if the parent's end doesn't match
                        var trailingComments = filterComments(getTrailingCommentsToEmit(node), compilerOptions.removeComments);
                        // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
                        ts.emitComments(currentSourceFile, writer, trailingComments, false, newLine, writeComment);
                    }
                    function emitLeadingCommentsOfPosition(pos) {
                        var leadingComments;
                        if (hasDetachedComments(pos)) {
                            // get comments without detached comments
                            leadingComments = getLeadingCommentsWithoutDetachedComments();
                        }
                        else {
                            // get the leading comments from the node
                            leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, pos);
                        }
                        leadingComments = filterComments(leadingComments, compilerOptions.removeComments);
                        ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, { pos: pos, end: pos }, leadingComments);
                        // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
                        ts.emitComments(currentSourceFile, writer, leadingComments, true, newLine, writeComment);
                    }
                    function emitDetachedComments(node) {
                        var leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos);
                        if (leadingComments) {
                            var detachedComments = [];
                            var lastComment;
                            ts.forEach(leadingComments, function (comment) {
                                if (lastComment) {
                                    var lastCommentLine = ts.getLineOfLocalPosition(currentSourceFile, lastComment.end);
                                    var commentLine = ts.getLineOfLocalPosition(currentSourceFile, comment.pos);
                                    if (commentLine >= lastCommentLine + 2) {
                                        // There was a blank line between the last comment and this comment.  This
                                        // comment is not part of the copyright comments.  Return what we have so
                                        // far.
                                        return detachedComments;
                                    }
                                }
                                detachedComments.push(comment);
                                lastComment = comment;
                            });
                            if (detachedComments.length) {
                                // All comments look like they could have been part of the copyright header.  Make
                                // sure there is at least one blank line between it and the node.  If not, it's not
                                // a copyright header.
                                var lastCommentLine = ts.getLineOfLocalPosition(currentSourceFile, detachedComments[detachedComments.length - 1].end);
                                var nodeLine = ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node.pos));
                                if (nodeLine >= lastCommentLine + 2) {
                                    // Valid detachedComments
                                    ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments);
                                    ts.emitComments(currentSourceFile, writer, detachedComments, true, newLine, writeComment);
                                    var currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: detachedComments[detachedComments.length - 1].end };
                                    if (detachedCommentsInfo) {
                                        detachedCommentsInfo.push(currentDetachedCommentInfo);
                                    }
                                    else {
                                        detachedCommentsInfo = [currentDetachedCommentInfo];
                                    }
                                }
                            }
                        }
                    }
                    function isPinnedOrTripleSlashComment(comment) {
                        if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 42 /* asterisk */) {
                            return currentSourceFile.text.charCodeAt(comment.pos + 2) === 33 /* exclamation */;
                        }
                        else if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 47 /* slash */ &&
                            comment.pos + 2 < comment.end &&
                            currentSourceFile.text.charCodeAt(comment.pos + 2) === 47 /* slash */ &&
                            currentSourceFile.text.substring(comment.pos, comment.end).match(ts.fullTripleSlashReferencePathRegEx)) {
                            return true;
                        }
                    }
                }
                function emitFile(jsFilePath, sourceFile) {
                    emitJavaScript(jsFilePath, sourceFile);
                    if (compilerOptions.declaration) {
                        ts.writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics);
                    }
                }
            }
            ts.emitFiles = emitFiles;
        })(ts || (ts = {}));
        /// <reference path="sys.ts" />
        /// <reference path="emitter.ts" />
        var ts;
        (function (ts) {
            /* @internal */ ts.programTime = 0;
            /* @internal */ ts.emitTime = 0;
            /* @internal */ ts.ioReadTime = 0;
            /* @internal */ ts.ioWriteTime = 0;
            /** The version of the TypeScript compiler release */
            ts.version = "1.5.0";
            function findConfigFile(searchPath) {
                var fileName = "tsconfig.json";
                while (true) {
                    if (ts.sys.fileExists(fileName)) {
                        return fileName;
                    }
                    var parentPath = ts.getDirectoryPath(searchPath);
                    if (parentPath === searchPath) {
                        break;
                    }
                    searchPath = parentPath;
                    fileName = "../" + fileName;
                }
                return undefined;
            }
            ts.findConfigFile = findConfigFile;
            function createCompilerHost(options, setParentNodes) {
                var currentDirectory;
                var existingDirectories = {};
                function getCanonicalFileName(fileName) {
                    // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
                    // otherwise use toLowerCase as a canonical form.
                    return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
                }
                // returned by CScript sys environment
                var unsupportedFileEncodingErrorCode = -2147024809;
                function getSourceFile(fileName, languageVersion, onError) {
                    var text;
                    try {
                        var start = new Date().getTime();
                        text = ts.sys.readFile(fileName, options.charset);
                        ts.ioReadTime += new Date().getTime() - start;
                    }
                    catch (e) {
                        if (onError) {
                            onError(e.number === unsupportedFileEncodingErrorCode
                                ? ts.createCompilerDiagnostic(ts.Diagnostics.Unsupported_file_encoding).messageText
                                : e.message);
                        }
                        text = "";
                    }
                    return text !== undefined ? ts.createSourceFile(fileName, text, languageVersion, setParentNodes) : undefined;
                }
                function directoryExists(directoryPath) {
                    if (ts.hasProperty(existingDirectories, directoryPath)) {
                        return true;
                    }
                    if (ts.sys.directoryExists(directoryPath)) {
                        existingDirectories[directoryPath] = true;
                        return true;
                    }
                    return false;
                }
                function ensureDirectoriesExist(directoryPath) {
                    if (directoryPath.length > ts.getRootLength(directoryPath) && !directoryExists(directoryPath)) {
                        var parentDirectory = ts.getDirectoryPath(directoryPath);
                        ensureDirectoriesExist(parentDirectory);
                        ts.sys.createDirectory(directoryPath);
                    }
                }
                function writeFile(fileName, data, writeByteOrderMark, onError) {
                    try {
                        var start = new Date().getTime();
                        ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName)));
                        ts.sys.writeFile(fileName, data, writeByteOrderMark);
                        ts.ioWriteTime += new Date().getTime() - start;
                    }
                    catch (e) {
                        if (onError) {
                            onError(e.message);
                        }
                    }
                }
                return {
                    getSourceFile: getSourceFile,
                    getDefaultLibFileName: function (options) { return ts.combinePaths(ts.getDirectoryPath(ts.normalizePath(ts.sys.getExecutingFilePath())), ts.getDefaultLibFileName(options)); },
                    writeFile: writeFile,
                    getCurrentDirectory: function () { return currentDirectory || (currentDirectory = ts.sys.getCurrentDirectory()); },
                    useCaseSensitiveFileNames: function () { return ts.sys.useCaseSensitiveFileNames; },
                    getCanonicalFileName: getCanonicalFileName,
                    getNewLine: function () { return ts.sys.newLine; }
                };
            }
            ts.createCompilerHost = createCompilerHost;
            function getPreEmitDiagnostics(program) {
                var diagnostics = program.getSyntacticDiagnostics().concat(program.getGlobalDiagnostics()).concat(program.getSemanticDiagnostics());
                if (program.getCompilerOptions().declaration) {
                    diagnostics.concat(program.getDeclarationDiagnostics());
                }
                return ts.sortAndDeduplicateDiagnostics(diagnostics);
            }
            ts.getPreEmitDiagnostics = getPreEmitDiagnostics;
            function flattenDiagnosticMessageText(messageText, newLine) {
                if (typeof messageText === "string") {
                    return messageText;
                }
                else {
                    var diagnosticChain = messageText;
                    var result = "";
                    var indent = 0;
                    while (diagnosticChain) {
                        if (indent) {
                            result += newLine;
                            for (var i = 0; i < indent; i++) {
                                result += "  ";
                            }
                        }
                        result += diagnosticChain.messageText;
                        indent++;
                        diagnosticChain = diagnosticChain.next;
                    }
                    return result;
                }
            }
            ts.flattenDiagnosticMessageText = flattenDiagnosticMessageText;
            function createProgram(rootNames, options, host) {
                var program;
                var files = [];
                var filesByName = {};
                var diagnostics = ts.createDiagnosticCollection();
                var seenNoDefaultLib = options.noLib;
                var commonSourceDirectory;
                var diagnosticsProducingTypeChecker;
                var noDiagnosticsTypeChecker;
                var start = new Date().getTime();
                host = host || createCompilerHost(options);
                ts.forEach(rootNames, function (name) { return processRootFile(name, false); });
                if (!seenNoDefaultLib) {
                    processRootFile(host.getDefaultLibFileName(options), true);
                }
                verifyCompilerOptions();
                ts.programTime += new Date().getTime() - start;
                program = {
                    getSourceFile: getSourceFile,
                    getSourceFiles: function () { return files; },
                    getCompilerOptions: function () { return options; },
                    getSyntacticDiagnostics: getSyntacticDiagnostics,
                    getGlobalDiagnostics: getGlobalDiagnostics,
                    getSemanticDiagnostics: getSemanticDiagnostics,
                    getDeclarationDiagnostics: getDeclarationDiagnostics,
                    getTypeChecker: getTypeChecker,
                    getDiagnosticsProducingTypeChecker: getDiagnosticsProducingTypeChecker,
                    getCommonSourceDirectory: function () { return commonSourceDirectory; },
                    emit: emit,
                    getCurrentDirectory: function () { return host.getCurrentDirectory(); },
                    getNodeCount: function () { return getDiagnosticsProducingTypeChecker().getNodeCount(); },
                    getIdentifierCount: function () { return getDiagnosticsProducingTypeChecker().getIdentifierCount(); },
                    getSymbolCount: function () { return getDiagnosticsProducingTypeChecker().getSymbolCount(); },
                    getTypeCount: function () { return getDiagnosticsProducingTypeChecker().getTypeCount(); }
                };
                return program;
                function getEmitHost(writeFileCallback) {
                    return {
                        getCanonicalFileName: function (fileName) { return host.getCanonicalFileName(fileName); },
                        getCommonSourceDirectory: program.getCommonSourceDirectory,
                        getCompilerOptions: program.getCompilerOptions,
                        getCurrentDirectory: function () { return host.getCurrentDirectory(); },
                        getNewLine: function () { return host.getNewLine(); },
                        getSourceFile: program.getSourceFile,
                        getSourceFiles: program.getSourceFiles,
                        writeFile: writeFileCallback || (function (fileName, data, writeByteOrderMark, onError) { return host.writeFile(fileName, data, writeByteOrderMark, onError); })
                    };
                }
                function getDiagnosticsProducingTypeChecker() {
                    return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = ts.createTypeChecker(program, true));
                }
                function getTypeChecker() {
                    return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = ts.createTypeChecker(program, false));
                }
                function emit(sourceFile, writeFileCallback) {
                    // If the noEmitOnError flag is set, then check if we have any errors so far.  If so,
                    // immediately bail out.
                    if (options.noEmitOnError && getPreEmitDiagnostics(this).length > 0) {
                        return { diagnostics: [], sourceMaps: undefined, emitSkipped: true };
                    }
                    // Create the emit resolver outside of the "emitTime" tracking code below.  That way
                    // any cost associated with it (like type checking) are appropriate associated with
                    // the type-checking counter.
                    var emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile);
                    var start = new Date().getTime();
                    var emitResult = ts.emitFiles(emitResolver, getEmitHost(writeFileCallback), sourceFile);
                    ts.emitTime += new Date().getTime() - start;
                    return emitResult;
                }
                function getSourceFile(fileName) {
                    fileName = host.getCanonicalFileName(fileName);
                    return ts.hasProperty(filesByName, fileName) ? filesByName[fileName] : undefined;
                }
                function getDiagnosticsHelper(sourceFile, getDiagnostics) {
                    if (sourceFile) {
                        return getDiagnostics(sourceFile);
                    }
                    var allDiagnostics = [];
                    ts.forEach(program.getSourceFiles(), function (sourceFile) {
                        ts.addRange(allDiagnostics, getDiagnostics(sourceFile));
                    });
                    return ts.sortAndDeduplicateDiagnostics(allDiagnostics);
                }
                function getSyntacticDiagnostics(sourceFile) {
                    return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile);
                }
                function getSemanticDiagnostics(sourceFile) {
                    return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile);
                }
                function getDeclarationDiagnostics(sourceFile) {
                    return getDiagnosticsHelper(sourceFile, getDeclarationDiagnosticsForFile);
                }
                function getSyntacticDiagnosticsForFile(sourceFile) {
                    return sourceFile.parseDiagnostics;
                }
                function getSemanticDiagnosticsForFile(sourceFile) {
                    var typeChecker = getDiagnosticsProducingTypeChecker();
                    ts.Debug.assert(!!sourceFile.bindDiagnostics);
                    var bindDiagnostics = sourceFile.bindDiagnostics;
                    var checkDiagnostics = typeChecker.getDiagnostics(sourceFile);
                    var programDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName);
                    return bindDiagnostics.concat(checkDiagnostics).concat(programDiagnostics);
                }
                function getDeclarationDiagnosticsForFile(sourceFile) {
                    if (!ts.isDeclarationFile(sourceFile)) {
                        var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile);
                        // Don't actually write any files since we're just getting diagnostics.
                        var writeFile = function () { };
                        return ts.getDeclarationDiagnostics(getEmitHost(writeFile), resolver, sourceFile);
                    }
                }
                function getGlobalDiagnostics() {
                    var typeChecker = getDiagnosticsProducingTypeChecker();
                    var allDiagnostics = [];
                    ts.addRange(allDiagnostics, typeChecker.getGlobalDiagnostics());
                    ts.addRange(allDiagnostics, diagnostics.getGlobalDiagnostics());
                    return ts.sortAndDeduplicateDiagnostics(allDiagnostics);
                }
                function hasExtension(fileName) {
                    return ts.getBaseFileName(fileName).indexOf(".") >= 0;
                }
                function processRootFile(fileName, isDefaultLib) {
                    processSourceFile(ts.normalizePath(fileName), isDefaultLib);
                }
                function processSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd) {
                    var start;
                    var length;
                    if (refEnd !== undefined && refPos !== undefined) {
                        start = refPos;
                        length = refEnd - refPos;
                    }
                    var diagnostic;
                    if (hasExtension(fileName)) {
                        if (!options.allowNonTsExtensions && !ts.fileExtensionIs(host.getCanonicalFileName(fileName), ".ts")) {
                            diagnostic = ts.Diagnostics.File_0_must_have_extension_ts_or_d_ts;
                        }
                        else if (!findSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd)) {
                            diagnostic = ts.Diagnostics.File_0_not_found;
                        }
                        else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) {
                            diagnostic = ts.Diagnostics.A_file_cannot_have_a_reference_to_itself;
                        }
                    }
                    else {
                        if (options.allowNonTsExtensions && !findSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd)) {
                            diagnostic = ts.Diagnostics.File_0_not_found;
                        }
                        else if (!findSourceFile(fileName + ".ts", isDefaultLib, refFile, refPos, refEnd) && !findSourceFile(fileName + ".d.ts", isDefaultLib, refFile, refPos, refEnd)) {
                            diagnostic = ts.Diagnostics.File_0_not_found;
                            fileName += ".ts";
                        }
                    }
                    if (diagnostic) {
                        if (refFile) {
                            diagnostics.add(ts.createFileDiagnostic(refFile, start, length, diagnostic, fileName));
                        }
                        else {
                            diagnostics.add(ts.createCompilerDiagnostic(diagnostic, fileName));
                        }
                    }
                }
                // Get source file from normalized fileName
                function findSourceFile(fileName, isDefaultLib, refFile, refStart, refLength) {
                    var canonicalName = host.getCanonicalFileName(fileName);
                    if (ts.hasProperty(filesByName, canonicalName)) {
                        // We've already looked for this file, use cached result
                        return getSourceFileFromCache(fileName, canonicalName, false);
                    }
                    else {
                        var normalizedAbsolutePath = ts.getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
                        var canonicalAbsolutePath = host.getCanonicalFileName(normalizedAbsolutePath);
                        if (ts.hasProperty(filesByName, canonicalAbsolutePath)) {
                            return getSourceFileFromCache(normalizedAbsolutePath, canonicalAbsolutePath, true);
                        }
                        // We haven't looked for this file, do so now and cache result
                        var file = filesByName[canonicalName] = host.getSourceFile(fileName, options.target, function (hostErrorMessage) {
                            if (refFile) {
                                diagnostics.add(ts.createFileDiagnostic(refFile, refStart, refLength, ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
                            }
                            else {
                                diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
                            }
                        });
                        if (file) {
                            seenNoDefaultLib = seenNoDefaultLib || file.hasNoDefaultLib;
                            // Set the source file for normalized absolute path
                            filesByName[canonicalAbsolutePath] = file;
                            if (!options.noResolve) {
                                var basePath = ts.getDirectoryPath(fileName);
                                processReferencedFiles(file, basePath);
                                processImportedModules(file, basePath);
                            }
                            if (isDefaultLib) {
                                files.unshift(file);
                            }
                            else {
                                files.push(file);
                            }
                        }
                        return file;
                    }
                    function getSourceFileFromCache(fileName, canonicalName, useAbsolutePath) {
                        var file = filesByName[canonicalName];
                        if (file && host.useCaseSensitiveFileNames()) {
                            var sourceFileName = useAbsolutePath ? ts.getNormalizedAbsolutePath(file.fileName, host.getCurrentDirectory()) : file.fileName;
                            if (canonicalName !== sourceFileName) {
                                diagnostics.add(ts.createFileDiagnostic(refFile, refStart, refLength, ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, sourceFileName));
                            }
                        }
                        return file;
                    }
                }
                function processReferencedFiles(file, basePath) {
                    ts.forEach(file.referencedFiles, function (ref) {
                        var referencedFileName = ts.isRootedDiskPath(ref.fileName) ? ref.fileName : ts.combinePaths(basePath, ref.fileName);
                        processSourceFile(ts.normalizePath(referencedFileName), false, file, ref.pos, ref.end);
                    });
                }
                function processImportedModules(file, basePath) {
                    ts.forEach(file.statements, function (node) {
                        if (node.kind === 209 /* ImportDeclaration */ || node.kind === 208 /* ImportEqualsDeclaration */ || node.kind === 215 /* ExportDeclaration */) {
                            var moduleNameExpr = ts.getExternalModuleName(node);
                            if (moduleNameExpr && moduleNameExpr.kind === 8 /* StringLiteral */) {
                                var moduleNameText = moduleNameExpr.text;
                                if (moduleNameText) {
                                    var searchPath = basePath;
                                    while (true) {
                                        var searchName = ts.normalizePath(ts.combinePaths(searchPath, moduleNameText));
                                        if (findModuleSourceFile(searchName + ".ts", moduleNameExpr) || findModuleSourceFile(searchName + ".d.ts", moduleNameExpr)) {
                                            break;
                                        }
                                        var parentPath = ts.getDirectoryPath(searchPath);
                                        if (parentPath === searchPath) {
                                            break;
                                        }
                                        searchPath = parentPath;
                                    }
                                }
                            }
                        }
                        else if (node.kind === 205 /* ModuleDeclaration */ && node.name.kind === 8 /* StringLiteral */ && (node.flags & 2 /* Ambient */ || ts.isDeclarationFile(file))) {
                            // TypeScript 1.0 spec (April 2014): 12.1.6
                            // An AmbientExternalModuleDeclaration declares an external module. 
                            // This type of declaration is permitted only in the global module.
                            // The StringLiteral must specify a top - level external module name.
                            // Relative external module names are not permitted
                            ts.forEachChild(node.body, function (node) {
                                if (ts.isExternalModuleImportEqualsDeclaration(node) &&
                                    ts.getExternalModuleImportEqualsDeclarationExpression(node).kind === 8 /* StringLiteral */) {
                                    var nameLiteral = ts.getExternalModuleImportEqualsDeclarationExpression(node);
                                    var moduleName = nameLiteral.text;
                                    if (moduleName) {
                                        // TypeScript 1.0 spec (April 2014): 12.1.6
                                        // An ExternalImportDeclaration in anAmbientExternalModuleDeclaration may reference other external modules 
                                        // only through top - level external module names. Relative external module names are not permitted.
                                        var searchName = ts.normalizePath(ts.combinePaths(basePath, moduleName));
                                        var tsFile = findModuleSourceFile(searchName + ".ts", nameLiteral);
                                        if (!tsFile) {
                                            findModuleSourceFile(searchName + ".d.ts", nameLiteral);
                                        }
                                    }
                                }
                            });
                        }
                    });
                    function findModuleSourceFile(fileName, nameLiteral) {
                        return findSourceFile(fileName, false, file, nameLiteral.pos, nameLiteral.end - nameLiteral.pos);
                    }
                }
                function computeCommonSourceDirectory(sourceFiles) {
                    var commonPathComponents;
                    var currentDirectory = host.getCurrentDirectory();
                    ts.forEach(files, function (sourceFile) {
                        // Each file contributes into common source file path
                        if (ts.isDeclarationFile(sourceFile)) {
                            return;
                        }
                        var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile.fileName, currentDirectory);
                        sourcePathComponents.pop(); // The base file name is not part of the common directory path
                        if (!commonPathComponents) {
                            // first file
                            commonPathComponents = sourcePathComponents;
                            return;
                        }
                        for (var i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) {
                            if (commonPathComponents[i] !== sourcePathComponents[i]) {
                                if (i === 0) {
                                    diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
                                    return;
                                }
                                // New common path found that is 0 -> i-1
                                commonPathComponents.length = i;
                                break;
                            }
                        }
                        // If the sourcePathComponents was shorter than the commonPathComponents, truncate to the sourcePathComponents
                        if (sourcePathComponents.length < commonPathComponents.length) {
                            commonPathComponents.length = sourcePathComponents.length;
                        }
                    });
                    return ts.getNormalizedPathFromPathComponents(commonPathComponents);
                }
                function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) {
                    var allFilesBelongToPath = true;
                    if (sourceFiles) {
                        var currentDirectory = host.getCurrentDirectory();
                        var absoluteRootDirectoryPath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(rootDirectory, currentDirectory));
                        for (var _i = 0; _i < sourceFiles.length; _i++) {
                            var sourceFile = sourceFiles[_i];
                            if (!ts.isDeclarationFile(sourceFile)) {
                                var absoluteSourceFilePath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory));
                                if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) {
                                    diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir));
                                    allFilesBelongToPath = false;
                                }
                            }
                        }
                    }
                    return allFilesBelongToPath;
                }
                function verifyCompilerOptions() {
                    if (options.separateCompilation) {
                        if (options.sourceMap) {
                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_sourceMap_cannot_be_specified_with_option_separateCompilation));
                        }
                        if (options.declaration) {
                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_declaration_cannot_be_specified_with_option_separateCompilation));
                        }
                        if (options.noEmitOnError) {
                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_noEmitOnError_cannot_be_specified_with_option_separateCompilation));
                        }
                        if (options.out) {
                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_out_cannot_be_specified_with_option_separateCompilation));
                        }
                    }
                    if (!options.sourceMap && (options.mapRoot || options.sourceRoot)) {
                        // Error to specify --mapRoot or --sourceRoot without mapSourceFiles
                        if (options.mapRoot) {
                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option));
                        }
                        if (options.sourceRoot) {
                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option));
                        }
                        return;
                    }
                    var languageVersion = options.target || 0 /* ES3 */;
                    var firstExternalModuleSourceFile = ts.forEach(files, function (f) { return ts.isExternalModule(f) ? f : undefined; });
                    if (options.separateCompilation) {
                        if (!options.module && languageVersion < 2 /* ES6 */) {
                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_separateCompilation_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher));
                        }
                        var firstNonExternalModuleSourceFile = ts.forEach(files, function (f) { return !ts.isExternalModule(f) && !ts.isDeclarationFile(f) ? f : undefined; });
                        if (firstNonExternalModuleSourceFile) {
                            var span = ts.getErrorSpanForNode(firstNonExternalModuleSourceFile, firstNonExternalModuleSourceFile);
                            diagnostics.add(ts.createFileDiagnostic(firstNonExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_compile_non_external_modules_when_the_separateCompilation_flag_is_provided));
                        }
                    }
                    else if (firstExternalModuleSourceFile && languageVersion < 2 /* ES6 */ && !options.module) {
                        // We cannot use createDiagnosticFromNode because nodes do not have parents yet 
                        var span = ts.getErrorSpanForNode(firstExternalModuleSourceFile, firstExternalModuleSourceFile.externalModuleIndicator);
                        diagnostics.add(ts.createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_compile_external_modules_unless_the_module_flag_is_provided));
                    }
                    // Cannot specify module gen target when in es6 or above
                    if (options.module && languageVersion >= 2 /* ES6 */) {
                        diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_compile_external_modules_into_amd_commonjs_or_umd_when_targeting_ES6_or_higher));
                    }
                    // there has to be common source directory if user specified --outdir || --sourceRoot
                    // if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted
                    if (options.outDir ||
                        options.sourceRoot ||
                        (options.mapRoot &&
                            (!options.out || firstExternalModuleSourceFile !== undefined))) {
                        if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) {
                            // If a rootDir is specified and is valid use it as the commonSourceDirectory
                            commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, host.getCurrentDirectory());
                        }
                        else {
                            // Compute the commonSourceDirectory from the input files
                            commonSourceDirectory = computeCommonSourceDirectory(files);
                        }
                        if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== ts.directorySeparator) {
                            // Make sure directory path ends with directory separator so this string can directly 
                            // used to replace with "" to get the relative path of the source file and the relative path doesn't
                            // start with / making it rooted path
                            commonSourceDirectory += ts.directorySeparator;
                        }
                    }
                    if (options.noEmit) {
                        if (options.out || options.outDir) {
                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_noEmit_cannot_be_specified_with_option_out_or_outDir));
                        }
                        if (options.declaration) {
                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_noEmit_cannot_be_specified_with_option_declaration));
                        }
                    }
                }
            }
            ts.createProgram = createProgram;
        })(ts || (ts = {}));
        /// <reference path="sys.ts"/>
        /// <reference path="types.ts"/>
        /// <reference path="core.ts"/>
        /// <reference path="scanner.ts"/>
        var ts;
        (function (ts) {
            /* @internal */
            ts.optionDeclarations = [
                {
                    name: "charset",
                    type: "string"
                },
                {
                    name: "declaration",
                    shortName: "d",
                    type: "boolean",
                    description: ts.Diagnostics.Generates_corresponding_d_ts_file
                },
                {
                    name: "diagnostics",
                    type: "boolean"
                },
                {
                    name: "emitBOM",
                    type: "boolean"
                },
                {
                    name: "help",
                    shortName: "h",
                    type: "boolean",
                    description: ts.Diagnostics.Print_this_message
                },
                {
                    name: "listFiles",
                    type: "boolean"
                },
                {
                    name: "locale",
                    type: "string"
                },
                {
                    name: "mapRoot",
                    type: "string",
                    isFilePath: true,
                    description: ts.Diagnostics.Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations,
                    paramType: ts.Diagnostics.LOCATION
                },
                {
                    name: "module",
                    shortName: "m",
                    type: {
                        "commonjs": 1 /* CommonJS */,
                        "amd": 2 /* AMD */,
                        "umd": 3 /* UMD */
                    },
                    description: ts.Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_or_umd,
                    paramType: ts.Diagnostics.KIND,
                    error: ts.Diagnostics.Argument_for_module_option_must_be_commonjs_amd_or_umd
                },
                {
                    name: "noEmit",
                    type: "boolean",
                    description: ts.Diagnostics.Do_not_emit_outputs
                },
                {
                    name: "noEmitOnError",
                    type: "boolean",
                    description: ts.Diagnostics.Do_not_emit_outputs_if_any_type_checking_errors_were_reported
                },
                {
                    name: "noImplicitAny",
                    type: "boolean",
                    description: ts.Diagnostics.Raise_error_on_expressions_and_declarations_with_an_implied_any_type
                },
                {
                    name: "noLib",
                    type: "boolean"
                },
                {
                    name: "noResolve",
                    type: "boolean"
                },
                {
                    name: "out",
                    type: "string",
                    description: ts.Diagnostics.Concatenate_and_emit_output_to_single_file,
                    paramType: ts.Diagnostics.FILE
                },
                {
                    name: "outDir",
                    type: "string",
                    isFilePath: true,
                    description: ts.Diagnostics.Redirect_output_structure_to_the_directory,
                    paramType: ts.Diagnostics.DIRECTORY
                },
                {
                    name: "preserveConstEnums",
                    type: "boolean",
                    description: ts.Diagnostics.Do_not_erase_const_enum_declarations_in_generated_code
                },
                {
                    name: "project",
                    shortName: "p",
                    type: "string",
                    isFilePath: true,
                    description: ts.Diagnostics.Compile_the_project_in_the_given_directory,
                    paramType: ts.Diagnostics.DIRECTORY
                },
                {
                    name: "removeComments",
                    type: "boolean",
                    description: ts.Diagnostics.Do_not_emit_comments_to_output
                },
                {
                    name: "rootDir",
                    type: "string",
                    isFilePath: true,
                    description: ts.Diagnostics.Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir,
                    paramType: ts.Diagnostics.LOCATION
                },
                {
                    name: "separateCompilation",
                    type: "boolean"
                },
                {
                    name: "sourceMap",
                    type: "boolean",
                    description: ts.Diagnostics.Generates_corresponding_map_file
                },
                {
                    name: "sourceRoot",
                    type: "string",
                    isFilePath: true,
                    description: ts.Diagnostics.Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations,
                    paramType: ts.Diagnostics.LOCATION
                },
                {
                    name: "suppressImplicitAnyIndexErrors",
                    type: "boolean",
                    description: ts.Diagnostics.Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures
                },
                {
                    name: "stripInternal",
                    type: "boolean",
                    description: ts.Diagnostics.Do_not_emit_declarations_for_code_that_has_an_internal_annotation,
                    experimental: true
                },
                {
                    name: "target",
                    shortName: "t",
                    type: { "es3": 0 /* ES3 */, "es5": 1 /* ES5 */, "es6": 2 /* ES6 */ },
                    description: ts.Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental,
                    paramType: ts.Diagnostics.VERSION,
                    error: ts.Diagnostics.Argument_for_target_option_must_be_ES3_ES5_or_ES6
                },
                {
                    name: "version",
                    shortName: "v",
                    type: "boolean",
                    description: ts.Diagnostics.Print_the_compiler_s_version
                },
                {
                    name: "watch",
                    shortName: "w",
                    type: "boolean",
                    description: ts.Diagnostics.Watch_input_files
                },
                {
                    name: "emitDecoratorMetadata",
                    type: "boolean",
                    experimental: true
                }
            ];
            function parseCommandLine(commandLine) {
                var options = {};
                var fileNames = [];
                var errors = [];
                var shortOptionNames = {};
                var optionNameMap = {};
                ts.forEach(ts.optionDeclarations, function (option) {
                    optionNameMap[option.name.toLowerCase()] = option;
                    if (option.shortName) {
                        shortOptionNames[option.shortName] = option.name;
                    }
                });
                parseStrings(commandLine);
                return {
                    options: options,
                    fileNames: fileNames,
                    errors: errors
                };
                function parseStrings(args) {
                    var i = 0;
                    while (i < args.length) {
                        var s = args[i++];
                        if (s.charCodeAt(0) === 64 /* at */) {
                            parseResponseFile(s.slice(1));
                        }
                        else if (s.charCodeAt(0) === 45 /* minus */) {
                            s = s.slice(s.charCodeAt(1) === 45 /* minus */ ? 2 : 1).toLowerCase();
                            // Try to translate short option names to their full equivalents.
                            if (ts.hasProperty(shortOptionNames, s)) {
                                s = shortOptionNames[s];
                            }
                            if (ts.hasProperty(optionNameMap, s)) {
                                var opt = optionNameMap[s];
                                // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument).
                                if (!args[i] && opt.type !== "boolean") {
                                    errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Compiler_option_0_expects_an_argument, opt.name));
                                }
                                switch (opt.type) {
                                    case "number":
                                        options[opt.name] = parseInt(args[i++]);
                                        break;
                                    case "boolean":
                                        options[opt.name] = true;
                                        break;
                                    case "string":
                                        options[opt.name] = args[i++] || "";
                                        break;
                                    // If not a primitive, the possible types are specified in what is effectively a map of options.
                                    default:
                                        var map = opt.type;
                                        var key = (args[i++] || "").toLowerCase();
                                        if (ts.hasProperty(map, key)) {
                                            options[opt.name] = map[key];
                                        }
                                        else {
                                            errors.push(ts.createCompilerDiagnostic(opt.error));
                                        }
                                }
                            }
                            else {
                                errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_compiler_option_0, s));
                            }
                        }
                        else {
                            fileNames.push(s);
                        }
                    }
                }
                function parseResponseFile(fileName) {
                    var text = ts.sys.readFile(fileName);
                    if (!text) {
                        errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, fileName));
                        return;
                    }
                    var args = [];
                    var pos = 0;
                    while (true) {
                        while (pos < text.length && text.charCodeAt(pos) <= 32 /* space */)
                            pos++;
                        if (pos >= text.length)
                            break;
                        var start = pos;
                        if (text.charCodeAt(start) === 34 /* doubleQuote */) {
                            pos++;
                            while (pos < text.length && text.charCodeAt(pos) !== 34 /* doubleQuote */)
                                pos++;
                            if (pos < text.length) {
                                args.push(text.substring(start + 1, pos));
                                pos++;
                            }
                            else {
                                errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unterminated_quoted_string_in_response_file_0, fileName));
                            }
                        }
                        else {
                            while (text.charCodeAt(pos) > 32 /* space */)
                                pos++;
                            args.push(text.substring(start, pos));
                        }
                    }
                    parseStrings(args);
                }
            }
            ts.parseCommandLine = parseCommandLine;
            /**
              * Read tsconfig.json file
              * @param fileName The path to the config file
              */
            function readConfigFile(fileName) {
                try {
                    var text = ts.sys.readFile(fileName);
                    return /\S/.test(text) ? JSON.parse(text) : {};
                }
                catch (e) {
                }
            }
            ts.readConfigFile = readConfigFile;
            /**
              * Parse the contents of a config file (tsconfig.json).
              * @param json The contents of the config file to parse
              * @param basePath A root directory to resolve relative path entries in the config
              *    file to. e.g. outDir
              */
            function parseConfigFile(json, basePath) {
                var errors = [];
                return {
                    options: getCompilerOptions(),
                    fileNames: getFiles(),
                    errors: errors
                };
                function getCompilerOptions() {
                    var options = {};
                    var optionNameMap = {};
                    ts.forEach(ts.optionDeclarations, function (option) {
                        optionNameMap[option.name] = option;
                    });
                    var jsonOptions = json["compilerOptions"];
                    if (jsonOptions) {
                        for (var id in jsonOptions) {
                            if (ts.hasProperty(optionNameMap, id)) {
                                var opt = optionNameMap[id];
                                var optType = opt.type;
                                var value = jsonOptions[id];
                                var expectedType = typeof optType === "string" ? optType : "string";
                                if (typeof value === expectedType) {
                                    if (typeof optType !== "string") {
                                        var key = value.toLowerCase();
                                        if (ts.hasProperty(optType, key)) {
                                            value = optType[key];
                                        }
                                        else {
                                            errors.push(ts.createCompilerDiagnostic(opt.error));
                                            value = 0;
                                        }
                                    }
                                    if (opt.isFilePath) {
                                        value = ts.normalizePath(ts.combinePaths(basePath, value));
                                    }
                                    options[opt.name] = value;
                                }
                                else {
                                    errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Compiler_option_0_requires_a_value_of_type_1, id, expectedType));
                                }
                            }
                            else {
                                errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_compiler_option_0, id));
                            }
                        }
                    }
                    return options;
                }
                function getFiles() {
                    var files = [];
                    if (ts.hasProperty(json, "files")) {
                        if (json["files"] instanceof Array) {
                            var files = ts.map(json["files"], function (s) { return ts.combinePaths(basePath, s); });
                        }
                    }
                    else {
                        var sysFiles = ts.sys.readDirectory(basePath, ".ts");
                        for (var i = 0; i < sysFiles.length; i++) {
                            var name = sysFiles[i];
                            if (!ts.fileExtensionIs(name, ".d.ts") || !ts.contains(sysFiles, name.substr(0, name.length - 5) + ".ts")) {
                                files.push(name);
                            }
                        }
                    }
                    return files;
                }
            }
            ts.parseConfigFile = parseConfigFile;
        })(ts || (ts = {}));
        /* @internal */
        var ts;
        (function (ts) {
            var OutliningElementsCollector;
            (function (OutliningElementsCollector) {
                function collectElements(sourceFile) {
                    var elements = [];
                    var collapseText = "...";
                    function addOutliningSpan(hintSpanNode, startElement, endElement, autoCollapse) {
                        if (hintSpanNode && startElement && endElement) {
                            var span = {
                                textSpan: ts.createTextSpanFromBounds(startElement.pos, endElement.end),
                                hintSpan: ts.createTextSpanFromBounds(hintSpanNode.getStart(), hintSpanNode.end),
                                bannerText: collapseText,
                                autoCollapse: autoCollapse
                            };
                            elements.push(span);
                        }
                    }
                    function addOutliningSpanComments(commentSpan, autoCollapse) {
                        if (commentSpan) {
                            var span = {
                                textSpan: ts.createTextSpanFromBounds(commentSpan.pos, commentSpan.end),
                                hintSpan: ts.createTextSpanFromBounds(commentSpan.pos, commentSpan.end),
                                bannerText: collapseText,
                                autoCollapse: autoCollapse
                            };
                            elements.push(span);
                        }
                    }
                    function addOutliningForLeadingCommentsForNode(n) {
                        var comments = ts.getLeadingCommentRangesOfNode(n, sourceFile);
                        if (comments) {
                            var firstSingleLineCommentStart = -1;
                            var lastSingleLineCommentEnd = -1;
                            var isFirstSingleLineComment = true;
                            var singleLineCommentCount = 0;
                            for (var _i = 0; _i < comments.length; _i++) {
                                var currentComment = comments[_i];
                                // For single line comments, combine consecutive ones (2 or more) into
                                // a single span from the start of the first till the end of the last
                                if (currentComment.kind === 2 /* SingleLineCommentTrivia */) {
                                    if (isFirstSingleLineComment) {
                                        firstSingleLineCommentStart = currentComment.pos;
                                    }
                                    isFirstSingleLineComment = false;
                                    lastSingleLineCommentEnd = currentComment.end;
                                    singleLineCommentCount++;
                                }
                                else if (currentComment.kind === 3 /* MultiLineCommentTrivia */) {
                                    combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd);
                                    addOutliningSpanComments(currentComment, false);
                                    singleLineCommentCount = 0;
                                    lastSingleLineCommentEnd = -1;
                                    isFirstSingleLineComment = true;
                                }
                            }
                            combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd);
                        }
                    }
                    function combineAndAddMultipleSingleLineComments(count, start, end) {
                        // Only outline spans of two or more consecutive single line comments
                        if (count > 1) {
                            var multipleSingleLineComments = {
                                pos: start,
                                end: end,
                                kind: 2 /* SingleLineCommentTrivia */
                            };
                            addOutliningSpanComments(multipleSingleLineComments, false);
                        }
                    }
                    function autoCollapse(node) {
                        return ts.isFunctionBlock(node) && node.parent.kind !== 163 /* ArrowFunction */;
                    }
                    var depth = 0;
                    var maxDepth = 20;
                    function walk(n) {
                        if (depth > maxDepth) {
                            return;
                        }
                        if (ts.isDeclaration(n)) {
                            addOutliningForLeadingCommentsForNode(n);
                        }
                        switch (n.kind) {
                            case 179 /* Block */:
                                if (!ts.isFunctionBlock(n)) {
                                    var parent_6 = n.parent;
                                    var openBrace = ts.findChildOfKind(n, 14 /* OpenBraceToken */, sourceFile);
                                    var closeBrace = ts.findChildOfKind(n, 15 /* CloseBraceToken */, sourceFile);
                                    // Check if the block is standalone, or 'attached' to some parent statement.
                                    // If the latter, we want to collaps the block, but consider its hint span
                                    // to be the entire span of the parent.
                                    if (parent_6.kind === 184 /* DoStatement */ ||
                                        parent_6.kind === 187 /* ForInStatement */ ||
                                        parent_6.kind === 188 /* ForOfStatement */ ||
                                        parent_6.kind === 186 /* ForStatement */ ||
                                        parent_6.kind === 183 /* IfStatement */ ||
                                        parent_6.kind === 185 /* WhileStatement */ ||
                                        parent_6.kind === 192 /* WithStatement */ ||
                                        parent_6.kind === 223 /* CatchClause */) {
                                        addOutliningSpan(parent_6, openBrace, closeBrace, autoCollapse(n));
                                        break;
                                    }
                                    if (parent_6.kind === 196 /* TryStatement */) {
                                        // Could be the try-block, or the finally-block.
                                        var tryStatement = parent_6;
                                        if (tryStatement.tryBlock === n) {
                                            addOutliningSpan(parent_6, openBrace, closeBrace, autoCollapse(n));
                                            break;
                                        }
                                        else if (tryStatement.finallyBlock === n) {
                                            var finallyKeyword = ts.findChildOfKind(tryStatement, 81 /* FinallyKeyword */, sourceFile);
                                            if (finallyKeyword) {
                                                addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n));
                                                break;
                                            }
                                        }
                                    }
                                    // Block was a standalone block.  In this case we want to only collapse
                                    // the span of the block, independent of any parent span.
                                    var span = ts.createTextSpanFromBounds(n.getStart(), n.end);
                                    elements.push({
                                        textSpan: span,
                                        hintSpan: span,
                                        bannerText: collapseText,
                                        autoCollapse: autoCollapse(n)
                                    });
                                    break;
                                }
                            // Fallthrough.
                            case 206 /* ModuleBlock */: {
                                var openBrace = ts.findChildOfKind(n, 14 /* OpenBraceToken */, sourceFile);
                                var closeBrace = ts.findChildOfKind(n, 15 /* CloseBraceToken */, sourceFile);
                                addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n));
                                break;
                            }
                            case 201 /* ClassDeclaration */:
                            case 202 /* InterfaceDeclaration */:
                            case 204 /* EnumDeclaration */:
                            case 154 /* ObjectLiteralExpression */:
                            case 207 /* CaseBlock */: {
                                var openBrace = ts.findChildOfKind(n, 14 /* OpenBraceToken */, sourceFile);
                                var closeBrace = ts.findChildOfKind(n, 15 /* CloseBraceToken */, sourceFile);
                                addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n));
                                break;
                            }
                            case 153 /* ArrayLiteralExpression */:
                                var openBracket = ts.findChildOfKind(n, 18 /* OpenBracketToken */, sourceFile);
                                var closeBracket = ts.findChildOfKind(n, 19 /* CloseBracketToken */, sourceFile);
                                addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n));
                                break;
                        }
                        depth++;
                        ts.forEachChild(n, walk);
                        depth--;
                    }
                    walk(sourceFile);
                    return elements;
                }
                OutliningElementsCollector.collectElements = collectElements;
            })(OutliningElementsCollector = ts.OutliningElementsCollector || (ts.OutliningElementsCollector = {}));
        })(ts || (ts = {}));
        /* @internal */
        var ts;
        (function (ts) {
            var NavigateTo;
            (function (NavigateTo) {
                function getNavigateToItems(program, cancellationToken, searchValue, maxResultCount) {
                    var patternMatcher = ts.createPatternMatcher(searchValue);
                    var rawItems = [];
                    // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[] 
                    ts.forEach(program.getSourceFiles(), function (sourceFile) {
                        cancellationToken.throwIfCancellationRequested();
                        var nameToDeclarations = sourceFile.getNamedDeclarations();
                        for (var name_21 in nameToDeclarations) {
                            var declarations = ts.getProperty(nameToDeclarations, name_21);
                            if (declarations) {
                                // First do a quick check to see if the name of the declaration matches the 
                                // last portion of the (possibly) dotted name they're searching for.
                                var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name_21);
                                if (!matches) {
                                    continue;
                                }
                                for (var _i = 0; _i < declarations.length; _i++) {
                                    var declaration = declarations[_i];
                                    // It was a match!  If the pattern has dots in it, then also see if the 
                                    // declaration container matches as well.
                                    if (patternMatcher.patternContainsDots) {
                                        var containers = getContainers(declaration);
                                        if (!containers) {
                                            return undefined;
                                        }
                                        matches = patternMatcher.getMatches(containers, name_21);
                                        if (!matches) {
                                            continue;
                                        }
                                    }
                                    var fileName = sourceFile.fileName;
                                    var matchKind = bestMatchKind(matches);
                                    rawItems.push({ name: name_21, fileName: fileName, matchKind: matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration: declaration });
                                }
                            }
                        }
                    });
                    rawItems.sort(compareNavigateToItems);
                    if (maxResultCount !== undefined) {
                        rawItems = rawItems.slice(0, maxResultCount);
                    }
                    var items = ts.map(rawItems, createNavigateToItem);
                    return items;
                    function allMatchesAreCaseSensitive(matches) {
                        ts.Debug.assert(matches.length > 0);
                        // This is a case sensitive match, only if all the submatches were case sensitive.
                        for (var _i = 0; _i < matches.length; _i++) {
                            var match = matches[_i];
                            if (!match.isCaseSensitive) {
                                return false;
                            }
                        }
                        return true;
                    }
                    function getTextOfIdentifierOrLiteral(node) {
                        if (node) {
                            if (node.kind === 65 /* Identifier */ ||
                                node.kind === 8 /* StringLiteral */ ||
                                node.kind === 7 /* NumericLiteral */) {
                                return node.text;
                            }
                        }
                        return undefined;
                    }
                    function tryAddSingleDeclarationName(declaration, containers) {
                        if (declaration && declaration.name) {
                            var text = getTextOfIdentifierOrLiteral(declaration.name);
                            if (text !== undefined) {
                                containers.unshift(text);
                            }
                            else if (declaration.name.kind === 127 /* ComputedPropertyName */) {
                                return tryAddComputedPropertyName(declaration.name.expression, containers, true);
                            }
                            else {
                                // Don't know how to add this.
                                return false;
                            }
                        }
                        return true;
                    }
                    // Only added the names of computed properties if they're simple dotted expressions, like:
                    //
                    //      [X.Y.Z]() { }
                    function tryAddComputedPropertyName(expression, containers, includeLastPortion) {
                        var text = getTextOfIdentifierOrLiteral(expression);
                        if (text !== undefined) {
                            if (includeLastPortion) {
                                containers.unshift(text);
                            }
                            return true;
                        }
                        if (expression.kind === 155 /* PropertyAccessExpression */) {
                            var propertyAccess = expression;
                            if (includeLastPortion) {
                                containers.unshift(propertyAccess.name.text);
                            }
                            return tryAddComputedPropertyName(propertyAccess.expression, containers, true);
                        }
                        return false;
                    }
                    function getContainers(declaration) {
                        var containers = [];
                        // First, if we started with a computed property name, then add all but the last
                        // portion into the container array.
                        if (declaration.name.kind === 127 /* ComputedPropertyName */) {
                            if (!tryAddComputedPropertyName(declaration.name.expression, containers, false)) {
                                return undefined;
                            }
                        }
                        // Now, walk up our containers, adding all their names to the container array.
                        declaration = ts.getContainerNode(declaration);
                        while (declaration) {
                            if (!tryAddSingleDeclarationName(declaration, containers)) {
                                return undefined;
                            }
                            declaration = ts.getContainerNode(declaration);
                        }
                        return containers;
                    }
                    function bestMatchKind(matches) {
                        ts.Debug.assert(matches.length > 0);
                        var bestMatchKind = ts.PatternMatchKind.camelCase;
                        for (var _i = 0; _i < matches.length; _i++) {
                            var match = matches[_i];
                            var kind = match.kind;
                            if (kind < bestMatchKind) {
                                bestMatchKind = kind;
                            }
                        }
                        return bestMatchKind;
                    }
                    // This means "compare in a case insensitive manner."
                    var baseSensitivity = { sensitivity: "base" };
                    function compareNavigateToItems(i1, i2) {
                        // TODO(cyrusn): get the gamut of comparisons that VS already uses here.
                        // Right now we just sort by kind first, and then by name of the item.
                        // We first sort case insensitively.  So "Aaa" will come before "bar".
                        // Then we sort case sensitively, so "aaa" will come before "Aaa".
                        return i1.matchKind - i2.matchKind ||
                            i1.name.localeCompare(i2.name, undefined, baseSensitivity) ||
                            i1.name.localeCompare(i2.name);
                    }
                    function createNavigateToItem(rawItem) {
                        var declaration = rawItem.declaration;
                        var container = ts.getContainerNode(declaration);
                        return {
                            name: rawItem.name,
                            kind: ts.getNodeKind(declaration),
                            kindModifiers: ts.getNodeModifiers(declaration),
                            matchKind: ts.PatternMatchKind[rawItem.matchKind],
                            isCaseSensitive: rawItem.isCaseSensitive,
                            fileName: rawItem.fileName,
                            textSpan: ts.createTextSpanFromBounds(declaration.getStart(), declaration.getEnd()),
                            // TODO(jfreeman): What should be the containerName when the container has a computed name?
                            containerName: container && container.name ? container.name.text : "",
                            containerKind: container && container.name ? ts.getNodeKind(container) : ""
                        };
                    }
                }
                NavigateTo.getNavigateToItems = getNavigateToItems;
            })(NavigateTo = ts.NavigateTo || (ts.NavigateTo = {}));
        })(ts || (ts = {}));
        /// <reference path='services.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var NavigationBar;
            (function (NavigationBar) {
                function getNavigationBarItems(sourceFile) {
                    // If the source file has any child items, then it included in the tree
                    // and takes lexical ownership of all other top-level items.
                    var hasGlobalNode = false;
                    return getItemsWorker(getTopLevelNodes(sourceFile), createTopLevelItem);
                    function getIndent(node) {
                        // If we have a global node in the tree,
                        // then it adds an extra layer of depth to all subnodes.
                        var indent = hasGlobalNode ? 1 : 0;
                        var current = node.parent;
                        while (current) {
                            switch (current.kind) {
                                case 205 /* ModuleDeclaration */:
                                    // If we have a module declared as A.B.C, it is more "intuitive"
                                    // to say it only has a single layer of depth
                                    do {
                                        current = current.parent;
                                    } while (current.kind === 205 /* ModuleDeclaration */);
                                // fall through
                                case 201 /* ClassDeclaration */:
                                case 204 /* EnumDeclaration */:
                                case 202 /* InterfaceDeclaration */:
                                case 200 /* FunctionDeclaration */:
                                    indent++;
                            }
                            current = current.parent;
                        }
                        return indent;
                    }
                    function getChildNodes(nodes) {
                        var childNodes = [];
                        function visit(node) {
                            switch (node.kind) {
                                case 180 /* VariableStatement */:
                                    ts.forEach(node.declarationList.declarations, visit);
                                    break;
                                case 150 /* ObjectBindingPattern */:
                                case 151 /* ArrayBindingPattern */:
                                    ts.forEach(node.elements, visit);
                                    break;
                                case 215 /* ExportDeclaration */:
                                    // Handle named exports case e.g.:
                                    //    export {a, b as B} from "mod";
                                    if (node.exportClause) {
                                        ts.forEach(node.exportClause.elements, visit);
                                    }
                                    break;
                                case 209 /* ImportDeclaration */:
                                    var importClause = node.importClause;
                                    if (importClause) {
                                        // Handle default import case e.g.:
                                        //    import d from "mod";
                                        if (importClause.name) {
                                            childNodes.push(importClause);
                                        }
                                        // Handle named bindings in imports e.g.:
                                        //    import * as NS from "mod";
                                        //    import {a, b as B} from "mod";
                                        if (importClause.namedBindings) {
                                            if (importClause.namedBindings.kind === 211 /* NamespaceImport */) {
                                                childNodes.push(importClause.namedBindings);
                                            }
                                            else {
                                                ts.forEach(importClause.namedBindings.elements, visit);
                                            }
                                        }
                                    }
                                    break;
                                case 152 /* BindingElement */:
                                case 198 /* VariableDeclaration */:
                                    if (ts.isBindingPattern(node.name)) {
                                        visit(node.name);
                                        break;
                                    }
                                // Fall through
                                case 201 /* ClassDeclaration */:
                                case 204 /* EnumDeclaration */:
                                case 202 /* InterfaceDeclaration */:
                                case 205 /* ModuleDeclaration */:
                                case 200 /* FunctionDeclaration */:
                                case 208 /* ImportEqualsDeclaration */:
                                case 213 /* ImportSpecifier */:
                                case 217 /* ExportSpecifier */:
                                    childNodes.push(node);
                                    break;
                            }
                        }
                        //for (let i = 0, n = nodes.length; i < n; i++) {
                        //    let node = nodes[i];
                        //    if (node.kind === SyntaxKind.ClassDeclaration ||
                        //        node.kind === SyntaxKind.EnumDeclaration ||
                        //        node.kind === SyntaxKind.InterfaceDeclaration ||
                        //        node.kind === SyntaxKind.ModuleDeclaration ||
                        //        node.kind === SyntaxKind.FunctionDeclaration) {
                        //        childNodes.push(node);
                        //    }
                        //    else if (node.kind === SyntaxKind.VariableStatement) {
                        //        childNodes.push.apply(childNodes, (<VariableStatement>node).declarations);
                        //    }
                        //}
                        ts.forEach(nodes, visit);
                        return sortNodes(childNodes);
                    }
                    function getTopLevelNodes(node) {
                        var topLevelNodes = [];
                        topLevelNodes.push(node);
                        addTopLevelNodes(node.statements, topLevelNodes);
                        return topLevelNodes;
                    }
                    function sortNodes(nodes) {
                        return nodes.slice(0).sort(function (n1, n2) {
                            if (n1.name && n2.name) {
                                return ts.getPropertyNameForPropertyNameNode(n1.name).localeCompare(ts.getPropertyNameForPropertyNameNode(n2.name));
                            }
                            else if (n1.name) {
                                return 1;
                            }
                            else if (n2.name) {
                                return -1;
                            }
                            else {
                                return n1.kind - n2.kind;
                            }
                        });
                    }
                    function addTopLevelNodes(nodes, topLevelNodes) {
                        nodes = sortNodes(nodes);
                        for (var _i = 0; _i < nodes.length; _i++) {
                            var node = nodes[_i];
                            switch (node.kind) {
                                case 201 /* ClassDeclaration */:
                                case 204 /* EnumDeclaration */:
                                case 202 /* InterfaceDeclaration */:
                                    topLevelNodes.push(node);
                                    break;
                                case 205 /* ModuleDeclaration */:
                                    var moduleDeclaration = node;
                                    topLevelNodes.push(node);
                                    addTopLevelNodes(getInnermostModule(moduleDeclaration).body.statements, topLevelNodes);
                                    break;
                                case 200 /* FunctionDeclaration */:
                                    var functionDeclaration = node;
                                    if (isTopLevelFunctionDeclaration(functionDeclaration)) {
                                        topLevelNodes.push(node);
                                        addTopLevelNodes(functionDeclaration.body.statements, topLevelNodes);
                                    }
                                    break;
                            }
                        }
                    }
                    function isTopLevelFunctionDeclaration(functionDeclaration) {
                        if (functionDeclaration.kind === 200 /* FunctionDeclaration */) {
                            // A function declaration is 'top level' if it contains any function declarations 
                            // within it. 
                            if (functionDeclaration.body && functionDeclaration.body.kind === 179 /* Block */) {
                                // Proper function declarations can only have identifier names
                                if (ts.forEach(functionDeclaration.body.statements, function (s) { return s.kind === 200 /* FunctionDeclaration */ && !isEmpty(s.name.text); })) {
                                    return true;
                                }
                                // Or if it is not parented by another function.  i.e all functions
                                // at module scope are 'top level'.
                                if (!ts.isFunctionBlock(functionDeclaration.parent)) {
                                    return true;
                                }
                            }
                        }
                        return false;
                    }
                    function getItemsWorker(nodes, createItem) {
                        var items = [];
                        var keyToItem = {};
                        for (var _i = 0; _i < nodes.length; _i++) {
                            var child = nodes[_i];
                            var item = createItem(child);
                            if (item !== undefined) {
                                if (item.text.length > 0) {
                                    var key = item.text + "-" + item.kind + "-" + item.indent;
                                    var itemWithSameName = keyToItem[key];
                                    if (itemWithSameName) {
                                        // We had an item with the same name.  Merge these items together.
                                        merge(itemWithSameName, item);
                                    }
                                    else {
                                        keyToItem[key] = item;
                                        items.push(item);
                                    }
                                }
                            }
                        }
                        return items;
                    }
                    function merge(target, source) {
                        // First, add any spans in the source to the target.
                        target.spans.push.apply(target.spans, source.spans);
                        if (source.childItems) {
                            if (!target.childItems) {
                                target.childItems = [];
                            }
                            // Next, recursively merge or add any children in the source as appropriate.
                            outer: for (var _i = 0, _a = source.childItems; _i < _a.length; _i++) {
                                var sourceChild = _a[_i];
                                for (var _b = 0, _c = target.childItems; _b < _c.length; _b++) {
                                    var targetChild = _c[_b];
                                    if (targetChild.text === sourceChild.text && targetChild.kind === sourceChild.kind) {
                                        // Found a match.  merge them.
                                        merge(targetChild, sourceChild);
                                        continue outer;
                                    }
                                }
                                // Didn't find a match, just add this child to the list.
                                target.childItems.push(sourceChild);
                            }
                        }
                    }
                    function createChildItem(node) {
                        switch (node.kind) {
                            case 129 /* Parameter */:
                                if (ts.isBindingPattern(node.name)) {
                                    break;
                                }
                                if ((node.flags & 499 /* Modifier */) === 0) {
                                    return undefined;
                                }
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberVariableElement);
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberFunctionElement);
                            case 136 /* GetAccessor */:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberGetAccessorElement);
                            case 137 /* SetAccessor */:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberSetAccessorElement);
                            case 140 /* IndexSignature */:
                                return createItem(node, "[]", ts.ScriptElementKind.indexSignatureElement);
                            case 226 /* EnumMember */:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberVariableElement);
                            case 138 /* CallSignature */:
                                return createItem(node, "()", ts.ScriptElementKind.callSignatureElement);
                            case 139 /* ConstructSignature */:
                                return createItem(node, "new()", ts.ScriptElementKind.constructSignatureElement);
                            case 132 /* PropertyDeclaration */:
                            case 131 /* PropertySignature */:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberVariableElement);
                            case 200 /* FunctionDeclaration */:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.functionElement);
                            case 198 /* VariableDeclaration */:
                            case 152 /* BindingElement */:
                                var variableDeclarationNode;
                                var name_22;
                                if (node.kind === 152 /* BindingElement */) {
                                    name_22 = node.name;
                                    variableDeclarationNode = node;
                                    // binding elements are added only for variable declarations
                                    // bubble up to the containing variable declaration
                                    while (variableDeclarationNode && variableDeclarationNode.kind !== 198 /* VariableDeclaration */) {
                                        variableDeclarationNode = variableDeclarationNode.parent;
                                    }
                                    ts.Debug.assert(variableDeclarationNode !== undefined);
                                }
                                else {
                                    ts.Debug.assert(!ts.isBindingPattern(node.name));
                                    variableDeclarationNode = node;
                                    name_22 = node.name;
                                }
                                if (ts.isConst(variableDeclarationNode)) {
                                    return createItem(node, getTextOfNode(name_22), ts.ScriptElementKind.constElement);
                                }
                                else if (ts.isLet(variableDeclarationNode)) {
                                    return createItem(node, getTextOfNode(name_22), ts.ScriptElementKind.letElement);
                                }
                                else {
                                    return createItem(node, getTextOfNode(name_22), ts.ScriptElementKind.variableElement);
                                }
                            case 135 /* Constructor */:
                                return createItem(node, "constructor", ts.ScriptElementKind.constructorImplementationElement);
                            case 217 /* ExportSpecifier */:
                            case 213 /* ImportSpecifier */:
                            case 208 /* ImportEqualsDeclaration */:
                            case 210 /* ImportClause */:
                            case 211 /* NamespaceImport */:
                                return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.alias);
                        }
                        return undefined;
                        function createItem(node, name, scriptElementKind) {
                            return getNavigationBarItem(name, scriptElementKind, ts.getNodeModifiers(node), [getNodeSpan(node)]);
                        }
                    }
                    function isEmpty(text) {
                        return !text || text.trim() === "";
                    }
                    function getNavigationBarItem(text, kind, kindModifiers, spans, childItems, indent) {
                        if (childItems === void 0) { childItems = []; }
                        if (indent === void 0) { indent = 0; }
                        if (isEmpty(text)) {
                            return undefined;
                        }
                        return {
                            text: text,
                            kind: kind,
                            kindModifiers: kindModifiers,
                            spans: spans,
                            childItems: childItems,
                            indent: indent,
                            bolded: false,
                            grayed: false
                        };
                    }
                    function createTopLevelItem(node) {
                        switch (node.kind) {
                            case 227 /* SourceFile */:
                                return createSourceFileItem(node);
                            case 201 /* ClassDeclaration */:
                                return createClassItem(node);
                            case 204 /* EnumDeclaration */:
                                return createEnumItem(node);
                            case 202 /* InterfaceDeclaration */:
                                return createIterfaceItem(node);
                            case 205 /* ModuleDeclaration */:
                                return createModuleItem(node);
                            case 200 /* FunctionDeclaration */:
                                return createFunctionItem(node);
                        }
                        return undefined;
                        function getModuleName(moduleDeclaration) {
                            // We want to maintain quotation marks.
                            if (moduleDeclaration.name.kind === 8 /* StringLiteral */) {
                                return getTextOfNode(moduleDeclaration.name);
                            }
                            // Otherwise, we need to aggregate each identifier to build up the qualified name.
                            var result = [];
                            result.push(moduleDeclaration.name.text);
                            while (moduleDeclaration.body && moduleDeclaration.body.kind === 205 /* ModuleDeclaration */) {
                                moduleDeclaration = moduleDeclaration.body;
                                result.push(moduleDeclaration.name.text);
                            }
                            return result.join(".");
                        }
                        function createModuleItem(node) {
                            var moduleName = getModuleName(node);
                            var childItems = getItemsWorker(getChildNodes(getInnermostModule(node).body.statements), createChildItem);
                            return getNavigationBarItem(moduleName, ts.ScriptElementKind.moduleElement, ts.getNodeModifiers(node), [getNodeSpan(node)], childItems, getIndent(node));
                        }
                        function createFunctionItem(node) {
                            if (node.body && node.body.kind === 179 /* Block */) {
                                var childItems = getItemsWorker(sortNodes(node.body.statements), createChildItem);
                                return getNavigationBarItem(!node.name ? "default" : node.name.text, ts.ScriptElementKind.functionElement, ts.getNodeModifiers(node), [getNodeSpan(node)], childItems, getIndent(node));
                            }
                            return undefined;
                        }
                        function createSourceFileItem(node) {
                            var childItems = getItemsWorker(getChildNodes(node.statements), createChildItem);
                            if (childItems === undefined || childItems.length === 0) {
                                return undefined;
                            }
                            hasGlobalNode = true;
                            var rootName = ts.isExternalModule(node)
                                ? "\"" + ts.escapeString(ts.getBaseFileName(ts.removeFileExtension(ts.normalizePath(node.fileName)))) + "\""
                                : "<global>";
                            return getNavigationBarItem(rootName, ts.ScriptElementKind.moduleElement, ts.ScriptElementKindModifier.none, [getNodeSpan(node)], childItems);
                        }
                        function createClassItem(node) {
                            var childItems;
                            if (node.members) {
                                var constructor = ts.forEach(node.members, function (member) {
                                    return member.kind === 135 /* Constructor */ && member;
                                });
                                // Add the constructor parameters in as children of the class (for property parameters).
                                // Note that *all non-binding pattern named* parameters will be added to the nodes array, but parameters that
                                // are not properties will be filtered out later by createChildItem.
                                var nodes = removeDynamicallyNamedProperties(node);
                                if (constructor) {
                                    nodes.push.apply(nodes, ts.filter(constructor.parameters, function (p) { return !ts.isBindingPattern(p.name); }));
                                }
                                childItems = getItemsWorker(sortNodes(nodes), createChildItem);
                            }
                            var nodeName = !node.name ? "default" : node.name.text;
                            return getNavigationBarItem(nodeName, ts.ScriptElementKind.classElement, ts.getNodeModifiers(node), [getNodeSpan(node)], childItems, getIndent(node));
                        }
                        function createEnumItem(node) {
                            var childItems = getItemsWorker(sortNodes(removeComputedProperties(node)), createChildItem);
                            return getNavigationBarItem(node.name.text, ts.ScriptElementKind.enumElement, ts.getNodeModifiers(node), [getNodeSpan(node)], childItems, getIndent(node));
                        }
                        function createIterfaceItem(node) {
                            var childItems = getItemsWorker(sortNodes(removeDynamicallyNamedProperties(node)), createChildItem);
                            return getNavigationBarItem(node.name.text, ts.ScriptElementKind.interfaceElement, ts.getNodeModifiers(node), [getNodeSpan(node)], childItems, getIndent(node));
                        }
                    }
                    function removeComputedProperties(node) {
                        return ts.filter(node.members, function (member) { return member.name === undefined || member.name.kind !== 127 /* ComputedPropertyName */; });
                    }
                    /**
                     * Like removeComputedProperties, but retains the properties with well known symbol names
                     */
                    function removeDynamicallyNamedProperties(node) {
                        return ts.filter(node.members, function (member) { return !ts.hasDynamicName(member); });
                    }
                    function getInnermostModule(node) {
                        while (node.body.kind === 205 /* ModuleDeclaration */) {
                            node = node.body;
                        }
                        return node;
                    }
                    function getNodeSpan(node) {
                        return node.kind === 227 /* SourceFile */
                            ? ts.createTextSpanFromBounds(node.getFullStart(), node.getEnd())
                            : ts.createTextSpanFromBounds(node.getStart(), node.getEnd());
                    }
                    function getTextOfNode(node) {
                        return ts.getTextOfNodeFromSourceText(sourceFile.text, node);
                    }
                }
                NavigationBar.getNavigationBarItems = getNavigationBarItems;
            })(NavigationBar = ts.NavigationBar || (ts.NavigationBar = {}));
        })(ts || (ts = {}));
        /* @internal */
        var ts;
        (function (ts) {
            // Note(cyrusn): this enum is ordered from strongest match type to weakest match type.
            (function (PatternMatchKind) {
                PatternMatchKind[PatternMatchKind["exact"] = 0] = "exact";
                PatternMatchKind[PatternMatchKind["prefix"] = 1] = "prefix";
                PatternMatchKind[PatternMatchKind["substring"] = 2] = "substring";
                PatternMatchKind[PatternMatchKind["camelCase"] = 3] = "camelCase";
            })(ts.PatternMatchKind || (ts.PatternMatchKind = {}));
            var PatternMatchKind = ts.PatternMatchKind;
            function createPatternMatch(kind, punctuationStripped, isCaseSensitive, camelCaseWeight) {
                return {
                    kind: kind,
                    punctuationStripped: punctuationStripped,
                    isCaseSensitive: isCaseSensitive,
                    camelCaseWeight: camelCaseWeight
                };
            }
            function createPatternMatcher(pattern) {
                // We'll often see the same candidate string many times when searching (For example, when
                // we see the name of a module that is used everywhere, or the name of an overload).  As 
                // such, we cache the information we compute about the candidate for the life of this 
                // pattern matcher so we don't have to compute it multiple times.
                var stringToWordSpans = {};
                pattern = pattern.trim();
                var fullPatternSegment = createSegment(pattern);
                var dotSeparatedSegments = pattern.split(".").map(function (p) { return createSegment(p.trim()); });
                var invalidPattern = dotSeparatedSegments.length === 0 || ts.forEach(dotSeparatedSegments, segmentIsInvalid);
                return {
                    getMatches: getMatches,
                    getMatchesForLastSegmentOfPattern: getMatchesForLastSegmentOfPattern,
                    patternContainsDots: dotSeparatedSegments.length > 1
                };
                // Quick checks so we can bail out when asked to match a candidate.
                function skipMatch(candidate) {
                    return invalidPattern || !candidate;
                }
                function getMatchesForLastSegmentOfPattern(candidate) {
                    if (skipMatch(candidate)) {
                        return undefined;
                    }
                    return matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments));
                }
                function getMatches(candidateContainers, candidate) {
                    if (skipMatch(candidate)) {
                        return undefined;
                    }
                    // First, check that the last part of the dot separated pattern matches the name of the
                    // candidate.  If not, then there's no point in proceeding and doing the more
                    // expensive work.
                    var candidateMatch = matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments));
                    if (!candidateMatch) {
                        return undefined;
                    }
                    candidateContainers = candidateContainers || [];
                    // -1 because the last part was checked against the name, and only the rest
                    // of the parts are checked against the container.
                    if (dotSeparatedSegments.length - 1 > candidateContainers.length) {
                        // There weren't enough container parts to match against the pattern parts.
                        // So this definitely doesn't match.
                        return undefined;
                    }
                    // So far so good.  Now break up the container for the candidate and check if all
                    // the dotted parts match up correctly.
                    var totalMatch = candidateMatch;
                    for (var i = dotSeparatedSegments.length - 2, j = candidateContainers.length - 1; i >= 0; i--, j--) {
                        var segment = dotSeparatedSegments[i];
                        var containerName = candidateContainers[j];
                        var containerMatch = matchSegment(containerName, segment);
                        if (!containerMatch) {
                            // This container didn't match the pattern piece.  So there's no match at all.
                            return undefined;
                        }
                        ts.addRange(totalMatch, containerMatch);
                    }
                    // Success, this symbol's full name matched against the dotted name the user was asking
                    // about.
                    return totalMatch;
                }
                function getWordSpans(word) {
                    if (!ts.hasProperty(stringToWordSpans, word)) {
                        stringToWordSpans[word] = breakIntoWordSpans(word);
                    }
                    return stringToWordSpans[word];
                }
                function matchTextChunk(candidate, chunk, punctuationStripped) {
                    var index = indexOfIgnoringCase(candidate, chunk.textLowerCase);
                    if (index === 0) {
                        if (chunk.text.length === candidate.length) {
                            // a) Check if the part matches the candidate entirely, in an case insensitive or
                            //    sensitive manner.  If it does, return that there was an exact match.
                            return createPatternMatch(PatternMatchKind.exact, punctuationStripped, candidate === chunk.text);
                        }
                        else {
                            // b) Check if the part is a prefix of the candidate, in a case insensitive or sensitive
                            //    manner.  If it does, return that there was a prefix match.
                            return createPatternMatch(PatternMatchKind.prefix, punctuationStripped, startsWith(candidate, chunk.text));
                        }
                    }
                    var isLowercase = chunk.isLowerCase;
                    if (isLowercase) {
                        if (index > 0) {
                            // c) If the part is entirely lowercase, then check if it is contained anywhere in the
                            //    candidate in a case insensitive manner.  If so, return that there was a substring
                            //    match. 
                            //
                            //    Note: We only have a substring match if the lowercase part is prefix match of some
                            //    word part. That way we don't match something like 'Class' when the user types 'a'.
                            //    But we would match 'FooAttribute' (since 'Attribute' starts with 'a').
                            var wordSpans = getWordSpans(candidate);
                            for (var _i = 0; _i < wordSpans.length; _i++) {
                                var span = wordSpans[_i];
                                if (partStartsWith(candidate, span, chunk.text, true)) {
                                    return createPatternMatch(PatternMatchKind.substring, punctuationStripped, 
                                    /*isCaseSensitive:*/ partStartsWith(candidate, span, chunk.text, false));
                                }
                            }
                        }
                    }
                    else {
                        // d) If the part was not entirely lowercase, then check if it is contained in the
                        //    candidate in a case *sensitive* manner. If so, return that there was a substring
                        //    match.
                        if (candidate.indexOf(chunk.text) > 0) {
                            return createPatternMatch(PatternMatchKind.substring, punctuationStripped, true);
                        }
                    }
                    if (!isLowercase) {
                        // e) If the part was not entirely lowercase, then attempt a camel cased match as well.
                        if (chunk.characterSpans.length > 0) {
                            var candidateParts = getWordSpans(candidate);
                            var camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, false);
                            if (camelCaseWeight !== undefined) {
                                return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, true, camelCaseWeight);
                            }
                            camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, true);
                            if (camelCaseWeight !== undefined) {
                                return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, false, camelCaseWeight);
                            }
                        }
                    }
                    if (isLowercase) {
                        // f) Is the pattern a substring of the candidate starting on one of the candidate's word boundaries?
                        // We could check every character boundary start of the candidate for the pattern. However, that's
                        // an m * n operation in the wost case. Instead, find the first instance of the pattern 
                        // substring, and see if it starts on a capital letter. It seems unlikely that the user will try to 
                        // filter the list based on a substring that starts on a capital letter and also with a lowercase one.
                        // (Pattern: fogbar, Candidate: quuxfogbarFogBar).
                        if (chunk.text.length < candidate.length) {
                            if (index > 0 && isUpperCaseLetter(candidate.charCodeAt(index))) {
                                return createPatternMatch(PatternMatchKind.substring, punctuationStripped, false);
                            }
                        }
                    }
                    return undefined;
                }
                function containsSpaceOrAsterisk(text) {
                    for (var i = 0; i < text.length; i++) {
                        var ch = text.charCodeAt(i);
                        if (ch === 32 /* space */ || ch === 42 /* asterisk */) {
                            return true;
                        }
                    }
                    return false;
                }
                function matchSegment(candidate, segment) {
                    // First check if the segment matches as is.  This is also useful if the segment contains
                    // characters we would normally strip when splitting into parts that we also may want to
                    // match in the candidate.  For example if the segment is "@int" and the candidate is
                    // "@int", then that will show up as an exact match here.
                    //
                    // Note: if the segment contains a space or an asterisk then we must assume that it's a
                    // multi-word segment.
                    if (!containsSpaceOrAsterisk(segment.totalTextChunk.text)) {
                        var match = matchTextChunk(candidate, segment.totalTextChunk, false);
                        if (match) {
                            return [match];
                        }
                    }
                    // The logic for pattern matching is now as follows:
                    //
                    // 1) Break the segment passed in into words.  Breaking is rather simple and a
                    //    good way to think about it that if gives you all the individual alphanumeric words
                    //    of the pattern.
                    //
                    // 2) For each word try to match the word against the candidate value.
                    //
                    // 3) Matching is as follows:
                    //
                    //   a) Check if the word matches the candidate entirely, in an case insensitive or
                    //    sensitive manner.  If it does, return that there was an exact match.
                    //
                    //   b) Check if the word is a prefix of the candidate, in a case insensitive or
                    //      sensitive manner.  If it does, return that there was a prefix match.
                    //
                    //   c) If the word is entirely lowercase, then check if it is contained anywhere in the
                    //      candidate in a case insensitive manner.  If so, return that there was a substring
                    //      match. 
                    //
                    //      Note: We only have a substring match if the lowercase part is prefix match of
                    //      some word part. That way we don't match something like 'Class' when the user
                    //      types 'a'. But we would match 'FooAttribute' (since 'Attribute' starts with
                    //      'a').
                    //
                    //   d) If the word was not entirely lowercase, then check if it is contained in the
                    //      candidate in a case *sensitive* manner. If so, return that there was a substring
                    //      match.
                    //
                    //   e) If the word was not entirely lowercase, then attempt a camel cased match as
                    //      well.
                    //
                    //   f) The word is all lower case. Is it a case insensitive substring of the candidate starting 
                    //      on a part boundary of the candidate?
                    //
                    // Only if all words have some sort of match is the pattern considered matched.
                    var subWordTextChunks = segment.subWordTextChunks;
                    var matches = undefined;
                    for (var _i = 0; _i < subWordTextChunks.length; _i++) {
                        var subWordTextChunk = subWordTextChunks[_i];
                        // Try to match the candidate with this word
                        var result = matchTextChunk(candidate, subWordTextChunk, true);
                        if (!result) {
                            return undefined;
                        }
                        matches = matches || [];
                        matches.push(result);
                    }
                    return matches;
                }
                function partStartsWith(candidate, candidateSpan, pattern, ignoreCase, patternSpan) {
                    var patternPartStart = patternSpan ? patternSpan.start : 0;
                    var patternPartLength = patternSpan ? patternSpan.length : pattern.length;
                    if (patternPartLength > candidateSpan.length) {
                        // Pattern part is longer than the candidate part. There can never be a match.
                        return false;
                    }
                    if (ignoreCase) {
                        for (var i = 0; i < patternPartLength; i++) {
                            var ch1 = pattern.charCodeAt(patternPartStart + i);
                            var ch2 = candidate.charCodeAt(candidateSpan.start + i);
                            if (toLowerCase(ch1) !== toLowerCase(ch2)) {
                                return false;
                            }
                        }
                    }
                    else {
                        for (var i = 0; i < patternPartLength; i++) {
                            var ch1 = pattern.charCodeAt(patternPartStart + i);
                            var ch2 = candidate.charCodeAt(candidateSpan.start + i);
                            if (ch1 !== ch2) {
                                return false;
                            }
                        }
                    }
                    return true;
                }
                function tryCamelCaseMatch(candidate, candidateParts, chunk, ignoreCase) {
                    var chunkCharacterSpans = chunk.characterSpans;
                    // Note: we may have more pattern parts than candidate parts.  This is because multiple
                    // pattern parts may match a candidate part.  For example "SiUI" against "SimpleUI".
                    // We'll have 3 pattern parts Si/U/I against two candidate parts Simple/UI.  However, U
                    // and I will both match in UI. 
                    var currentCandidate = 0;
                    var currentChunkSpan = 0;
                    var firstMatch = undefined;
                    var contiguous = undefined;
                    while (true) {
                        // Let's consider our termination cases
                        if (currentChunkSpan === chunkCharacterSpans.length) {
                            // We did match! We shall assign a weight to this
                            var weight = 0;
                            // Was this contiguous?
                            if (contiguous) {
                                weight += 1;
                            }
                            // Did we start at the beginning of the candidate?
                            if (firstMatch === 0) {
                                weight += 2;
                            }
                            return weight;
                        }
                        else if (currentCandidate === candidateParts.length) {
                            // No match, since we still have more of the pattern to hit
                            return undefined;
                        }
                        var candidatePart = candidateParts[currentCandidate];
                        var gotOneMatchThisCandidate = false;
                        // Consider the case of matching SiUI against SimpleUIElement. The candidate parts
                        // will be Simple/UI/Element, and the pattern parts will be Si/U/I.  We'll match 'Si'
                        // against 'Simple' first.  Then we'll match 'U' against 'UI'. However, we want to
                        // still keep matching pattern parts against that candidate part. 
                        for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) {
                            var chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan];
                            if (gotOneMatchThisCandidate) {
                                // We've already gotten one pattern part match in this candidate.  We will
                                // only continue trying to consumer pattern parts if the last part and this
                                // part are both upper case.  
                                if (!isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) ||
                                    !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start))) {
                                    break;
                                }
                            }
                            if (!partStartsWith(candidate, candidatePart, chunk.text, ignoreCase, chunkCharacterSpan)) {
                                break;
                            }
                            gotOneMatchThisCandidate = true;
                            firstMatch = firstMatch === undefined ? currentCandidate : firstMatch;
                            // If we were contiguous, then keep that value.  If we weren't, then keep that
                            // value.  If we don't know, then set the value to 'true' as an initial match is
                            // obviously contiguous.
                            contiguous = contiguous === undefined ? true : contiguous;
                            candidatePart = ts.createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length);
                        }
                        // Check if we matched anything at all.  If we didn't, then we need to unset the
                        // contiguous bit if we currently had it set.
                        // If we haven't set the bit yet, then that means we haven't matched anything so
                        // far, and we don't want to change that.
                        if (!gotOneMatchThisCandidate && contiguous !== undefined) {
                            contiguous = false;
                        }
                        // Move onto the next candidate.
                        currentCandidate++;
                    }
                }
            }
            ts.createPatternMatcher = createPatternMatcher;
            // Helper function to compare two matches to determine which is better.  Matches are first
            // ordered by kind (so all prefix matches always beat all substring matches).  Then, if the
            // match is a camel case match, the relative weights of the match are used to determine 
            // which is better (with a greater weight being better).  Then if the match is of the same 
            // type, then a case sensitive match is considered better than an insensitive one. 
            function patternMatchCompareTo(match1, match2) {
                return compareType(match1, match2) ||
                    compareCamelCase(match1, match2) ||
                    compareCase(match1, match2) ||
                    comparePunctuation(match1, match2);
            }
            function comparePunctuation(result1, result2) {
                // Consider a match to be better if it was successful without stripping punctuation
                // versus a match that had to strip punctuation to succeed.
                if (result1.punctuationStripped !== result2.punctuationStripped) {
                    return result1.punctuationStripped ? 1 : -1;
                }
                return 0;
            }
            function compareCase(result1, result2) {
                if (result1.isCaseSensitive !== result2.isCaseSensitive) {
                    return result1.isCaseSensitive ? -1 : 1;
                }
                return 0;
            }
            function compareType(result1, result2) {
                return result1.kind - result2.kind;
            }
            function compareCamelCase(result1, result2) {
                if (result1.kind === PatternMatchKind.camelCase && result2.kind === PatternMatchKind.camelCase) {
                    // Swap the values here.  If result1 has a higher weight, then we want it to come
                    // first.
                    return result2.camelCaseWeight - result1.camelCaseWeight;
                }
                return 0;
            }
            function createSegment(text) {
                return {
                    totalTextChunk: createTextChunk(text),
                    subWordTextChunks: breakPatternIntoTextChunks(text)
                };
            }
            // A segment is considered invalid if we couldn't find any words in it.
            function segmentIsInvalid(segment) {
                return segment.subWordTextChunks.length === 0;
            }
            function isUpperCaseLetter(ch) {
                // Fast check for the ascii range.
                if (ch >= 65 /* A */ && ch <= 90 /* Z */) {
                    return true;
                }
                if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 2 /* Latest */)) {
                    return false;
                }
                // TODO: find a way to determine this for any unicode characters in a 
                // non-allocating manner.
                var str = String.fromCharCode(ch);
                return str === str.toUpperCase();
            }
            function isLowerCaseLetter(ch) {
                // Fast check for the ascii range.
                if (ch >= 97 /* a */ && ch <= 122 /* z */) {
                    return true;
                }
                if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 2 /* Latest */)) {
                    return false;
                }
                // TODO: find a way to determine this for any unicode characters in a 
                // non-allocating manner.
                var str = String.fromCharCode(ch);
                return str === str.toLowerCase();
            }
            function containsUpperCaseLetter(string) {
                for (var i = 0, n = string.length; i < n; i++) {
                    if (isUpperCaseLetter(string.charCodeAt(i))) {
                        return true;
                    }
                }
                return false;
            }
            function startsWith(string, search) {
                for (var i = 0, n = search.length; i < n; i++) {
                    if (string.charCodeAt(i) !== search.charCodeAt(i)) {
                        return false;
                    }
                }
                return true;
            }
            // Assumes 'value' is already lowercase.
            function indexOfIgnoringCase(string, value) {
                for (var i = 0, n = string.length - value.length; i <= n; i++) {
                    if (startsWithIgnoringCase(string, value, i)) {
                        return i;
                    }
                }
                return -1;
            }
            // Assumes 'value' is already lowercase.
            function startsWithIgnoringCase(string, value, start) {
                for (var i = 0, n = value.length; i < n; i++) {
                    var ch1 = toLowerCase(string.charCodeAt(i + start));
                    var ch2 = value.charCodeAt(i);
                    if (ch1 !== ch2) {
                        return false;
                    }
                }
                return true;
            }
            function toLowerCase(ch) {
                // Fast convert for the ascii range.
                if (ch >= 65 /* A */ && ch <= 90 /* Z */) {
                    return 97 /* a */ + (ch - 65 /* A */);
                }
                if (ch < 127 /* maxAsciiCharacter */) {
                    return ch;
                }
                // TODO: find a way to compute this for any unicode characters in a 
                // non-allocating manner.
                return String.fromCharCode(ch).toLowerCase().charCodeAt(0);
            }
            function isDigit(ch) {
                // TODO(cyrusn): Find a way to support this for unicode digits.
                return ch >= 48 /* _0 */ && ch <= 57 /* _9 */;
            }
            function isWordChar(ch) {
                return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 /* _ */ || ch === 36 /* $ */;
            }
            function breakPatternIntoTextChunks(pattern) {
                var result = [];
                var wordStart = 0;
                var wordLength = 0;
                for (var i = 0; i < pattern.length; i++) {
                    var ch = pattern.charCodeAt(i);
                    if (isWordChar(ch)) {
                        if (wordLength++ === 0) {
                            wordStart = i;
                        }
                    }
                    else {
                        if (wordLength > 0) {
                            result.push(createTextChunk(pattern.substr(wordStart, wordLength)));
                            wordLength = 0;
                        }
                    }
                }
                if (wordLength > 0) {
                    result.push(createTextChunk(pattern.substr(wordStart, wordLength)));
                }
                return result;
            }
            function createTextChunk(text) {
                var textLowerCase = text.toLowerCase();
                return {
                    text: text,
                    textLowerCase: textLowerCase,
                    isLowerCase: text === textLowerCase,
                    characterSpans: breakIntoCharacterSpans(text)
                };
            }
            /* @internal */ function breakIntoCharacterSpans(identifier) {
                return breakIntoSpans(identifier, false);
            }
            ts.breakIntoCharacterSpans = breakIntoCharacterSpans;
            /* @internal */ function breakIntoWordSpans(identifier) {
                return breakIntoSpans(identifier, true);
            }
            ts.breakIntoWordSpans = breakIntoWordSpans;
            function breakIntoSpans(identifier, word) {
                var result = [];
                var wordStart = 0;
                for (var i = 1, n = identifier.length; i < n; i++) {
                    var lastIsDigit = isDigit(identifier.charCodeAt(i - 1));
                    var currentIsDigit = isDigit(identifier.charCodeAt(i));
                    var hasTransitionFromLowerToUpper = transitionFromLowerToUpper(identifier, word, i);
                    var hasTransitionFromUpperToLower = transitionFromUpperToLower(identifier, word, i, wordStart);
                    if (charIsPunctuation(identifier.charCodeAt(i - 1)) ||
                        charIsPunctuation(identifier.charCodeAt(i)) ||
                        lastIsDigit != currentIsDigit ||
                        hasTransitionFromLowerToUpper ||
                        hasTransitionFromUpperToLower) {
                        if (!isAllPunctuation(identifier, wordStart, i)) {
                            result.push(ts.createTextSpan(wordStart, i - wordStart));
                        }
                        wordStart = i;
                    }
                }
                if (!isAllPunctuation(identifier, wordStart, identifier.length)) {
                    result.push(ts.createTextSpan(wordStart, identifier.length - wordStart));
                }
                return result;
            }
            function charIsPunctuation(ch) {
                switch (ch) {
                    case 33 /* exclamation */:
                    case 34 /* doubleQuote */:
                    case 35 /* hash */:
                    case 37 /* percent */:
                    case 38 /* ampersand */:
                    case 39 /* singleQuote */:
                    case 40 /* openParen */:
                    case 41 /* closeParen */:
                    case 42 /* asterisk */:
                    case 44 /* comma */:
                    case 45 /* minus */:
                    case 46 /* dot */:
                    case 47 /* slash */:
                    case 58 /* colon */:
                    case 59 /* semicolon */:
                    case 63 /* question */:
                    case 64 /* at */:
                    case 91 /* openBracket */:
                    case 92 /* backslash */:
                    case 93 /* closeBracket */:
                    case 95 /* _ */:
                    case 123 /* openBrace */:
                    case 125 /* closeBrace */:
                        return true;
                }
                return false;
            }
            function isAllPunctuation(identifier, start, end) {
                for (var i = start; i < end; i++) {
                    var ch = identifier.charCodeAt(i);
                    // We don't consider _ or $ as punctuation as there may be things with that name.
                    if (!charIsPunctuation(ch) || ch === 95 /* _ */ || ch === 36 /* $ */) {
                        return false;
                    }
                }
                return true;
            }
            function transitionFromUpperToLower(identifier, word, index, wordStart) {
                if (word) {
                    // Cases this supports:
                    // 1) IDisposable -> I, Disposable
                    // 2) UIElement -> UI, Element
                    // 3) HTMLDocument -> HTML, Document
                    //
                    // etc.
                    if (index != wordStart &&
                        index + 1 < identifier.length) {
                        var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
                        var nextIsLower = isLowerCaseLetter(identifier.charCodeAt(index + 1));
                        if (currentIsUpper && nextIsLower) {
                            // We have a transition from an upper to a lower letter here.  But we only
                            // want to break if all the letters that preceded are uppercase.  i.e. if we
                            // have "Foo" we don't want to break that into "F, oo".  But if we have
                            // "IFoo" or "UIFoo", then we want to break that into "I, Foo" and "UI,
                            // Foo".  i.e. the last uppercase letter belongs to the lowercase letters
                            // that follows.  Note: this will make the following not split properly:
                            // "HELLOthere".  However, these sorts of names do not show up in .Net
                            // programs.
                            for (var i = wordStart; i < index; i++) {
                                if (!isUpperCaseLetter(identifier.charCodeAt(i))) {
                                    return false;
                                }
                            }
                            return true;
                        }
                    }
                }
                return false;
            }
            function transitionFromLowerToUpper(identifier, word, index) {
                var lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1));
                var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
                // See if the casing indicates we're starting a new word. Note: if we're breaking on
                // words, then just seeing an upper case character isn't enough.  Instead, it has to
                // be uppercase and the previous character can't be uppercase. 
                //
                // For example, breaking "AddMetadata" on words would make: Add Metadata
                //
                // on characters would be: A dd M etadata
                //
                // Break "AM" on words would be: AM
                //
                // on characters would be: A M
                //
                // We break the search string on characters.  But we break the symbol name on words.
                var transition = word
                    ? (currentIsUpper && !lastIsUpper)
                    : currentIsUpper;
                return transition;
            }
        })(ts || (ts = {}));
        ///<reference path='services.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var SignatureHelp;
            (function (SignatureHelp) {
                // A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression
                // or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference. 
                // To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it 
                // will return the generic identifier that started the expression (e.g. "foo" in "foo<any, |"). It is then up to the caller to ensure that this is a valid generic expression through 
                // looking up the type. The method will also keep track of the parameter index inside the expression.
                //public static isInPartiallyWrittenTypeArgumentList(syntaxTree: TypeScript.SyntaxTree, position: number): any {
                //    let token = Syntax.findTokenOnLeft(syntaxTree.sourceUnit(), position, /*includeSkippedTokens*/ true);
                //    if (token && TypeScript.Syntax.hasAncestorOfKind(token, TypeScript.SyntaxKind.TypeParameterList)) {
                //        // We are in the wrong generic list. bail out
                //        return null;
                //    }
                //    let stack = 0;
                //    let argumentIndex = 0;
                //    whileLoop:
                //    while (token) {
                //        switch (token.kind()) {
                //            case TypeScript.SyntaxKind.LessThanToken:
                //                if (stack === 0) {
                //                    // Found the beginning of the generic argument expression
                //                    let lessThanToken = token;
                //                    token = previousToken(token, /*includeSkippedTokens*/ true);
                //                    if (!token || token.kind() !== TypeScript.SyntaxKind.IdentifierName) {
                //                        break whileLoop;
                //                    }
                //                    // Found the name, return the data
                //                    return {
                //                        genericIdentifer: token,
                //                        lessThanToken: lessThanToken,
                //                        argumentIndex: argumentIndex
                //                    };
                //                }
                //                else if (stack < 0) {
                //                    // Seen one too many less than tokens, bail out
                //                    break whileLoop;
                //                }
                //                else {
                //                    stack--;
                //                }
                //                break;
                //            case TypeScript.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
                //                stack++;
                //            // Intentaion fall through
                //            case TypeScript.SyntaxKind.GreaterThanToken:
                //                stack++;
                //                break;
                //            case TypeScript.SyntaxKind.CommaToken:
                //                if (stack == 0) {
                //                    argumentIndex++;
                //                }
                //                break;
                //            case TypeScript.SyntaxKind.CloseBraceToken:
                //                // This can be object type, skip untill we find the matching open brace token
                //                let unmatchedOpenBraceTokens = 0;
                //                // Skip untill the matching open brace token
                //                token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.CloseBraceToken, TypeScript.SyntaxKind.OpenBraceToken);
                //                if (!token) {
                //                    // No matching token was found. bail out
                //                    break whileLoop;
                //                }
                //                break;
                //            case TypeScript.SyntaxKind.EqualsGreaterThanToken:
                //                // This can be a function type or a constructor type. In either case, we want to skip the function defintion
                //                token = previousToken(token, /*includeSkippedTokens*/ true);
                //                if (token && token.kind() === TypeScript.SyntaxKind.CloseParenToken) {
                //                    // Skip untill the matching open paren token
                //                    token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.CloseParenToken, TypeScript.SyntaxKind.OpenParenToken);
                //                    if (token && token.kind() === TypeScript.SyntaxKind.GreaterThanToken) {
                //                        // Another generic type argument list, skip it\
                //                        token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.GreaterThanToken, TypeScript.SyntaxKind.LessThanToken);
                //                    }
                //                    if (token && token.kind() === TypeScript.SyntaxKind.NewKeyword) {
                //                        // In case this was a constructor type, skip the new keyword
                //                        token = previousToken(token, /*includeSkippedTokens*/ true);
                //                    }
                //                    if (!token) {
                //                        // No matching token was found. bail out
                //                        break whileLoop;
                //                    }
                //                }
                //                else {
                //                    // This is not a funtion type. exit the main loop
                //                    break whileLoop;
                //                }
                //                break;
                //            case TypeScript.SyntaxKind.IdentifierName:
                //            case TypeScript.SyntaxKind.AnyKeyword:
                //            case TypeScript.SyntaxKind.NumberKeyword:
                //            case TypeScript.SyntaxKind.StringKeyword:
                //            case TypeScript.SyntaxKind.VoidKeyword:
                //            case TypeScript.SyntaxKind.BooleanKeyword:
                //            case TypeScript.SyntaxKind.DotToken:
                //            case TypeScript.SyntaxKind.OpenBracketToken:
                //            case TypeScript.SyntaxKind.CloseBracketToken:
                //                // Valid tokens in a type name. Skip.
                //                break;
                //            default:
                //                break whileLoop;
                //        }
                //        token = previousToken(token, /*includeSkippedTokens*/ true);
                //    }
                //    return null;
                //}
                //private static moveBackUpTillMatchingTokenKind(token: TypeScript.ISyntaxToken, tokenKind: TypeScript.SyntaxKind, matchingTokenKind: TypeScript.SyntaxKind): TypeScript.ISyntaxToken {
                //    if (!token || token.kind() !== tokenKind) {
                //        throw TypeScript.Errors.invalidOperation();
                //    }
                //    // Skip the current token
                //    token = previousToken(token, /*includeSkippedTokens*/ true);
                //    let stack = 0;
                //    while (token) {
                //        if (token.kind() === matchingTokenKind) {
                //            if (stack === 0) {
                //                // Found the matching token, return
                //                return token;
                //            }
                //            else if (stack < 0) {
                //                // tokens overlapped.. bail out.
                //                break;
                //            }
                //            else {
                //                stack--;
                //            }
                //        }
                //        else if (token.kind() === tokenKind) {
                //            stack++;
                //        }
                //        // Move back
                //        token = previousToken(token, /*includeSkippedTokens*/ true);
                //    }
                //    // Did not find matching token
                //    return null;
                //}
                var emptyArray = [];
                var ArgumentListKind;
                (function (ArgumentListKind) {
                    ArgumentListKind[ArgumentListKind["TypeArguments"] = 0] = "TypeArguments";
                    ArgumentListKind[ArgumentListKind["CallArguments"] = 1] = "CallArguments";
                    ArgumentListKind[ArgumentListKind["TaggedTemplateArguments"] = 2] = "TaggedTemplateArguments";
                })(ArgumentListKind || (ArgumentListKind = {}));
                function getSignatureHelpItems(program, sourceFile, position, cancellationToken) {
                    var typeChecker = program.getTypeChecker();
                    // Decide whether to show signature help
                    var startingToken = ts.findTokenOnLeftOfPosition(sourceFile, position);
                    if (!startingToken) {
                        // We are at the beginning of the file
                        return undefined;
                    }
                    var argumentInfo = getContainingArgumentInfo(startingToken);
                    cancellationToken.throwIfCancellationRequested();
                    // Semantic filtering of signature help
                    if (!argumentInfo) {
                        return undefined;
                    }
                    var call = argumentInfo.invocation;
                    var candidates = [];
                    var resolvedSignature = typeChecker.getResolvedSignature(call, candidates);
                    cancellationToken.throwIfCancellationRequested();
                    if (!candidates.length) {
                        // We didn't have any sig help items produced by the TS compiler.  If this is a JS 
                        // file, then see if we can figure out anything better.
                        if (ts.isJavaScript(sourceFile.fileName)) {
                            return createJavaScriptSignatureHelpItems(argumentInfo);
                        }
                        return undefined;
                    }
                    return createSignatureHelpItems(candidates, resolvedSignature, argumentInfo);
                    function createJavaScriptSignatureHelpItems(argumentInfo) {
                        if (argumentInfo.invocation.kind !== 157 /* CallExpression */) {
                            return undefined;
                        }
                        // See if we can find some symbol with the call expression name that has call signatures.
                        var callExpression = argumentInfo.invocation;
                        var expression = callExpression.expression;
                        var name = expression.kind === 65 /* Identifier */
                            ? expression
                            : expression.kind === 155 /* PropertyAccessExpression */
                                ? expression.name
                                : undefined;
                        if (!name || !name.text) {
                            return undefined;
                        }
                        var typeChecker = program.getTypeChecker();
                        for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) {
                            var sourceFile_1 = _a[_i];
                            var nameToDeclarations = sourceFile_1.getNamedDeclarations();
                            var declarations = ts.getProperty(nameToDeclarations, name.text);
                            if (declarations) {
                                for (var _b = 0; _b < declarations.length; _b++) {
                                    var declaration = declarations[_b];
                                    var symbol = declaration.symbol;
                                    if (symbol) {
                                        var type = typeChecker.getTypeOfSymbolAtLocation(symbol, declaration);
                                        if (type) {
                                            var callSignatures = type.getCallSignatures();
                                            if (callSignatures && callSignatures.length) {
                                                return createSignatureHelpItems(callSignatures, callSignatures[0], argumentInfo);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    /**
                     * Returns relevant information for the argument list and the current argument if we are
                     * in the argument of an invocation; returns undefined otherwise.
                     */
                    function getImmediatelyContainingArgumentInfo(node) {
                        if (node.parent.kind === 157 /* CallExpression */ || node.parent.kind === 158 /* NewExpression */) {
                            var callExpression = node.parent;
                            // There are 3 cases to handle:
                            //   1. The token introduces a list, and should begin a sig help session
                            //   2. The token is either not associated with a list, or ends a list, so the session should end
                            //   3. The token is buried inside a list, and should give sig help
                            //
                            // The following are examples of each:
                            //
                            //    Case 1:
                            //          foo<#T, U>(#a, b)    -> The token introduces a list, and should begin a sig help session
                            //    Case 2:
                            //          fo#o<T, U>#(a, b)#   -> The token is either not associated with a list, or ends a list, so the session should end
                            //    Case 3:
                            //          foo<T#, U#>(a#, #b#) -> The token is buried inside a list, and should give sig help
                            // Find out if 'node' is an argument, a type argument, or neither
                            if (node.kind === 24 /* LessThanToken */ ||
                                node.kind === 16 /* OpenParenToken */) {
                                // Find the list that starts right *after* the < or ( token.
                                // If the user has just opened a list, consider this item 0.
                                var list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile);
                                var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
                                ts.Debug.assert(list !== undefined);
                                return {
                                    kind: isTypeArgList ? 0 /* TypeArguments */ : 1 /* CallArguments */,
                                    invocation: callExpression,
                                    argumentsSpan: getApplicableSpanForArguments(list),
                                    argumentIndex: 0,
                                    argumentCount: getArgumentCount(list)
                                };
                            }
                            // findListItemInfo can return undefined if we are not in parent's argument list
                            // or type argument list. This includes cases where the cursor is:
                            //   - To the right of the closing paren, non-substitution template, or template tail.
                            //   - Between the type arguments and the arguments (greater than token)
                            //   - On the target of the call (parent.func)
                            //   - On the 'new' keyword in a 'new' expression
                            var listItemInfo = ts.findListItemInfo(node);
                            if (listItemInfo) {
                                var list = listItemInfo.list;
                                var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
                                var argumentIndex = getArgumentIndex(list, node);
                                var argumentCount = getArgumentCount(list);
                                ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex);
                                return {
                                    kind: isTypeArgList ? 0 /* TypeArguments */ : 1 /* CallArguments */,
                                    invocation: callExpression,
                                    argumentsSpan: getApplicableSpanForArguments(list),
                                    argumentIndex: argumentIndex,
                                    argumentCount: argumentCount
                                };
                            }
                        }
                        else if (node.kind === 10 /* NoSubstitutionTemplateLiteral */ && node.parent.kind === 159 /* TaggedTemplateExpression */) {
                            // Check if we're actually inside the template;
                            // otherwise we'll fall out and return undefined.
                            if (ts.isInsideTemplateLiteral(node, position)) {
                                return getArgumentListInfoForTemplate(node.parent, 0);
                            }
                        }
                        else if (node.kind === 11 /* TemplateHead */ && node.parent.parent.kind === 159 /* TaggedTemplateExpression */) {
                            var templateExpression = node.parent;
                            var tagExpression = templateExpression.parent;
                            ts.Debug.assert(templateExpression.kind === 171 /* TemplateExpression */);
                            var argumentIndex = ts.isInsideTemplateLiteral(node, position) ? 0 : 1;
                            return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
                        }
                        else if (node.parent.kind === 176 /* TemplateSpan */ && node.parent.parent.parent.kind === 159 /* TaggedTemplateExpression */) {
                            var templateSpan = node.parent;
                            var templateExpression = templateSpan.parent;
                            var tagExpression = templateExpression.parent;
                            ts.Debug.assert(templateExpression.kind === 171 /* TemplateExpression */);
                            // If we're just after a template tail, don't show signature help.
                            if (node.kind === 13 /* TemplateTail */ && !ts.isInsideTemplateLiteral(node, position)) {
                                return undefined;
                            }
                            var spanIndex = templateExpression.templateSpans.indexOf(templateSpan);
                            var argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node);
                            return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
                        }
                        return undefined;
                    }
                    function getArgumentIndex(argumentsList, node) {
                        // The list we got back can include commas.  In the presence of errors it may 
                        // also just have nodes without commas.  For example "Foo(a b c)" will have 3 
                        // args without commas.   We want to find what index we're at.  So we count
                        // forward until we hit ourselves, only incrementing the index if it isn't a
                        // comma.
                        //
                        // Note: the subtlety around trailing commas (in getArgumentCount) does not apply
                        // here.  That's because we're only walking forward until we hit the node we're
                        // on.  In that case, even if we're after the trailing comma, we'll still see
                        // that trailing comma in the list, and we'll have generated the appropriate
                        // arg index.
                        var argumentIndex = 0;
                        var listChildren = argumentsList.getChildren();
                        for (var _i = 0; _i < listChildren.length; _i++) {
                            var child = listChildren[_i];
                            if (child === node) {
                                break;
                            }
                            if (child.kind !== 23 /* CommaToken */) {
                                argumentIndex++;
                            }
                        }
                        return argumentIndex;
                    }
                    function getArgumentCount(argumentsList) {
                        // The argument count for a list is normally the number of non-comma children it has.
                        // For example, if you have "Foo(a,b)" then there will be three children of the arg
                        // list 'a' '<comma>' 'b'.  So, in this case the arg count will be 2.  However, there
                        // is a small subtlety.  If you have  "Foo(a,)", then the child list will just have
                        // 'a' '<comma>'.  So, in the case where the last child is a comma, we increase the
                        // arg count by one to compensate.
                        //
                        // Note: this subtlety only applies to the last comma.  If you had "Foo(a,,"  then 
                        // we'll have:  'a' '<comma>' '<missing>' 
                        // That will give us 2 non-commas.  We then add one for the last comma, givin us an
                        // arg count of 3.
                        var listChildren = argumentsList.getChildren();
                        var argumentCount = ts.countWhere(listChildren, function (arg) { return arg.kind !== 23 /* CommaToken */; });
                        if (listChildren.length > 0 && ts.lastOrUndefined(listChildren).kind === 23 /* CommaToken */) {
                            argumentCount++;
                        }
                        return argumentCount;
                    }
                    // spanIndex is either the index for a given template span.
                    // This does not give appropriate results for a NoSubstitutionTemplateLiteral
                    function getArgumentIndexForTemplatePiece(spanIndex, node) {
                        // Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1.
                        // There are three cases we can encounter:
                        //      1. We are precisely in the template literal (argIndex = 0).
                        //      2. We are in or to the right of the substitution expression (argIndex = spanIndex + 1).
                        //      3. We are directly to the right of the template literal, but because we look for the token on the left,
                        //          not enough to put us in the substitution expression; we should consider ourselves part of
                        //          the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1).
                        //
                        // Example: f  `# abcd $#{#  1 + 1#  }# efghi ${ #"#hello"#  }  #  `
                        //              ^       ^ ^       ^   ^          ^ ^      ^     ^
                        // Case:        1       1 3       2   1          3 2      2     1
                        ts.Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node.");
                        if (ts.isTemplateLiteralKind(node.kind)) {
                            if (ts.isInsideTemplateLiteral(node, position)) {
                                return 0;
                            }
                            return spanIndex + 2;
                        }
                        return spanIndex + 1;
                    }
                    function getArgumentListInfoForTemplate(tagExpression, argumentIndex) {
                        // argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument.
                        var argumentCount = tagExpression.template.kind === 10 /* NoSubstitutionTemplateLiteral */
                            ? 1
                            : tagExpression.template.templateSpans.length + 1;
                        ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex);
                        return {
                            kind: 2 /* TaggedTemplateArguments */,
                            invocation: tagExpression,
                            argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression),
                            argumentIndex: argumentIndex,
                            argumentCount: argumentCount
                        };
                    }
                    function getApplicableSpanForArguments(argumentsList) {
                        // We use full start and skip trivia on the end because we want to include trivia on
                        // both sides. For example,
                        //
                        //    foo(   /*comment */     a, b, c      /*comment*/     )
                        //        |                                               |
                        //
                        // The applicable span is from the first bar to the second bar (inclusive,
                        // but not including parentheses)
                        var applicableSpanStart = argumentsList.getFullStart();
                        var applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), false);
                        return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
                    }
                    function getApplicableSpanForTaggedTemplate(taggedTemplate) {
                        var template = taggedTemplate.template;
                        var applicableSpanStart = template.getStart();
                        var applicableSpanEnd = template.getEnd();
                        // We need to adjust the end position for the case where the template does not have a tail.
                        // Otherwise, we will not show signature help past the expression.
                        // For example,
                        //
                        //      `  ${ 1 + 1        foo(10)
                        //       |        |
                        //
                        // This is because a Missing node has no width. However, what we actually want is to include trivia
                        // leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail.
                        if (template.kind === 171 /* TemplateExpression */) {
                            var lastSpan = ts.lastOrUndefined(template.templateSpans);
                            if (lastSpan.literal.getFullWidth() === 0) {
                                applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, false);
                            }
                        }
                        return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
                    }
                    function getContainingArgumentInfo(node) {
                        for (var n = node; n.kind !== 227 /* SourceFile */; n = n.parent) {
                            if (ts.isFunctionBlock(n)) {
                                return undefined;
                            }
                            // If the node is not a subspan of its parent, this is a big problem.
                            // There have been crashes that might be caused by this violation.
                            if (n.pos < n.parent.pos || n.end > n.parent.end) {
                                ts.Debug.fail("Node of kind " + n.kind + " is not a subspan of its parent of kind " + n.parent.kind);
                            }
                            var argumentInfo_1 = getImmediatelyContainingArgumentInfo(n);
                            if (argumentInfo_1) {
                                return argumentInfo_1;
                            }
                        }
                        return undefined;
                    }
                    function getChildListThatStartsWithOpenerToken(parent, openerToken, sourceFile) {
                        var children = parent.getChildren(sourceFile);
                        var indexOfOpenerToken = children.indexOf(openerToken);
                        ts.Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1);
                        return children[indexOfOpenerToken + 1];
                    }
                    /**
                     * The selectedItemIndex could be negative for several reasons.
                     *     1. There are too many arguments for all of the overloads
                     *     2. None of the overloads were type compatible
                     * The solution here is to try to pick the best overload by picking
                     * either the first one that has an appropriate number of parameters,
                     * or the one with the most parameters.
                     */
                    function selectBestInvalidOverloadIndex(candidates, argumentCount) {
                        var maxParamsSignatureIndex = -1;
                        var maxParams = -1;
                        for (var i = 0; i < candidates.length; i++) {
                            var candidate = candidates[i];
                            if (candidate.hasRestParameter || candidate.parameters.length >= argumentCount) {
                                return i;
                            }
                            if (candidate.parameters.length > maxParams) {
                                maxParams = candidate.parameters.length;
                                maxParamsSignatureIndex = i;
                            }
                        }
                        return maxParamsSignatureIndex;
                    }
                    function createSignatureHelpItems(candidates, bestSignature, argumentListInfo) {
                        var applicableSpan = argumentListInfo.argumentsSpan;
                        var isTypeParameterList = argumentListInfo.kind === 0 /* TypeArguments */;
                        var invocation = argumentListInfo.invocation;
                        var callTarget = ts.getInvokedExpression(invocation);
                        var callTargetSymbol = typeChecker.getSymbolAtLocation(callTarget);
                        var callTargetDisplayParts = callTargetSymbol && ts.symbolToDisplayParts(typeChecker, callTargetSymbol, undefined, undefined);
                        var items = ts.map(candidates, function (candidateSignature) {
                            var signatureHelpParameters;
                            var prefixDisplayParts = [];
                            var suffixDisplayParts = [];
                            if (callTargetDisplayParts) {
                                prefixDisplayParts.push.apply(prefixDisplayParts, callTargetDisplayParts);
                            }
                            if (isTypeParameterList) {
                                prefixDisplayParts.push(ts.punctuationPart(24 /* LessThanToken */));
                                var typeParameters = candidateSignature.typeParameters;
                                signatureHelpParameters = typeParameters && typeParameters.length > 0 ? ts.map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
                                suffixDisplayParts.push(ts.punctuationPart(25 /* GreaterThanToken */));
                                var parameterParts = ts.mapToDisplayParts(function (writer) {
                                    return typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.parameters, writer, invocation);
                                });
                                suffixDisplayParts.push.apply(suffixDisplayParts, parameterParts);
                            }
                            else {
                                var typeParameterParts = ts.mapToDisplayParts(function (writer) {
                                    return typeChecker.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation);
                                });
                                prefixDisplayParts.push.apply(prefixDisplayParts, typeParameterParts);
                                prefixDisplayParts.push(ts.punctuationPart(16 /* OpenParenToken */));
                                var parameters = candidateSignature.parameters;
                                signatureHelpParameters = parameters.length > 0 ? ts.map(parameters, createSignatureHelpParameterForParameter) : emptyArray;
                                suffixDisplayParts.push(ts.punctuationPart(17 /* CloseParenToken */));
                            }
                            var returnTypeParts = ts.mapToDisplayParts(function (writer) {
                                return typeChecker.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation);
                            });
                            suffixDisplayParts.push.apply(suffixDisplayParts, returnTypeParts);
                            return {
                                isVariadic: candidateSignature.hasRestParameter,
                                prefixDisplayParts: prefixDisplayParts,
                                suffixDisplayParts: suffixDisplayParts,
                                separatorDisplayParts: [ts.punctuationPart(23 /* CommaToken */), ts.spacePart()],
                                parameters: signatureHelpParameters,
                                documentation: candidateSignature.getDocumentationComment()
                            };
                        });
                        var argumentIndex = argumentListInfo.argumentIndex;
                        // argumentCount is the *apparent* number of arguments.
                        var argumentCount = argumentListInfo.argumentCount;
                        var selectedItemIndex = candidates.indexOf(bestSignature);
                        if (selectedItemIndex < 0) {
                            selectedItemIndex = selectBestInvalidOverloadIndex(candidates, argumentCount);
                        }
                        ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex);
                        return {
                            items: items,
                            applicableSpan: applicableSpan,
                            selectedItemIndex: selectedItemIndex,
                            argumentIndex: argumentIndex,
                            argumentCount: argumentCount
                        };
                        function createSignatureHelpParameterForParameter(parameter) {
                            var displayParts = ts.mapToDisplayParts(function (writer) {
                                return typeChecker.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation);
                            });
                            var isOptional = ts.hasQuestionToken(parameter.valueDeclaration);
                            return {
                                name: parameter.name,
                                documentation: parameter.getDocumentationComment(),
                                displayParts: displayParts,
                                isOptional: isOptional
                            };
                        }
                        function createSignatureHelpParameterForTypeParameter(typeParameter) {
                            var displayParts = ts.mapToDisplayParts(function (writer) {
                                return typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation);
                            });
                            return {
                                name: typeParameter.symbol.name,
                                documentation: emptyArray,
                                displayParts: displayParts,
                                isOptional: false
                            };
                        }
                    }
                }
                SignatureHelp.getSignatureHelpItems = getSignatureHelpItems;
            })(SignatureHelp = ts.SignatureHelp || (ts.SignatureHelp = {}));
        })(ts || (ts = {}));
        // These utilities are common to multiple language service features.
        /* @internal */
        var ts;
        (function (ts) {
            function getEndLinePosition(line, sourceFile) {
                ts.Debug.assert(line >= 0);
                var lineStarts = sourceFile.getLineStarts();
                var lineIndex = line;
                if (lineIndex + 1 === lineStarts.length) {
                    // last line - return EOF
                    return sourceFile.text.length - 1;
                }
                else {
                    // current line start
                    var start = lineStarts[lineIndex];
                    // take the start position of the next line -1 = it should be some line break
                    var pos = lineStarts[lineIndex + 1] - 1;
                    ts.Debug.assert(ts.isLineBreak(sourceFile.text.charCodeAt(pos)));
                    // walk backwards skipping line breaks, stop the the beginning of current line.
                    // i.e:
                    // <some text>
                    // $ <- end of line for this position should match the start position
                    while (start <= pos && ts.isLineBreak(sourceFile.text.charCodeAt(pos))) {
                        pos--;
                    }
                    return pos;
                }
            }
            ts.getEndLinePosition = getEndLinePosition;
            function getLineStartPositionForPosition(position, sourceFile) {
                var lineStarts = sourceFile.getLineStarts();
                var line = sourceFile.getLineAndCharacterOfPosition(position).line;
                return lineStarts[line];
            }
            ts.getLineStartPositionForPosition = getLineStartPositionForPosition;
            function rangeContainsRange(r1, r2) {
                return startEndContainsRange(r1.pos, r1.end, r2);
            }
            ts.rangeContainsRange = rangeContainsRange;
            function startEndContainsRange(start, end, range) {
                return start <= range.pos && end >= range.end;
            }
            ts.startEndContainsRange = startEndContainsRange;
            function rangeContainsStartEnd(range, start, end) {
                return range.pos <= start && range.end >= end;
            }
            ts.rangeContainsStartEnd = rangeContainsStartEnd;
            function rangeOverlapsWithStartEnd(r1, start, end) {
                return startEndOverlapsWithStartEnd(r1.pos, r1.end, start, end);
            }
            ts.rangeOverlapsWithStartEnd = rangeOverlapsWithStartEnd;
            function startEndOverlapsWithStartEnd(start1, end1, start2, end2) {
                var start = Math.max(start1, start2);
                var end = Math.min(end1, end2);
                return start < end;
            }
            ts.startEndOverlapsWithStartEnd = startEndOverlapsWithStartEnd;
            function positionBelongsToNode(candidate, position, sourceFile) {
                return candidate.end > position || !isCompletedNode(candidate, sourceFile);
            }
            ts.positionBelongsToNode = positionBelongsToNode;
            function isCompletedNode(n, sourceFile) {
                if (ts.nodeIsMissing(n)) {
                    return false;
                }
                switch (n.kind) {
                    case 201 /* ClassDeclaration */:
                    case 202 /* InterfaceDeclaration */:
                    case 204 /* EnumDeclaration */:
                    case 154 /* ObjectLiteralExpression */:
                    case 150 /* ObjectBindingPattern */:
                    case 145 /* TypeLiteral */:
                    case 179 /* Block */:
                    case 206 /* ModuleBlock */:
                    case 207 /* CaseBlock */:
                        return nodeEndsWith(n, 15 /* CloseBraceToken */, sourceFile);
                    case 223 /* CatchClause */:
                        return isCompletedNode(n.block, sourceFile);
                    case 158 /* NewExpression */:
                        if (!n.arguments) {
                            return true;
                        }
                    // fall through
                    case 157 /* CallExpression */:
                    case 161 /* ParenthesizedExpression */:
                    case 149 /* ParenthesizedType */:
                        return nodeEndsWith(n, 17 /* CloseParenToken */, sourceFile);
                    case 142 /* FunctionType */:
                    case 143 /* ConstructorType */:
                        return isCompletedNode(n.type, sourceFile);
                    case 135 /* Constructor */:
                    case 136 /* GetAccessor */:
                    case 137 /* SetAccessor */:
                    case 200 /* FunctionDeclaration */:
                    case 162 /* FunctionExpression */:
                    case 134 /* MethodDeclaration */:
                    case 133 /* MethodSignature */:
                    case 139 /* ConstructSignature */:
                    case 138 /* CallSignature */:
                    case 163 /* ArrowFunction */:
                        if (n.body) {
                            return isCompletedNode(n.body, sourceFile);
                        }
                        if (n.type) {
                            return isCompletedNode(n.type, sourceFile);
                        }
                        // Even though type parameters can be unclosed, we can get away with
                        // having at least a closing paren.
                        return hasChildOfKind(n, 17 /* CloseParenToken */, sourceFile);
                    case 205 /* ModuleDeclaration */:
                        return n.body && isCompletedNode(n.body, sourceFile);
                    case 183 /* IfStatement */:
                        if (n.elseStatement) {
                            return isCompletedNode(n.elseStatement, sourceFile);
                        }
                        return isCompletedNode(n.thenStatement, sourceFile);
                    case 182 /* ExpressionStatement */:
                        return isCompletedNode(n.expression, sourceFile);
                    case 153 /* ArrayLiteralExpression */:
                    case 151 /* ArrayBindingPattern */:
                    case 156 /* ElementAccessExpression */:
                    case 127 /* ComputedPropertyName */:
                    case 147 /* TupleType */:
                        return nodeEndsWith(n, 19 /* CloseBracketToken */, sourceFile);
                    case 140 /* IndexSignature */:
                        if (n.type) {
                            return isCompletedNode(n.type, sourceFile);
                        }
                        return hasChildOfKind(n, 19 /* CloseBracketToken */, sourceFile);
                    case 220 /* CaseClause */:
                    case 221 /* DefaultClause */:
                        // there is no such thing as terminator token for CaseClause/DefaultClause so for simplicitly always consider them non-completed
                        return false;
                    case 186 /* ForStatement */:
                    case 187 /* ForInStatement */:
                    case 188 /* ForOfStatement */:
                    case 185 /* WhileStatement */:
                        return isCompletedNode(n.statement, sourceFile);
                    case 184 /* DoStatement */:
                        // rough approximation: if DoStatement has While keyword - then if node is completed is checking the presence of ')';
                        var hasWhileKeyword = findChildOfKind(n, 100 /* WhileKeyword */, sourceFile);
                        if (hasWhileKeyword) {
                            return nodeEndsWith(n, 17 /* CloseParenToken */, sourceFile);
                        }
                        return isCompletedNode(n.statement, sourceFile);
                    case 144 /* TypeQuery */:
                        return isCompletedNode(n.exprName, sourceFile);
                    case 165 /* TypeOfExpression */:
                    case 164 /* DeleteExpression */:
                    case 166 /* VoidExpression */:
                    case 172 /* YieldExpression */:
                    case 173 /* SpreadElementExpression */:
                        var unaryWordExpression = n;
                        return isCompletedNode(unaryWordExpression.expression, sourceFile);
                    case 159 /* TaggedTemplateExpression */:
                        return isCompletedNode(n.template, sourceFile);
                    case 171 /* TemplateExpression */:
                        var lastSpan = ts.lastOrUndefined(n.templateSpans);
                        return isCompletedNode(lastSpan, sourceFile);
                    case 176 /* TemplateSpan */:
                        return ts.nodeIsPresent(n.literal);
                    case 167 /* PrefixUnaryExpression */:
                        return isCompletedNode(n.operand, sourceFile);
                    case 169 /* BinaryExpression */:
                        return isCompletedNode(n.right, sourceFile);
                    case 170 /* ConditionalExpression */:
                        return isCompletedNode(n.whenFalse, sourceFile);
                    default:
                        return true;
                }
            }
            ts.isCompletedNode = isCompletedNode;
            /*
             * Checks if node ends with 'expectedLastToken'.
             * If child at position 'length - 1' is 'SemicolonToken' it is skipped and 'expectedLastToken' is compared with child at position 'length - 2'.
             */
            function nodeEndsWith(n, expectedLastToken, sourceFile) {
                var children = n.getChildren(sourceFile);
                if (children.length) {
                    var last = children[children.length - 1];
                    if (last.kind === expectedLastToken) {
                        return true;
                    }
                    else if (last.kind === 22 /* SemicolonToken */ && children.length !== 1) {
                        return children[children.length - 2].kind === expectedLastToken;
                    }
                }
                return false;
            }
            function findListItemInfo(node) {
                var list = findContainingList(node);
                // It is possible at this point for syntaxList to be undefined, either if
                // node.parent had no list child, or if none of its list children contained
                // the span of node. If this happens, return undefined. The caller should
                // handle this case.
                if (!list) {
                    return undefined;
                }
                var children = list.getChildren();
                var listItemIndex = ts.indexOf(children, node);
                return {
                    listItemIndex: listItemIndex,
                    list: list
                };
            }
            ts.findListItemInfo = findListItemInfo;
            function hasChildOfKind(n, kind, sourceFile) {
                return !!findChildOfKind(n, kind, sourceFile);
            }
            ts.hasChildOfKind = hasChildOfKind;
            function findChildOfKind(n, kind, sourceFile) {
                return ts.forEach(n.getChildren(sourceFile), function (c) { return c.kind === kind && c; });
            }
            ts.findChildOfKind = findChildOfKind;
            function findContainingList(node) {
                // The node might be a list element (nonsynthetic) or a comma (synthetic). Either way, it will
                // be parented by the container of the SyntaxList, not the SyntaxList itself.
                // In order to find the list item index, we first need to locate SyntaxList itself and then search
                // for the position of the relevant node (or comma).
                var syntaxList = ts.forEach(node.parent.getChildren(), function (c) {
                    // find syntax list that covers the span of the node
                    if (c.kind === 228 /* SyntaxList */ && c.pos <= node.pos && c.end >= node.end) {
                        return c;
                    }
                });
                // Either we didn't find an appropriate list, or the list must contain us.
                ts.Debug.assert(!syntaxList || ts.contains(syntaxList.getChildren(), node));
                return syntaxList;
            }
            ts.findContainingList = findContainingList;
            /* Gets the token whose text has range [start, end) and
             * position >= start and (position < end or (position === end && token is keyword or identifier))
             */
            function getTouchingWord(sourceFile, position) {
                return getTouchingToken(sourceFile, position, function (n) { return isWord(n.kind); });
            }
            ts.getTouchingWord = getTouchingWord;
            /* Gets the token whose text has range [start, end) and position >= start
             * and (position < end or (position === end && token is keyword or identifier or numeric\string litera))
             */
            function getTouchingPropertyName(sourceFile, position) {
                return getTouchingToken(sourceFile, position, function (n) { return isPropertyName(n.kind); });
            }
            ts.getTouchingPropertyName = getTouchingPropertyName;
            /** Returns the token if position is in [start, end) or if position === end and includeItemAtEndPosition(token) === true */
            function getTouchingToken(sourceFile, position, includeItemAtEndPosition) {
                return getTokenAtPositionWorker(sourceFile, position, false, includeItemAtEndPosition);
            }
            ts.getTouchingToken = getTouchingToken;
            /** Returns a token if position is in [start-of-leading-trivia, end) */
            function getTokenAtPosition(sourceFile, position) {
                return getTokenAtPositionWorker(sourceFile, position, true, undefined);
            }
            ts.getTokenAtPosition = getTokenAtPosition;
            /** Get the token whose text contains the position */
            function getTokenAtPositionWorker(sourceFile, position, allowPositionInLeadingTrivia, includeItemAtEndPosition) {
                var current = sourceFile;
                outer: while (true) {
                    if (isToken(current)) {
                        // exit early
                        return current;
                    }
                    // find the child that contains 'position'
                    for (var i = 0, n = current.getChildCount(sourceFile); i < n; i++) {
                        var child = current.getChildAt(i);
                        var start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile);
                        if (start <= position) {
                            var end = child.getEnd();
                            if (position < end || (position === end && child.kind === 1 /* EndOfFileToken */)) {
                                current = child;
                                continue outer;
                            }
                            else if (includeItemAtEndPosition && end === position) {
                                var previousToken = findPrecedingToken(position, sourceFile, child);
                                if (previousToken && includeItemAtEndPosition(previousToken)) {
                                    return previousToken;
                                }
                            }
                        }
                    }
                    return current;
                }
            }
            /**
              * The token on the left of the position is the token that strictly includes the position
              * or sits to the left of the cursor if it is on a boundary. For example
              *
              *   fo|o               -> will return foo
              *   foo <comment> |bar -> will return foo
              *
              */
            function findTokenOnLeftOfPosition(file, position) {
                // Ideally, getTokenAtPosition should return a token. However, it is currently
                // broken, so we do a check to make sure the result was indeed a token.
                var tokenAtPosition = getTokenAtPosition(file, position);
                if (isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) {
                    return tokenAtPosition;
                }
                return findPrecedingToken(position, file);
            }
            ts.findTokenOnLeftOfPosition = findTokenOnLeftOfPosition;
            function findNextToken(previousToken, parent) {
                return find(parent);
                function find(n) {
                    if (isToken(n) && n.pos === previousToken.end) {
                        // this is token that starts at the end of previous token - return it
                        return n;
                    }
                    var children = n.getChildren();
                    for (var _i = 0; _i < children.length; _i++) {
                        var child = children[_i];
                        var shouldDiveInChildNode = 
                        // previous token is enclosed somewhere in the child
                        (child.pos <= previousToken.pos && child.end > previousToken.end) ||
                            // previous token ends exactly at the beginning of child
                            (child.pos === previousToken.end);
                        if (shouldDiveInChildNode && nodeHasTokens(child)) {
                            return find(child);
                        }
                    }
                    return undefined;
                }
            }
            ts.findNextToken = findNextToken;
            function findPrecedingToken(position, sourceFile, startNode) {
                return find(startNode || sourceFile);
                function findRightmostToken(n) {
                    if (isToken(n)) {
                        return n;
                    }
                    var children = n.getChildren();
                    var candidate = findRightmostChildNodeWithTokens(children, children.length);
                    return candidate && findRightmostToken(candidate);
                }
                function find(n) {
                    if (isToken(n)) {
                        return n;
                    }
                    var children = n.getChildren();
                    for (var i = 0, len = children.length; i < len; i++) {
                        var child = children[i];
                        if (nodeHasTokens(child)) {
                            if (position <= child.end) {
                                if (child.getStart(sourceFile) >= position) {
                                    // actual start of the node is past the position - previous token should be at the end of previous child
                                    var candidate = findRightmostChildNodeWithTokens(children, i);
                                    return candidate && findRightmostToken(candidate);
                                }
                                else {
                                    // candidate should be in this node
                                    return find(child);
                                }
                            }
                        }
                    }
                    ts.Debug.assert(startNode !== undefined || n.kind === 227 /* SourceFile */);
                    // Here we know that none of child token nodes embrace the position, 
                    // the only known case is when position is at the end of the file.
                    // Try to find the rightmost token in the file without filtering.
                    // Namely we are skipping the check: 'position < node.end'
                    if (children.length) {
                        var candidate = findRightmostChildNodeWithTokens(children, children.length);
                        return candidate && findRightmostToken(candidate);
                    }
                }
                /// finds last node that is considered as candidate for search (isCandidate(node) === true) starting from 'exclusiveStartPosition'
                function findRightmostChildNodeWithTokens(children, exclusiveStartPosition) {
                    for (var i = exclusiveStartPosition - 1; i >= 0; --i) {
                        if (nodeHasTokens(children[i])) {
                            return children[i];
                        }
                    }
                }
            }
            ts.findPrecedingToken = findPrecedingToken;
            function nodeHasTokens(n) {
                // If we have a token or node that has a non-zero width, it must have tokens.
                // Note, that getWidth() does not take trivia into account.
                return n.getWidth() !== 0;
            }
            function getNodeModifiers(node) {
                var flags = ts.getCombinedNodeFlags(node);
                var result = [];
                if (flags & 32 /* Private */)
                    result.push(ts.ScriptElementKindModifier.privateMemberModifier);
                if (flags & 64 /* Protected */)
                    result.push(ts.ScriptElementKindModifier.protectedMemberModifier);
                if (flags & 16 /* Public */)
                    result.push(ts.ScriptElementKindModifier.publicMemberModifier);
                if (flags & 128 /* Static */)
                    result.push(ts.ScriptElementKindModifier.staticModifier);
                if (flags & 1 /* Export */)
                    result.push(ts.ScriptElementKindModifier.exportedModifier);
                if (ts.isInAmbientContext(node))
                    result.push(ts.ScriptElementKindModifier.ambientModifier);
                return result.length > 0 ? result.join(',') : ts.ScriptElementKindModifier.none;
            }
            ts.getNodeModifiers = getNodeModifiers;
            function getTypeArgumentOrTypeParameterList(node) {
                if (node.kind === 141 /* TypeReference */ || node.kind === 157 /* CallExpression */) {
                    return node.typeArguments;
                }
                if (ts.isFunctionLike(node) || node.kind === 201 /* ClassDeclaration */ || node.kind === 202 /* InterfaceDeclaration */) {
                    return node.typeParameters;
                }
                return undefined;
            }
            ts.getTypeArgumentOrTypeParameterList = getTypeArgumentOrTypeParameterList;
            function isToken(n) {
                return n.kind >= 0 /* FirstToken */ && n.kind <= 125 /* LastToken */;
            }
            ts.isToken = isToken;
            function isWord(kind) {
                return kind === 65 /* Identifier */ || ts.isKeyword(kind);
            }
            ts.isWord = isWord;
            function isPropertyName(kind) {
                return kind === 8 /* StringLiteral */ || kind === 7 /* NumericLiteral */ || isWord(kind);
            }
            function isComment(kind) {
                return kind === 2 /* SingleLineCommentTrivia */ || kind === 3 /* MultiLineCommentTrivia */;
            }
            ts.isComment = isComment;
            function isPunctuation(kind) {
                return 14 /* FirstPunctuation */ <= kind && kind <= 64 /* LastPunctuation */;
            }
            ts.isPunctuation = isPunctuation;
            function isInsideTemplateLiteral(node, position) {
                return ts.isTemplateLiteralKind(node.kind)
                    && (node.getStart() < position && position < node.getEnd()) || (!!node.isUnterminated && position === node.getEnd());
            }
            ts.isInsideTemplateLiteral = isInsideTemplateLiteral;
            function isAccessibilityModifier(kind) {
                switch (kind) {
                    case 108 /* PublicKeyword */:
                    case 106 /* PrivateKeyword */:
                    case 107 /* ProtectedKeyword */:
                        return true;
                }
                return false;
            }
            ts.isAccessibilityModifier = isAccessibilityModifier;
            function compareDataObjects(dst, src) {
                for (var e in dst) {
                    if (typeof dst[e] === "object") {
                        if (!compareDataObjects(dst[e], src[e])) {
                            return false;
                        }
                    }
                    else if (typeof dst[e] !== "function") {
                        if (dst[e] !== src[e]) {
                            return false;
                        }
                    }
                }
                return true;
            }
            ts.compareDataObjects = compareDataObjects;
        })(ts || (ts = {}));
        // Display-part writer helpers
        /* @internal */
        var ts;
        (function (ts) {
            function isFirstDeclarationOfSymbolParameter(symbol) {
                return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === 129 /* Parameter */;
            }
            ts.isFirstDeclarationOfSymbolParameter = isFirstDeclarationOfSymbolParameter;
            var displayPartWriter = getDisplayPartWriter();
            function getDisplayPartWriter() {
                var displayParts;
                var lineStart;
                var indent;
                resetWriter();
                return {
                    displayParts: function () { return displayParts; },
                    writeKeyword: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.keyword); },
                    writeOperator: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.operator); },
                    writePunctuation: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.punctuation); },
                    writeSpace: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.space); },
                    writeStringLiteral: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.stringLiteral); },
                    writeParameter: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.parameterName); },
                    writeSymbol: writeSymbol,
                    writeLine: writeLine,
                    increaseIndent: function () { indent++; },
                    decreaseIndent: function () { indent--; },
                    clear: resetWriter,
                    trackSymbol: function () { }
                };
                function writeIndent() {
                    if (lineStart) {
                        var indentString = ts.getIndentString(indent);
                        if (indentString) {
                            displayParts.push(displayPart(indentString, ts.SymbolDisplayPartKind.space));
                        }
                        lineStart = false;
                    }
                }
                function writeKind(text, kind) {
                    writeIndent();
                    displayParts.push(displayPart(text, kind));
                }
                function writeSymbol(text, symbol) {
                    writeIndent();
                    displayParts.push(symbolPart(text, symbol));
                }
                function writeLine() {
                    displayParts.push(lineBreakPart());
                    lineStart = true;
                }
                function resetWriter() {
                    displayParts = [];
                    lineStart = true;
                    indent = 0;
                }
            }
            function symbolPart(text, symbol) {
                return displayPart(text, displayPartKind(symbol), symbol);
                function displayPartKind(symbol) {
                    var flags = symbol.flags;
                    if (flags & 3 /* Variable */) {
                        return isFirstDeclarationOfSymbolParameter(symbol) ? ts.SymbolDisplayPartKind.parameterName : ts.SymbolDisplayPartKind.localName;
                    }
                    else if (flags & 4 /* Property */) {
                        return ts.SymbolDisplayPartKind.propertyName;
                    }
                    else if (flags & 32768 /* GetAccessor */) {
                        return ts.SymbolDisplayPartKind.propertyName;
                    }
                    else if (flags & 65536 /* SetAccessor */) {
                        return ts.SymbolDisplayPartKind.propertyName;
                    }
                    else if (flags & 8 /* EnumMember */) {
                        return ts.SymbolDisplayPartKind.enumMemberName;
                    }
                    else if (flags & 16 /* Function */) {
                        return ts.SymbolDisplayPartKind.functionName;
                    }
                    else if (flags & 32 /* Class */) {
                        return ts.SymbolDisplayPartKind.className;
                    }
                    else if (flags & 64 /* Interface */) {
                        return ts.SymbolDisplayPartKind.interfaceName;
                    }
                    else if (flags & 384 /* Enum */) {
                        return ts.SymbolDisplayPartKind.enumName;
                    }
                    else if (flags & 1536 /* Module */) {
                        return ts.SymbolDisplayPartKind.moduleName;
                    }
                    else if (flags & 8192 /* Method */) {
                        return ts.SymbolDisplayPartKind.methodName;
                    }
                    else if (flags & 262144 /* TypeParameter */) {
                        return ts.SymbolDisplayPartKind.typeParameterName;
                    }
                    else if (flags & 524288 /* TypeAlias */) {
                        return ts.SymbolDisplayPartKind.aliasName;
                    }
                    else if (flags & 8388608 /* Alias */) {
                        return ts.SymbolDisplayPartKind.aliasName;
                    }
                    return ts.SymbolDisplayPartKind.text;
                }
            }
            ts.symbolPart = symbolPart;
            function displayPart(text, kind, symbol) {
                return {
                    text: text,
                    kind: ts.SymbolDisplayPartKind[kind]
                };
            }
            ts.displayPart = displayPart;
            function spacePart() {
                return displayPart(" ", ts.SymbolDisplayPartKind.space);
            }
            ts.spacePart = spacePart;
            function keywordPart(kind) {
                return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.keyword);
            }
            ts.keywordPart = keywordPart;
            function punctuationPart(kind) {
                return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.punctuation);
            }
            ts.punctuationPart = punctuationPart;
            function operatorPart(kind) {
                return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.operator);
            }
            ts.operatorPart = operatorPart;
            function textOrKeywordPart(text) {
                var kind = ts.stringToToken(text);
                return kind === undefined
                    ? textPart(text)
                    : keywordPart(kind);
            }
            ts.textOrKeywordPart = textOrKeywordPart;
            function textPart(text) {
                return displayPart(text, ts.SymbolDisplayPartKind.text);
            }
            ts.textPart = textPart;
            function lineBreakPart() {
                return displayPart("\n", ts.SymbolDisplayPartKind.lineBreak);
            }
            ts.lineBreakPart = lineBreakPart;
            function mapToDisplayParts(writeDisplayParts) {
                writeDisplayParts(displayPartWriter);
                var result = displayPartWriter.displayParts();
                displayPartWriter.clear();
                return result;
            }
            ts.mapToDisplayParts = mapToDisplayParts;
            function typeToDisplayParts(typechecker, type, enclosingDeclaration, flags) {
                return mapToDisplayParts(function (writer) {
                    typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
                });
            }
            ts.typeToDisplayParts = typeToDisplayParts;
            function symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration, meaning, flags) {
                return mapToDisplayParts(function (writer) {
                    typeChecker.getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags);
                });
            }
            ts.symbolToDisplayParts = symbolToDisplayParts;
            function signatureToDisplayParts(typechecker, signature, enclosingDeclaration, flags) {
                return mapToDisplayParts(function (writer) {
                    typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags);
                });
            }
            ts.signatureToDisplayParts = signatureToDisplayParts;
            function isJavaScript(fileName) {
                return ts.fileExtensionIs(fileName, ".js");
            }
            ts.isJavaScript = isJavaScript;
        })(ts || (ts = {}));
        /// <reference path="formatting.ts"/>
        /// <reference path="..\..\compiler\scanner.ts"/>
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var scanner = ts.createScanner(2 /* Latest */, false);
                var ScanAction;
                (function (ScanAction) {
                    ScanAction[ScanAction["Scan"] = 0] = "Scan";
                    ScanAction[ScanAction["RescanGreaterThanToken"] = 1] = "RescanGreaterThanToken";
                    ScanAction[ScanAction["RescanSlashToken"] = 2] = "RescanSlashToken";
                    ScanAction[ScanAction["RescanTemplateToken"] = 3] = "RescanTemplateToken";
                })(ScanAction || (ScanAction = {}));
                function getFormattingScanner(sourceFile, startPos, endPos) {
                    scanner.setText(sourceFile.text);
                    scanner.setTextPos(startPos);
                    var wasNewLine = true;
                    var leadingTrivia;
                    var trailingTrivia;
                    var savedPos;
                    var lastScanAction;
                    var lastTokenInfo;
                    return {
                        advance: advance,
                        readTokenInfo: readTokenInfo,
                        isOnToken: isOnToken,
                        lastTrailingTriviaWasNewLine: function () { return wasNewLine; },
                        close: function () {
                            lastTokenInfo = undefined;
                            scanner.setText(undefined);
                        }
                    };
                    function advance() {
                        lastTokenInfo = undefined;
                        var isStarted = scanner.getStartPos() !== startPos;
                        if (isStarted) {
                            if (trailingTrivia) {
                                ts.Debug.assert(trailingTrivia.length !== 0);
                                wasNewLine = trailingTrivia[trailingTrivia.length - 1].kind === 4 /* NewLineTrivia */;
                            }
                            else {
                                wasNewLine = false;
                            }
                        }
                        leadingTrivia = undefined;
                        trailingTrivia = undefined;
                        if (!isStarted) {
                            scanner.scan();
                        }
                        var t;
                        var pos = scanner.getStartPos();
                        // Read leading trivia and token
                        while (pos < endPos) {
                            var t_2 = scanner.getToken();
                            if (!ts.isTrivia(t_2)) {
                                break;
                            }
                            // consume leading trivia
                            scanner.scan();
                            var item = {
                                pos: pos,
                                end: scanner.getStartPos(),
                                kind: t_2
                            };
                            pos = scanner.getStartPos();
                            if (!leadingTrivia) {
                                leadingTrivia = [];
                            }
                            leadingTrivia.push(item);
                        }
                        savedPos = scanner.getStartPos();
                    }
                    function shouldRescanGreaterThanToken(node) {
                        if (node) {
                            switch (node.kind) {
                                case 27 /* GreaterThanEqualsToken */:
                                case 60 /* GreaterThanGreaterThanEqualsToken */:
                                case 61 /* GreaterThanGreaterThanGreaterThanEqualsToken */:
                                case 42 /* GreaterThanGreaterThanGreaterThanToken */:
                                case 41 /* GreaterThanGreaterThanToken */:
                                    return true;
                            }
                        }
                        return false;
                    }
                    function shouldRescanSlashToken(container) {
                        return container.kind === 9 /* RegularExpressionLiteral */;
                    }
                    function shouldRescanTemplateToken(container) {
                        return container.kind === 12 /* TemplateMiddle */ ||
                            container.kind === 13 /* TemplateTail */;
                    }
                    function startsWithSlashToken(t) {
                        return t === 36 /* SlashToken */ || t === 57 /* SlashEqualsToken */;
                    }
                    function readTokenInfo(n) {
                        if (!isOnToken()) {
                            // scanner is not on the token (either advance was not called yet or scanner is already past the end position)
                            return {
                                leadingTrivia: leadingTrivia,
                                trailingTrivia: undefined,
                                token: undefined
                            };
                        }
                        // normally scanner returns the smallest available token
                        // check the kind of context node to determine if scanner should have more greedy behavior and consume more text.
                        var expectedScanAction = shouldRescanGreaterThanToken(n)
                            ? 1 /* RescanGreaterThanToken */
                            : shouldRescanSlashToken(n)
                                ? 2 /* RescanSlashToken */
                                : shouldRescanTemplateToken(n)
                                    ? 3 /* RescanTemplateToken */
                                    : 0 /* Scan */;
                        if (lastTokenInfo && expectedScanAction === lastScanAction) {
                            // readTokenInfo was called before with the same expected scan action.
                            // No need to re-scan text, return existing 'lastTokenInfo'
                            // it is ok to call fixTokenKind here since it does not affect
                            // what portion of text is consumed. In opposize rescanning can change it,
                            // i.e. for '>=' when originally scanner eats just one character
                            // and rescanning forces it to consume more.
                            return fixTokenKind(lastTokenInfo, n);
                        }
                        if (scanner.getStartPos() !== savedPos) {
                            ts.Debug.assert(lastTokenInfo !== undefined);
                            // readTokenInfo was called before but scan action differs - rescan text
                            scanner.setTextPos(savedPos);
                            scanner.scan();
                        }
                        var currentToken = scanner.getToken();
                        if (expectedScanAction === 1 /* RescanGreaterThanToken */ && currentToken === 25 /* GreaterThanToken */) {
                            currentToken = scanner.reScanGreaterToken();
                            ts.Debug.assert(n.kind === currentToken);
                            lastScanAction = 1 /* RescanGreaterThanToken */;
                        }
                        else if (expectedScanAction === 2 /* RescanSlashToken */ && startsWithSlashToken(currentToken)) {
                            currentToken = scanner.reScanSlashToken();
                            ts.Debug.assert(n.kind === currentToken);
                            lastScanAction = 2 /* RescanSlashToken */;
                        }
                        else if (expectedScanAction === 3 /* RescanTemplateToken */ && currentToken === 15 /* CloseBraceToken */) {
                            currentToken = scanner.reScanTemplateToken();
                            lastScanAction = 3 /* RescanTemplateToken */;
                        }
                        else {
                            lastScanAction = 0 /* Scan */;
                        }
                        var token = {
                            pos: scanner.getStartPos(),
                            end: scanner.getTextPos(),
                            kind: currentToken
                        };
                        // consume trailing trivia
                        if (trailingTrivia) {
                            trailingTrivia = undefined;
                        }
                        while (scanner.getStartPos() < endPos) {
                            currentToken = scanner.scan();
                            if (!ts.isTrivia(currentToken)) {
                                break;
                            }
                            var trivia = {
                                pos: scanner.getStartPos(),
                                end: scanner.getTextPos(),
                                kind: currentToken
                            };
                            if (!trailingTrivia) {
                                trailingTrivia = [];
                            }
                            trailingTrivia.push(trivia);
                            if (currentToken === 4 /* NewLineTrivia */) {
                                // move past new line
                                scanner.scan();
                                break;
                            }
                        }
                        lastTokenInfo = {
                            leadingTrivia: leadingTrivia,
                            trailingTrivia: trailingTrivia,
                            token: token
                        };
                        return fixTokenKind(lastTokenInfo, n);
                    }
                    function isOnToken() {
                        var current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken();
                        var startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos();
                        return startPos < endPos && current !== 1 /* EndOfFileToken */ && !ts.isTrivia(current);
                    }
                    // when containing node in the tree is token 
                    // but its kind differs from the kind that was returned by the scanner,
                    // then kind needs to be fixed. This might happen in cases 
                    // when parser interprets token differently, i.e keyword treated as identifier
                    function fixTokenKind(tokenInfo, container) {
                        if (ts.isToken(container) && tokenInfo.token.kind !== container.kind) {
                            tokenInfo.token.kind = container.kind;
                        }
                        return tokenInfo;
                    }
                }
                formatting.getFormattingScanner = getFormattingScanner;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        /// <reference path="references.ts"/>
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var FormattingContext = (function () {
                    function FormattingContext(sourceFile, formattingRequestKind) {
                        this.sourceFile = sourceFile;
                        this.formattingRequestKind = formattingRequestKind;
                    }
                    FormattingContext.prototype.updateContext = function (currentRange, currentTokenParent, nextRange, nextTokenParent, commonParent) {
                        ts.Debug.assert(currentRange !== undefined, "currentTokenSpan is null");
                        ts.Debug.assert(currentTokenParent !== undefined, "currentTokenParent is null");
                        ts.Debug.assert(nextRange !== undefined, "nextTokenSpan is null");
                        ts.Debug.assert(nextTokenParent !== undefined, "nextTokenParent is null");
                        ts.Debug.assert(commonParent !== undefined, "commonParent is null");
                        this.currentTokenSpan = currentRange;
                        this.currentTokenParent = currentTokenParent;
                        this.nextTokenSpan = nextRange;
                        this.nextTokenParent = nextTokenParent;
                        this.contextNode = commonParent;
                        // drop cached results
                        this.contextNodeAllOnSameLine = undefined;
                        this.nextNodeAllOnSameLine = undefined;
                        this.tokensAreOnSameLine = undefined;
                        this.contextNodeBlockIsOnOneLine = undefined;
                        this.nextNodeBlockIsOnOneLine = undefined;
                    };
                    FormattingContext.prototype.ContextNodeAllOnSameLine = function () {
                        if (this.contextNodeAllOnSameLine === undefined) {
                            this.contextNodeAllOnSameLine = this.NodeIsOnOneLine(this.contextNode);
                        }
                        return this.contextNodeAllOnSameLine;
                    };
                    FormattingContext.prototype.NextNodeAllOnSameLine = function () {
                        if (this.nextNodeAllOnSameLine === undefined) {
                            this.nextNodeAllOnSameLine = this.NodeIsOnOneLine(this.nextTokenParent);
                        }
                        return this.nextNodeAllOnSameLine;
                    };
                    FormattingContext.prototype.TokensAreOnSameLine = function () {
                        if (this.tokensAreOnSameLine === undefined) {
                            var startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line;
                            var endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line;
                            this.tokensAreOnSameLine = (startLine == endLine);
                        }
                        return this.tokensAreOnSameLine;
                    };
                    FormattingContext.prototype.ContextNodeBlockIsOnOneLine = function () {
                        if (this.contextNodeBlockIsOnOneLine === undefined) {
                            this.contextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.contextNode);
                        }
                        return this.contextNodeBlockIsOnOneLine;
                    };
                    FormattingContext.prototype.NextNodeBlockIsOnOneLine = function () {
                        if (this.nextNodeBlockIsOnOneLine === undefined) {
                            this.nextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.nextTokenParent);
                        }
                        return this.nextNodeBlockIsOnOneLine;
                    };
                    FormattingContext.prototype.NodeIsOnOneLine = function (node) {
                        var startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line;
                        var endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line;
                        return startLine == endLine;
                    };
                    FormattingContext.prototype.BlockIsOnOneLine = function (node) {
                        var openBrace = ts.findChildOfKind(node, 14 /* OpenBraceToken */, this.sourceFile);
                        var closeBrace = ts.findChildOfKind(node, 15 /* CloseBraceToken */, this.sourceFile);
                        if (openBrace && closeBrace) {
                            var startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line;
                            var endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line;
                            return startLine === endLine;
                        }
                        return false;
                    };
                    return FormattingContext;
                })();
                formatting.FormattingContext = FormattingContext;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        /// <reference path="references.ts"/>
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                (function (FormattingRequestKind) {
                    FormattingRequestKind[FormattingRequestKind["FormatDocument"] = 0] = "FormatDocument";
                    FormattingRequestKind[FormattingRequestKind["FormatSelection"] = 1] = "FormatSelection";
                    FormattingRequestKind[FormattingRequestKind["FormatOnEnter"] = 2] = "FormatOnEnter";
                    FormattingRequestKind[FormattingRequestKind["FormatOnSemicolon"] = 3] = "FormatOnSemicolon";
                    FormattingRequestKind[FormattingRequestKind["FormatOnClosingCurlyBrace"] = 4] = "FormatOnClosingCurlyBrace";
                })(formatting.FormattingRequestKind || (formatting.FormattingRequestKind = {}));
                var FormattingRequestKind = formatting.FormattingRequestKind;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        ///<reference path='references.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var Rule = (function () {
                    function Rule(Descriptor, Operation, Flag) {
                        if (Flag === void 0) { Flag = 0 /* None */; }
                        this.Descriptor = Descriptor;
                        this.Operation = Operation;
                        this.Flag = Flag;
                    }
                    Rule.prototype.toString = function () {
                        return "[desc=" + this.Descriptor + "," +
                            "operation=" + this.Operation + "," +
                            "flag=" + this.Flag + "]";
                    };
                    return Rule;
                })();
                formatting.Rule = Rule;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        ///<reference path='references.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                (function (RuleAction) {
                    RuleAction[RuleAction["Ignore"] = 1] = "Ignore";
                    RuleAction[RuleAction["Space"] = 2] = "Space";
                    RuleAction[RuleAction["NewLine"] = 4] = "NewLine";
                    RuleAction[RuleAction["Delete"] = 8] = "Delete";
                })(formatting.RuleAction || (formatting.RuleAction = {}));
                var RuleAction = formatting.RuleAction;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        ///<reference path='references.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var RuleDescriptor = (function () {
                    function RuleDescriptor(LeftTokenRange, RightTokenRange) {
                        this.LeftTokenRange = LeftTokenRange;
                        this.RightTokenRange = RightTokenRange;
                    }
                    RuleDescriptor.prototype.toString = function () {
                        return "[leftRange=" + this.LeftTokenRange + "," +
                            "rightRange=" + this.RightTokenRange + "]";
                    };
                    RuleDescriptor.create1 = function (left, right) {
                        return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), formatting.Shared.TokenRange.FromToken(right));
                    };
                    RuleDescriptor.create2 = function (left, right) {
                        return RuleDescriptor.create4(left, formatting.Shared.TokenRange.FromToken(right));
                    };
                    RuleDescriptor.create3 = function (left, right) {
                        return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), right);
                    };
                    RuleDescriptor.create4 = function (left, right) {
                        return new RuleDescriptor(left, right);
                    };
                    return RuleDescriptor;
                })();
                formatting.RuleDescriptor = RuleDescriptor;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        ///<reference path='references.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                (function (RuleFlags) {
                    RuleFlags[RuleFlags["None"] = 0] = "None";
                    RuleFlags[RuleFlags["CanDeleteNewLines"] = 1] = "CanDeleteNewLines";
                })(formatting.RuleFlags || (formatting.RuleFlags = {}));
                var RuleFlags = formatting.RuleFlags;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        ///<reference path='references.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var RuleOperation = (function () {
                    function RuleOperation() {
                        this.Context = null;
                        this.Action = null;
                    }
                    RuleOperation.prototype.toString = function () {
                        return "[context=" + this.Context + "," +
                            "action=" + this.Action + "]";
                    };
                    RuleOperation.create1 = function (action) {
                        return RuleOperation.create2(formatting.RuleOperationContext.Any, action);
                    };
                    RuleOperation.create2 = function (context, action) {
                        var result = new RuleOperation();
                        result.Context = context;
                        result.Action = action;
                        return result;
                    };
                    return RuleOperation;
                })();
                formatting.RuleOperation = RuleOperation;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        ///<reference path='references.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var RuleOperationContext = (function () {
                    function RuleOperationContext() {
                        var funcs = [];
                        for (var _i = 0; _i < arguments.length; _i++) {
                            funcs[_i - 0] = arguments[_i];
                        }
                        this.customContextChecks = funcs;
                    }
                    RuleOperationContext.prototype.IsAny = function () {
                        return this == RuleOperationContext.Any;
                    };
                    RuleOperationContext.prototype.InContext = function (context) {
                        if (this.IsAny()) {
                            return true;
                        }
                        for (var _i = 0, _a = this.customContextChecks; _i < _a.length; _i++) {
                            var check = _a[_i];
                            if (!check(context)) {
                                return false;
                            }
                        }
                        return true;
                    };
                    RuleOperationContext.Any = new RuleOperationContext();
                    return RuleOperationContext;
                })();
                formatting.RuleOperationContext = RuleOperationContext;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        ///<reference path='references.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var Rules = (function () {
                    function Rules() {
                        ///
                        /// Common Rules
                        ///
                        // Leave comments alone
                        this.IgnoreBeforeComment = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.Comments), formatting.RuleOperation.create1(1 /* Ignore */));
                        this.IgnoreAfterLineComment = new formatting.Rule(formatting.RuleDescriptor.create3(2 /* SingleLineCommentTrivia */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create1(1 /* Ignore */));
                        // Space after keyword but not before ; or : or ?
                        this.NoSpaceBeforeSemicolon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 22 /* SemicolonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.NoSpaceBeforeColon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 51 /* ColonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */));
                        this.NoSpaceBeforeQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 50 /* QuestionToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */));
                        this.SpaceAfterColon = new formatting.Rule(formatting.RuleDescriptor.create3(51 /* ColonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 2 /* Space */));
                        this.SpaceAfterQuestionMarkInConditionalOperator = new formatting.Rule(formatting.RuleDescriptor.create3(50 /* QuestionToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsConditionalOperatorContext), 2 /* Space */));
                        this.NoSpaceAfterQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create3(50 /* QuestionToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.SpaceAfterSemicolon = new formatting.Rule(formatting.RuleDescriptor.create3(22 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2 /* Space */));
                        // Space after }.
                        this.SpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* CloseBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsAfterCodeBlockContext), 2 /* Space */));
                        // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied
                        this.SpaceBetweenCloseBraceAndElse = new formatting.Rule(formatting.RuleDescriptor.create1(15 /* CloseBraceToken */, 76 /* ElseKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2 /* Space */));
                        this.SpaceBetweenCloseBraceAndWhile = new formatting.Rule(formatting.RuleDescriptor.create1(15 /* CloseBraceToken */, 100 /* WhileKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2 /* Space */));
                        this.NoSpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* CloseBraceToken */, formatting.Shared.TokenRange.FromTokens([17 /* CloseParenToken */, 19 /* CloseBracketToken */, 23 /* CommaToken */, 22 /* SemicolonToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        // No space for indexer and dot
                        this.NoSpaceBeforeDot = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 20 /* DotToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.NoSpaceAfterDot = new formatting.Rule(formatting.RuleDescriptor.create3(20 /* DotToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.NoSpaceBeforeOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 18 /* OpenBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.NoSpaceAfterOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create3(18 /* OpenBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.NoSpaceBeforeCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 19 /* CloseBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.NoSpaceAfterCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create3(19 /* CloseBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        // Place a space before open brace in a function declaration
                        this.FunctionOpenBraceLeftTokenRange = formatting.Shared.TokenRange.AnyIncludingMultilineComments;
                        this.SpaceBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 14 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */);
                        // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc)
                        this.TypeScriptOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([65 /* Identifier */, 3 /* MultiLineCommentTrivia */]);
                        this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 14 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */);
                        // Place a space before open brace in a control flow construct
                        this.ControlOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([17 /* CloseParenToken */, 3 /* MultiLineCommentTrivia */, 75 /* DoKeyword */, 96 /* TryKeyword */, 81 /* FinallyKeyword */, 76 /* ElseKeyword */]);
                        this.SpaceBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 14 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */);
                        // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}.
                        this.SpaceAfterOpenBrace = new formatting.Rule(formatting.RuleDescriptor.create3(14 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2 /* Space */));
                        this.SpaceBeforeCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 15 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2 /* Space */));
                        this.NoSpaceBetweenEmptyBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(14 /* OpenBraceToken */, 15 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsObjectContext), 8 /* Delete */));
                        // Insert new line after { and before } in multi-line contexts.
                        this.NewLineAfterOpenBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create3(14 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4 /* NewLine */));
                        // For functions and control block place } on a new line    [multi-line rule]
                        this.NewLineBeforeCloseBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.AnyIncludingMultilineComments, 15 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4 /* NewLine */));
                        // Special handling of unary operators.
                        // Prefix operators generally shouldn't have a space between
                        // them and their target unary expression.
                        this.NoSpaceAfterUnaryPrefixOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.UnaryPrefixOperators, formatting.Shared.TokenRange.UnaryPrefixExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */));
                        this.NoSpaceAfterUnaryPreincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(38 /* PlusPlusToken */, formatting.Shared.TokenRange.UnaryPreincrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.NoSpaceAfterUnaryPredecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(39 /* MinusMinusToken */, formatting.Shared.TokenRange.UnaryPredecrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.NoSpaceBeforeUnaryPostincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostincrementExpressions, 38 /* PlusPlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.NoSpaceBeforeUnaryPostdecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostdecrementExpressions, 39 /* MinusMinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        // More unary operator special-casing.
                        // DevDiv 181814:  Be careful when removing leading whitespace
                        // around unary operators.  Examples:
                        //      1 - -2  --X-->  1--2
                        //      a + ++b --X-->  a+++b
                        this.SpaceAfterPostincrementWhenFollowedByAdd = new formatting.Rule(formatting.RuleDescriptor.create1(38 /* PlusPlusToken */, 33 /* PlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */));
                        this.SpaceAfterAddWhenFollowedByUnaryPlus = new formatting.Rule(formatting.RuleDescriptor.create1(33 /* PlusToken */, 33 /* PlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */));
                        this.SpaceAfterAddWhenFollowedByPreincrement = new formatting.Rule(formatting.RuleDescriptor.create1(33 /* PlusToken */, 38 /* PlusPlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */));
                        this.SpaceAfterPostdecrementWhenFollowedBySubtract = new formatting.Rule(formatting.RuleDescriptor.create1(39 /* MinusMinusToken */, 34 /* MinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */));
                        this.SpaceAfterSubtractWhenFollowedByUnaryMinus = new formatting.Rule(formatting.RuleDescriptor.create1(34 /* MinusToken */, 34 /* MinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */));
                        this.SpaceAfterSubtractWhenFollowedByPredecrement = new formatting.Rule(formatting.RuleDescriptor.create1(34 /* MinusToken */, 39 /* MinusMinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */));
                        this.NoSpaceBeforeComma = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 23 /* CommaToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.SpaceAfterCertainKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([98 /* VarKeyword */, 94 /* ThrowKeyword */, 88 /* NewKeyword */, 74 /* DeleteKeyword */, 90 /* ReturnKeyword */, 97 /* TypeOfKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2 /* Space */));
                        this.SpaceAfterLetConstInVariableDeclaration = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([104 /* LetKeyword */, 70 /* ConstKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsStartOfVariableDeclarationList), 2 /* Space */));
                        this.NoSpaceBeforeOpenParenInFuncCall = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsFunctionCallOrNewContext, Rules.IsPreviousTokenNotComma), 8 /* Delete */));
                        this.SpaceAfterFunctionInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create3(83 /* FunctionKeyword */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */));
                        this.NoSpaceBeforeOpenParenInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsFunctionDeclContext), 8 /* Delete */));
                        this.SpaceAfterVoidOperator = new formatting.Rule(formatting.RuleDescriptor.create3(99 /* VoidKeyword */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsVoidOpContext), 2 /* Space */));
                        this.NoSpaceBetweenReturnAndSemicolon = new formatting.Rule(formatting.RuleDescriptor.create1(90 /* ReturnKeyword */, 22 /* SemicolonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        // Add a space between statements. All keywords except (do,else,case) has open/close parens after them.
                        // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any]
                        this.SpaceBetweenStatements = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([17 /* CloseParenToken */, 75 /* DoKeyword */, 76 /* ElseKeyword */, 67 /* CaseKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotForContext), 2 /* Space */));
                        // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter.
                        this.SpaceAfterTryFinally = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([96 /* TryKeyword */, 81 /* FinallyKeyword */]), 14 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2 /* Space */));
                        //      get x() {}
                        //      set x(val) {}
                        this.SpaceAfterGetSetInMember = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([116 /* GetKeyword */, 120 /* SetKeyword */]), 65 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */));
                        // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options.
                        this.SpaceBeforeBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryKeywordOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */));
                        this.SpaceAfterBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryKeywordOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */));
                        // TypeScript-specific higher priority rules
                        // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses
                        this.NoSpaceAfterConstructor = new formatting.Rule(formatting.RuleDescriptor.create1(114 /* ConstructorKeyword */, 16 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        // Use of module as a function call. e.g.: import m2 = module("m2");
                        this.NoSpaceAfterModuleImport = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([117 /* ModuleKeyword */, 118 /* RequireKeyword */]), 16 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        // Add a space around certain TypeScript keywords
                        this.SpaceAfterCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([69 /* ClassKeyword */, 115 /* DeclareKeyword */, 77 /* EnumKeyword */, 78 /* ExportKeyword */, 79 /* ExtendsKeyword */, 116 /* GetKeyword */, 102 /* ImplementsKeyword */, 85 /* ImportKeyword */, 103 /* InterfaceKeyword */, 117 /* ModuleKeyword */, 106 /* PrivateKeyword */, 108 /* PublicKeyword */, 120 /* SetKeyword */, 109 /* StaticKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2 /* Space */));
                        this.SpaceBeforeCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([79 /* ExtendsKeyword */, 102 /* ImplementsKeyword */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2 /* Space */));
                        // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" {
                        this.SpaceAfterModuleName = new formatting.Rule(formatting.RuleDescriptor.create1(8 /* StringLiteral */, 14 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsModuleDeclContext), 2 /* Space */));
                        // Lambda expressions
                        this.SpaceAfterArrow = new formatting.Rule(formatting.RuleDescriptor.create3(32 /* EqualsGreaterThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2 /* Space */));
                        // Optional parameters and let args
                        this.NoSpaceAfterEllipsis = new formatting.Rule(formatting.RuleDescriptor.create1(21 /* DotDotDotToken */, 65 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.NoSpaceAfterOptionalParameters = new formatting.Rule(formatting.RuleDescriptor.create3(50 /* QuestionToken */, formatting.Shared.TokenRange.FromTokens([17 /* CloseParenToken */, 23 /* CommaToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */));
                        // generics
                        this.NoSpaceBeforeOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.TypeNames, 24 /* LessThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8 /* Delete */));
                        this.NoSpaceBetweenCloseParenAndAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create1(17 /* CloseParenToken */, 24 /* LessThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8 /* Delete */));
                        this.NoSpaceAfterOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(24 /* LessThanToken */, formatting.Shared.TokenRange.TypeNames), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8 /* Delete */));
                        this.NoSpaceBeforeCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 25 /* GreaterThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8 /* Delete */));
                        this.NoSpaceAfterCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(25 /* GreaterThanToken */, formatting.Shared.TokenRange.FromTokens([16 /* OpenParenToken */, 18 /* OpenBracketToken */, 25 /* GreaterThanToken */, 23 /* CommaToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8 /* Delete */));
                        // Remove spaces in empty interface literals. e.g.: x: {}
                        this.NoSpaceBetweenEmptyInterfaceBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(14 /* OpenBraceToken */, 15 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsObjectTypeContext), 8 /* Delete */));
                        // decorators
                        this.SpaceBeforeAt = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 52 /* AtToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2 /* Space */));
                        this.NoSpaceAfterAt = new formatting.Rule(formatting.RuleDescriptor.create3(52 /* AtToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.SpaceAfterDecorator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([65 /* Identifier */, 78 /* ExportKeyword */, 73 /* DefaultKeyword */, 69 /* ClassKeyword */, 109 /* StaticKeyword */, 108 /* PublicKeyword */, 106 /* PrivateKeyword */, 107 /* ProtectedKeyword */, 116 /* GetKeyword */, 120 /* SetKeyword */, 18 /* OpenBracketToken */, 35 /* AsteriskToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsEndOfDecoratorContextOnSameLine), 2 /* Space */));
                        // These rules are higher in priority than user-configurable rules.
                        this.HighPriorityCommonRules =
                            [
                                this.IgnoreBeforeComment, this.IgnoreAfterLineComment,
                                this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQuestionMark, this.SpaceAfterQuestionMarkInConditionalOperator,
                                this.NoSpaceAfterQuestionMark,
                                this.NoSpaceBeforeDot, this.NoSpaceAfterDot,
                                this.NoSpaceAfterUnaryPrefixOperator,
                                this.NoSpaceAfterUnaryPreincrementOperator, this.NoSpaceAfterUnaryPredecrementOperator,
                                this.NoSpaceBeforeUnaryPostincrementOperator, this.NoSpaceBeforeUnaryPostdecrementOperator,
                                this.SpaceAfterPostincrementWhenFollowedByAdd,
                                this.SpaceAfterAddWhenFollowedByUnaryPlus, this.SpaceAfterAddWhenFollowedByPreincrement,
                                this.SpaceAfterPostdecrementWhenFollowedBySubtract,
                                this.SpaceAfterSubtractWhenFollowedByUnaryMinus, this.SpaceAfterSubtractWhenFollowedByPredecrement,
                                this.NoSpaceAfterCloseBrace,
                                this.SpaceAfterOpenBrace, this.SpaceBeforeCloseBrace, this.NewLineBeforeCloseBraceInBlockContext,
                                this.SpaceAfterCloseBrace, this.SpaceBetweenCloseBraceAndElse, this.SpaceBetweenCloseBraceAndWhile, this.NoSpaceBetweenEmptyBraceBrackets,
                                this.SpaceAfterFunctionInFuncDecl, this.NewLineAfterOpenBraceInBlockContext, this.SpaceAfterGetSetInMember,
                                this.NoSpaceBetweenReturnAndSemicolon,
                                this.SpaceAfterCertainKeywords,
                                this.SpaceAfterLetConstInVariableDeclaration,
                                this.NoSpaceBeforeOpenParenInFuncCall,
                                this.SpaceBeforeBinaryKeywordOperator, this.SpaceAfterBinaryKeywordOperator,
                                this.SpaceAfterVoidOperator,
                                // TypeScript-specific rules
                                this.NoSpaceAfterConstructor, this.NoSpaceAfterModuleImport,
                                this.SpaceAfterCertainTypeScriptKeywords, this.SpaceBeforeCertainTypeScriptKeywords,
                                this.SpaceAfterModuleName,
                                this.SpaceAfterArrow,
                                this.NoSpaceAfterEllipsis,
                                this.NoSpaceAfterOptionalParameters,
                                this.NoSpaceBetweenEmptyInterfaceBraceBrackets,
                                this.NoSpaceBeforeOpenAngularBracket,
                                this.NoSpaceBetweenCloseParenAndAngularBracket,
                                this.NoSpaceAfterOpenAngularBracket,
                                this.NoSpaceBeforeCloseAngularBracket,
                                this.NoSpaceAfterCloseAngularBracket,
                                this.SpaceBeforeAt,
                                this.NoSpaceAfterAt,
                                this.SpaceAfterDecorator,
                            ];
                        // These rules are lower in priority than user-configurable rules.
                        this.LowPriorityCommonRules =
                            [
                                this.NoSpaceBeforeSemicolon,
                                this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock,
                                this.NoSpaceBeforeComma,
                                this.NoSpaceBeforeOpenBracket, this.NoSpaceAfterOpenBracket,
                                this.NoSpaceBeforeCloseBracket, this.NoSpaceAfterCloseBracket,
                                this.SpaceAfterSemicolon,
                                this.NoSpaceBeforeOpenParenInFuncDecl,
                                this.SpaceBetweenStatements, this.SpaceAfterTryFinally
                            ];
                        ///
                        /// Rules controlled by user options
                        ///
                        // Insert space after comma delimiter
                        this.SpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* CommaToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2 /* Space */));
                        this.NoSpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* CommaToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        // Insert space before and after binary operators
                        this.SpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */));
                        this.SpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */));
                        this.NoSpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 8 /* Delete */));
                        this.NoSpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 8 /* Delete */));
                        // Insert space after keywords in control flow statements
                        this.SpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 16 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 2 /* Space */));
                        this.NoSpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 16 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 8 /* Delete */));
                        // Open Brace braces after function
                        //TypeScript: Function can have return types, which can be made of tons of different token kinds
                        this.NewLineBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 14 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */);
                        // Open Brace braces after TypeScript module/class/interface
                        this.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 14 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */);
                        // Open Brace braces after control block
                        this.NewLineBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 14 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */);
                        // Insert space after semicolon in for statement
                        this.SpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(22 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsForContext), 2 /* Space */));
                        this.NoSpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(22 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsForContext), 8 /* Delete */));
                        // Insert space after opening and before closing nonempty parenthesis
                        this.SpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(16 /* OpenParenToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2 /* Space */));
                        this.SpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2 /* Space */));
                        this.NoSpaceBetweenParens = new formatting.Rule(formatting.RuleDescriptor.create1(16 /* OpenParenToken */, 17 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.NoSpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(16 /* OpenParenToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        this.NoSpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8 /* Delete */));
                        // Insert space after function keyword for anonymous functions
                        this.SpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(83 /* FunctionKeyword */, 16 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */));
                        this.NoSpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(83 /* FunctionKeyword */, 16 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 8 /* Delete */));
                    }
                    Rules.prototype.getRuleName = function (rule) {
                        var o = this;
                        for (var name_23 in o) {
                            if (o[name_23] === rule) {
                                return name_23;
                            }
                        }
                        throw new Error("Unknown rule");
                    };
                    ///
                    /// Contexts
                    ///
                    Rules.IsForContext = function (context) {
                        return context.contextNode.kind === 186 /* ForStatement */;
                    };
                    Rules.IsNotForContext = function (context) {
                        return !Rules.IsForContext(context);
                    };
                    Rules.IsBinaryOpContext = function (context) {
                        switch (context.contextNode.kind) {
                            case 169 /* BinaryExpression */:
                            case 170 /* ConditionalExpression */:
                                return true;
                            // equals in binding elements: function foo([[x, y] = [1, 2]])
                            case 152 /* BindingElement */:
                            // equals in type X = ...
                            case 203 /* TypeAliasDeclaration */:
                            // equal in import a = module('a');
                            case 208 /* ImportEqualsDeclaration */:
                            // equal in let a = 0;
                            case 198 /* VariableDeclaration */:
                            // equal in p = 0;
                            case 129 /* Parameter */:
                            case 226 /* EnumMember */:
                            case 132 /* PropertyDeclaration */:
                            case 131 /* PropertySignature */:
                                return context.currentTokenSpan.kind === 53 /* EqualsToken */ || context.nextTokenSpan.kind === 53 /* EqualsToken */;
                            // "in" keyword in for (let x in []) { }
                            case 187 /* ForInStatement */:
                                return context.currentTokenSpan.kind === 86 /* InKeyword */ || context.nextTokenSpan.kind === 86 /* InKeyword */;
                            // Technically, "of" is not a binary operator, but format it the same way as "in"
                            case 188 /* ForOfStatement */:
                                return context.currentTokenSpan.kind === 125 /* OfKeyword */ || context.nextTokenSpan.kind === 125 /* OfKeyword */;
                        }
                        return false;
                    };
                    Rules.IsNotBinaryOpContext = function (context) {
                        return !Rules.IsBinaryOpContext(context);
                    };
                    Rules.IsConditionalOperatorContext = function (context) {
                        return context.contextNode.kind === 170 /* ConditionalExpression */;
                    };
                    Rules.IsSameLineTokenOrBeforeMultilineBlockContext = function (context) {
                        //// This check is mainly used inside SpaceBeforeOpenBraceInControl and SpaceBeforeOpenBraceInFunction.
                        ////
                        //// Ex: 
                        //// if (1)     { ....
                        ////      * ) and { are on the same line so apply the rule. Here we don't care whether it's same or multi block context
                        ////
                        //// Ex: 
                        //// if (1)
                        //// { ... }
                        ////      * ) and { are on differnet lines. We only need to format if the block is multiline context. So in this case we don't format.
                        ////
                        //// Ex:
                        //// if (1) 
                        //// { ...
                        //// }
                        ////      * ) and { are on differnet lines. We only need to format if the block is multiline context. So in this case we format.
                        return context.TokensAreOnSameLine() || Rules.IsBeforeMultilineBlockContext(context);
                    };
                    // This check is done before an open brace in a control construct, a function, or a typescript block declaration
                    Rules.IsBeforeMultilineBlockContext = function (context) {
                        return Rules.IsBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine());
                    };
                    Rules.IsMultilineBlockContext = function (context) {
                        return Rules.IsBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
                    };
                    Rules.IsSingleLineBlockContext = function (context) {
                        return Rules.IsBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
                    };
                    Rules.IsBlockContext = function (context) {
                        return Rules.NodeIsBlockContext(context.contextNode);
                    };
                    Rules.IsBeforeBlockContext = function (context) {
                        return Rules.NodeIsBlockContext(context.nextTokenParent);
                    };
                    // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children
                    Rules.NodeIsBlockContext = function (node) {
                        if (Rules.NodeIsTypeScriptDeclWithBlockContext(node)) {
                            // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc).
                            return true;
                        }
                        switch (node.kind) {
                            case 179 /* Block */:
                            case 207 /* CaseBlock */:
                            case 154 /* ObjectLiteralExpression */:
                            case 206 /* ModuleBlock */:
                                return true;
                        }
                        return false;
                    };
                    Rules.IsFunctionDeclContext = function (context) {
                        switch (context.contextNode.kind) {
                            case 200 /* FunctionDeclaration */:
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                            //case SyntaxKind.MemberFunctionDeclaration:
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                            ///case SyntaxKind.MethodSignature:
                            case 138 /* CallSignature */:
                            case 162 /* FunctionExpression */:
                            case 135 /* Constructor */:
                            case 163 /* ArrowFunction */:
                            //case SyntaxKind.ConstructorDeclaration:
                            //case SyntaxKind.SimpleArrowFunctionExpression:
                            //case SyntaxKind.ParenthesizedArrowFunctionExpression:
                            case 202 /* InterfaceDeclaration */:
                                return true;
                        }
                        return false;
                    };
                    Rules.IsTypeScriptDeclWithBlockContext = function (context) {
                        return Rules.NodeIsTypeScriptDeclWithBlockContext(context.contextNode);
                    };
                    Rules.NodeIsTypeScriptDeclWithBlockContext = function (node) {
                        switch (node.kind) {
                            case 201 /* ClassDeclaration */:
                            case 202 /* InterfaceDeclaration */:
                            case 204 /* EnumDeclaration */:
                            case 145 /* TypeLiteral */:
                            case 205 /* ModuleDeclaration */:
                                return true;
                        }
                        return false;
                    };
                    Rules.IsAfterCodeBlockContext = function (context) {
                        switch (context.currentTokenParent.kind) {
                            case 201 /* ClassDeclaration */:
                            case 205 /* ModuleDeclaration */:
                            case 204 /* EnumDeclaration */:
                            case 179 /* Block */:
                            case 223 /* CatchClause */:
                            case 206 /* ModuleBlock */:
                            case 193 /* SwitchStatement */:
                                return true;
                        }
                        return false;
                    };
                    Rules.IsControlDeclContext = function (context) {
                        switch (context.contextNode.kind) {
                            case 183 /* IfStatement */:
                            case 193 /* SwitchStatement */:
                            case 186 /* ForStatement */:
                            case 187 /* ForInStatement */:
                            case 188 /* ForOfStatement */:
                            case 185 /* WhileStatement */:
                            case 196 /* TryStatement */:
                            case 184 /* DoStatement */:
                            case 192 /* WithStatement */:
                            // TODO
                            // case SyntaxKind.ElseClause:
                            case 223 /* CatchClause */:
                                return true;
                            default:
                                return false;
                        }
                    };
                    Rules.IsObjectContext = function (context) {
                        return context.contextNode.kind === 154 /* ObjectLiteralExpression */;
                    };
                    Rules.IsFunctionCallContext = function (context) {
                        return context.contextNode.kind === 157 /* CallExpression */;
                    };
                    Rules.IsNewContext = function (context) {
                        return context.contextNode.kind === 158 /* NewExpression */;
                    };
                    Rules.IsFunctionCallOrNewContext = function (context) {
                        return Rules.IsFunctionCallContext(context) || Rules.IsNewContext(context);
                    };
                    Rules.IsPreviousTokenNotComma = function (context) {
                        return context.currentTokenSpan.kind !== 23 /* CommaToken */;
                    };
                    Rules.IsSameLineTokenContext = function (context) {
                        return context.TokensAreOnSameLine();
                    };
                    Rules.IsEndOfDecoratorContextOnSameLine = function (context) {
                        return context.TokensAreOnSameLine() &&
                            context.contextNode.decorators &&
                            Rules.NodeIsInDecoratorContext(context.currentTokenParent) &&
                            !Rules.NodeIsInDecoratorContext(context.nextTokenParent);
                    };
                    Rules.NodeIsInDecoratorContext = function (node) {
                        while (ts.isExpression(node)) {
                            node = node.parent;
                        }
                        return node.kind === 130 /* Decorator */;
                    };
                    Rules.IsStartOfVariableDeclarationList = function (context) {
                        return context.currentTokenParent.kind === 199 /* VariableDeclarationList */ &&
                            context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos;
                    };
                    Rules.IsNotFormatOnEnter = function (context) {
                        return context.formattingRequestKind != 2 /* FormatOnEnter */;
                    };
                    Rules.IsModuleDeclContext = function (context) {
                        return context.contextNode.kind === 205 /* ModuleDeclaration */;
                    };
                    Rules.IsObjectTypeContext = function (context) {
                        return context.contextNode.kind === 145 /* TypeLiteral */; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration;
                    };
                    Rules.IsTypeArgumentOrParameter = function (token, parent) {
                        if (token.kind !== 24 /* LessThanToken */ && token.kind !== 25 /* GreaterThanToken */) {
                            return false;
                        }
                        switch (parent.kind) {
                            case 141 /* TypeReference */:
                            case 201 /* ClassDeclaration */:
                            case 202 /* InterfaceDeclaration */:
                            case 200 /* FunctionDeclaration */:
                            case 162 /* FunctionExpression */:
                            case 163 /* ArrowFunction */:
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                            case 138 /* CallSignature */:
                            case 139 /* ConstructSignature */:
                            case 157 /* CallExpression */:
                            case 158 /* NewExpression */:
                                return true;
                            default:
                                return false;
                        }
                    };
                    Rules.IsTypeArgumentOrParameterContext = function (context) {
                        return Rules.IsTypeArgumentOrParameter(context.currentTokenSpan, context.currentTokenParent) ||
                            Rules.IsTypeArgumentOrParameter(context.nextTokenSpan, context.nextTokenParent);
                    };
                    Rules.IsVoidOpContext = function (context) {
                        return context.currentTokenSpan.kind === 99 /* VoidKeyword */ && context.currentTokenParent.kind === 166 /* VoidExpression */;
                    };
                    return Rules;
                })();
                formatting.Rules = Rules;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        ///<reference path='references.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var RulesMap = (function () {
                    function RulesMap() {
                        this.map = [];
                        this.mapRowLength = 0;
                    }
                    RulesMap.create = function (rules) {
                        var result = new RulesMap();
                        result.Initialize(rules);
                        return result;
                    };
                    RulesMap.prototype.Initialize = function (rules) {
                        this.mapRowLength = 125 /* LastToken */ + 1;
                        this.map = new Array(this.mapRowLength * this.mapRowLength); //new Array<RulesBucket>(this.mapRowLength * this.mapRowLength);
                        // This array is used only during construction of the rulesbucket in the map
                        var rulesBucketConstructionStateList = new Array(this.map.length); //new Array<RulesBucketConstructionState>(this.map.length);
                        this.FillRules(rules, rulesBucketConstructionStateList);
                        return this.map;
                    };
                    RulesMap.prototype.FillRules = function (rules, rulesBucketConstructionStateList) {
                        var _this = this;
                        rules.forEach(function (rule) {
                            _this.FillRule(rule, rulesBucketConstructionStateList);
                        });
                    };
                    RulesMap.prototype.GetRuleBucketIndex = function (row, column) {
                        var rulesBucketIndex = (row * this.mapRowLength) + column;
                        //Debug.Assert(rulesBucketIndex < this.map.Length, "Trying to access an index outside the array.");
                        return rulesBucketIndex;
                    };
                    RulesMap.prototype.FillRule = function (rule, rulesBucketConstructionStateList) {
                        var _this = this;
                        var specificRule = rule.Descriptor.LeftTokenRange != formatting.Shared.TokenRange.Any &&
                            rule.Descriptor.RightTokenRange != formatting.Shared.TokenRange.Any;
                        rule.Descriptor.LeftTokenRange.GetTokens().forEach(function (left) {
                            rule.Descriptor.RightTokenRange.GetTokens().forEach(function (right) {
                                var rulesBucketIndex = _this.GetRuleBucketIndex(left, right);
                                var rulesBucket = _this.map[rulesBucketIndex];
                                if (rulesBucket == undefined) {
                                    rulesBucket = _this.map[rulesBucketIndex] = new RulesBucket();
                                }
                                rulesBucket.AddRule(rule, specificRule, rulesBucketConstructionStateList, rulesBucketIndex);
                            });
                        });
                    };
                    RulesMap.prototype.GetRule = function (context) {
                        var bucketIndex = this.GetRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind);
                        var bucket = this.map[bucketIndex];
                        if (bucket != null) {
                            for (var _i = 0, _a = bucket.Rules(); _i < _a.length; _i++) {
                                var rule = _a[_i];
                                if (rule.Operation.Context.InContext(context)) {
                                    return rule;
                                }
                            }
                        }
                        return null;
                    };
                    return RulesMap;
                })();
                formatting.RulesMap = RulesMap;
                var MaskBitSize = 5;
                var Mask = 0x1f;
                (function (RulesPosition) {
                    RulesPosition[RulesPosition["IgnoreRulesSpecific"] = 0] = "IgnoreRulesSpecific";
                    RulesPosition[RulesPosition["IgnoreRulesAny"] = MaskBitSize * 1] = "IgnoreRulesAny";
                    RulesPosition[RulesPosition["ContextRulesSpecific"] = MaskBitSize * 2] = "ContextRulesSpecific";
                    RulesPosition[RulesPosition["ContextRulesAny"] = MaskBitSize * 3] = "ContextRulesAny";
                    RulesPosition[RulesPosition["NoContextRulesSpecific"] = MaskBitSize * 4] = "NoContextRulesSpecific";
                    RulesPosition[RulesPosition["NoContextRulesAny"] = MaskBitSize * 5] = "NoContextRulesAny";
                })(formatting.RulesPosition || (formatting.RulesPosition = {}));
                var RulesPosition = formatting.RulesPosition;
                var RulesBucketConstructionState = (function () {
                    function RulesBucketConstructionState() {
                        //// The Rules list contains all the inserted rules into a rulebucket in the following order:
                        ////    1- Ignore rules with specific token combination
                        ////    2- Ignore rules with any token combination
                        ////    3- Context rules with specific token combination
                        ////    4- Context rules with any token combination
                        ////    5- Non-context rules with specific token combination
                        ////    6- Non-context rules with any token combination
                        //// 
                        //// The member rulesInsertionIndexBitmap is used to describe the number of rules
                        //// in each sub-bucket (above) hence can be used to know the index of where to insert 
                        //// the next rule. It's a bitmap which contains 6 different sections each is given 5 bits.
                        ////
                        //// Example:
                        //// In order to insert a rule to the end of sub-bucket (3), we get the index by adding
                        //// the values in the bitmap segments 3rd, 2nd, and 1st.
                        this.rulesInsertionIndexBitmap = 0;
                    }
                    RulesBucketConstructionState.prototype.GetInsertionIndex = function (maskPosition) {
                        var index = 0;
                        var pos = 0;
                        var indexBitmap = this.rulesInsertionIndexBitmap;
                        while (pos <= maskPosition) {
                            index += (indexBitmap & Mask);
                            indexBitmap >>= MaskBitSize;
                            pos += MaskBitSize;
                        }
                        return index;
                    };
                    RulesBucketConstructionState.prototype.IncreaseInsertionIndex = function (maskPosition) {
                        var value = (this.rulesInsertionIndexBitmap >> maskPosition) & Mask;
                        value++;
                        ts.Debug.assert((value & Mask) == value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules.");
                        var temp = this.rulesInsertionIndexBitmap & ~(Mask << maskPosition);
                        temp |= value << maskPosition;
                        this.rulesInsertionIndexBitmap = temp;
                    };
                    return RulesBucketConstructionState;
                })();
                formatting.RulesBucketConstructionState = RulesBucketConstructionState;
                var RulesBucket = (function () {
                    function RulesBucket() {
                        this.rules = [];
                    }
                    RulesBucket.prototype.Rules = function () {
                        return this.rules;
                    };
                    RulesBucket.prototype.AddRule = function (rule, specificTokens, constructionState, rulesBucketIndex) {
                        var position;
                        if (rule.Operation.Action == 1 /* Ignore */) {
                            position = specificTokens ?
                                RulesPosition.IgnoreRulesSpecific :
                                RulesPosition.IgnoreRulesAny;
                        }
                        else if (!rule.Operation.Context.IsAny()) {
                            position = specificTokens ?
                                RulesPosition.ContextRulesSpecific :
                                RulesPosition.ContextRulesAny;
                        }
                        else {
                            position = specificTokens ?
                                RulesPosition.NoContextRulesSpecific :
                                RulesPosition.NoContextRulesAny;
                        }
                        var state = constructionState[rulesBucketIndex];
                        if (state === undefined) {
                            state = constructionState[rulesBucketIndex] = new RulesBucketConstructionState();
                        }
                        var index = state.GetInsertionIndex(position);
                        this.rules.splice(index, 0, rule);
                        state.IncreaseInsertionIndex(position);
                    };
                    return RulesBucket;
                })();
                formatting.RulesBucket = RulesBucket;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        ///<reference path='references.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var Shared;
                (function (Shared) {
                    var TokenRangeAccess = (function () {
                        function TokenRangeAccess(from, to, except) {
                            this.tokens = [];
                            for (var token = from; token <= to; token++) {
                                if (except.indexOf(token) < 0) {
                                    this.tokens.push(token);
                                }
                            }
                        }
                        TokenRangeAccess.prototype.GetTokens = function () {
                            return this.tokens;
                        };
                        TokenRangeAccess.prototype.Contains = function (token) {
                            return this.tokens.indexOf(token) >= 0;
                        };
                        return TokenRangeAccess;
                    })();
                    Shared.TokenRangeAccess = TokenRangeAccess;
                    var TokenValuesAccess = (function () {
                        function TokenValuesAccess(tks) {
                            this.tokens = tks && tks.length ? tks : [];
                        }
                        TokenValuesAccess.prototype.GetTokens = function () {
                            return this.tokens;
                        };
                        TokenValuesAccess.prototype.Contains = function (token) {
                            return this.tokens.indexOf(token) >= 0;
                        };
                        return TokenValuesAccess;
                    })();
                    Shared.TokenValuesAccess = TokenValuesAccess;
                    var TokenSingleValueAccess = (function () {
                        function TokenSingleValueAccess(token) {
                            this.token = token;
                        }
                        TokenSingleValueAccess.prototype.GetTokens = function () {
                            return [this.token];
                        };
                        TokenSingleValueAccess.prototype.Contains = function (tokenValue) {
                            return tokenValue == this.token;
                        };
                        return TokenSingleValueAccess;
                    })();
                    Shared.TokenSingleValueAccess = TokenSingleValueAccess;
                    var TokenAllAccess = (function () {
                        function TokenAllAccess() {
                        }
                        TokenAllAccess.prototype.GetTokens = function () {
                            var result = [];
                            for (var token = 0 /* FirstToken */; token <= 125 /* LastToken */; token++) {
                                result.push(token);
                            }
                            return result;
                        };
                        TokenAllAccess.prototype.Contains = function (tokenValue) {
                            return true;
                        };
                        TokenAllAccess.prototype.toString = function () {
                            return "[allTokens]";
                        };
                        return TokenAllAccess;
                    })();
                    Shared.TokenAllAccess = TokenAllAccess;
                    var TokenRange = (function () {
                        function TokenRange(tokenAccess) {
                            this.tokenAccess = tokenAccess;
                        }
                        TokenRange.FromToken = function (token) {
                            return new TokenRange(new TokenSingleValueAccess(token));
                        };
                        TokenRange.FromTokens = function (tokens) {
                            return new TokenRange(new TokenValuesAccess(tokens));
                        };
                        TokenRange.FromRange = function (f, to, except) {
                            if (except === void 0) { except = []; }
                            return new TokenRange(new TokenRangeAccess(f, to, except));
                        };
                        TokenRange.AllTokens = function () {
                            return new TokenRange(new TokenAllAccess());
                        };
                        TokenRange.prototype.GetTokens = function () {
                            return this.tokenAccess.GetTokens();
                        };
                        TokenRange.prototype.Contains = function (token) {
                            return this.tokenAccess.Contains(token);
                        };
                        TokenRange.prototype.toString = function () {
                            return this.tokenAccess.toString();
                        };
                        TokenRange.Any = TokenRange.AllTokens();
                        TokenRange.AnyIncludingMultilineComments = TokenRange.FromTokens(TokenRange.Any.GetTokens().concat([3 /* MultiLineCommentTrivia */]));
                        TokenRange.Keywords = TokenRange.FromRange(66 /* FirstKeyword */, 125 /* LastKeyword */);
                        TokenRange.BinaryOperators = TokenRange.FromRange(24 /* FirstBinaryOperator */, 64 /* LastBinaryOperator */);
                        TokenRange.BinaryKeywordOperators = TokenRange.FromTokens([86 /* InKeyword */, 87 /* InstanceOfKeyword */, 125 /* OfKeyword */]);
                        TokenRange.UnaryPrefixOperators = TokenRange.FromTokens([38 /* PlusPlusToken */, 39 /* MinusMinusToken */, 47 /* TildeToken */, 46 /* ExclamationToken */]);
                        TokenRange.UnaryPrefixExpressions = TokenRange.FromTokens([7 /* NumericLiteral */, 65 /* Identifier */, 16 /* OpenParenToken */, 18 /* OpenBracketToken */, 14 /* OpenBraceToken */, 93 /* ThisKeyword */, 88 /* NewKeyword */]);
                        TokenRange.UnaryPreincrementExpressions = TokenRange.FromTokens([65 /* Identifier */, 16 /* OpenParenToken */, 93 /* ThisKeyword */, 88 /* NewKeyword */]);
                        TokenRange.UnaryPostincrementExpressions = TokenRange.FromTokens([65 /* Identifier */, 17 /* CloseParenToken */, 19 /* CloseBracketToken */, 88 /* NewKeyword */]);
                        TokenRange.UnaryPredecrementExpressions = TokenRange.FromTokens([65 /* Identifier */, 16 /* OpenParenToken */, 93 /* ThisKeyword */, 88 /* NewKeyword */]);
                        TokenRange.UnaryPostdecrementExpressions = TokenRange.FromTokens([65 /* Identifier */, 17 /* CloseParenToken */, 19 /* CloseBracketToken */, 88 /* NewKeyword */]);
                        TokenRange.Comments = TokenRange.FromTokens([2 /* SingleLineCommentTrivia */, 3 /* MultiLineCommentTrivia */]);
                        TokenRange.TypeNames = TokenRange.FromTokens([65 /* Identifier */, 119 /* NumberKeyword */, 121 /* StringKeyword */, 113 /* BooleanKeyword */, 122 /* SymbolKeyword */, 99 /* VoidKeyword */, 112 /* AnyKeyword */]);
                        return TokenRange;
                    })();
                    Shared.TokenRange = TokenRange;
                })(Shared = formatting.Shared || (formatting.Shared = {}));
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        ///<reference path='..\services.ts' />
        ///<reference path='formattingContext.ts' />
        ///<reference path='formattingRequestKind.ts' />
        ///<reference path='rule.ts' />
        ///<reference path='ruleAction.ts' />
        ///<reference path='ruleDescriptor.ts' />
        ///<reference path='ruleFlag.ts' />
        ///<reference path='ruleOperation.ts' />
        ///<reference path='ruleOperationContext.ts' />
        ///<reference path='rules.ts' />
        ///<reference path='rulesMap.ts' />
        ///<reference path='tokenRange.ts' /> 
        /// <reference path="references.ts"/>
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var RulesProvider = (function () {
                    function RulesProvider() {
                        this.globalRules = new formatting.Rules();
                    }
                    RulesProvider.prototype.getRuleName = function (rule) {
                        return this.globalRules.getRuleName(rule);
                    };
                    RulesProvider.prototype.getRuleByName = function (name) {
                        return this.globalRules[name];
                    };
                    RulesProvider.prototype.getRulesMap = function () {
                        return this.rulesMap;
                    };
                    RulesProvider.prototype.ensureUpToDate = function (options) {
                        if (this.options == null || !ts.compareDataObjects(this.options, options)) {
                            var activeRules = this.createActiveRules(options);
                            var rulesMap = formatting.RulesMap.create(activeRules);
                            this.activeRules = activeRules;
                            this.rulesMap = rulesMap;
                            this.options = ts.clone(options);
                        }
                    };
                    RulesProvider.prototype.createActiveRules = function (options) {
                        var rules = this.globalRules.HighPriorityCommonRules.slice(0);
                        if (options.InsertSpaceAfterCommaDelimiter) {
                            rules.push(this.globalRules.SpaceAfterComma);
                        }
                        else {
                            rules.push(this.globalRules.NoSpaceAfterComma);
                        }
                        if (options.InsertSpaceAfterFunctionKeywordForAnonymousFunctions) {
                            rules.push(this.globalRules.SpaceAfterAnonymousFunctionKeyword);
                        }
                        else {
                            rules.push(this.globalRules.NoSpaceAfterAnonymousFunctionKeyword);
                        }
                        if (options.InsertSpaceAfterKeywordsInControlFlowStatements) {
                            rules.push(this.globalRules.SpaceAfterKeywordInControl);
                        }
                        else {
                            rules.push(this.globalRules.NoSpaceAfterKeywordInControl);
                        }
                        if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) {
                            rules.push(this.globalRules.SpaceAfterOpenParen);
                            rules.push(this.globalRules.SpaceBeforeCloseParen);
                            rules.push(this.globalRules.NoSpaceBetweenParens);
                        }
                        else {
                            rules.push(this.globalRules.NoSpaceAfterOpenParen);
                            rules.push(this.globalRules.NoSpaceBeforeCloseParen);
                            rules.push(this.globalRules.NoSpaceBetweenParens);
                        }
                        if (options.InsertSpaceAfterSemicolonInForStatements) {
                            rules.push(this.globalRules.SpaceAfterSemicolonInFor);
                        }
                        else {
                            rules.push(this.globalRules.NoSpaceAfterSemicolonInFor);
                        }
                        if (options.InsertSpaceBeforeAndAfterBinaryOperators) {
                            rules.push(this.globalRules.SpaceBeforeBinaryOperator);
                            rules.push(this.globalRules.SpaceAfterBinaryOperator);
                        }
                        else {
                            rules.push(this.globalRules.NoSpaceBeforeBinaryOperator);
                            rules.push(this.globalRules.NoSpaceAfterBinaryOperator);
                        }
                        if (options.PlaceOpenBraceOnNewLineForControlBlocks) {
                            rules.push(this.globalRules.NewLineBeforeOpenBraceInControl);
                        }
                        if (options.PlaceOpenBraceOnNewLineForFunctions) {
                            rules.push(this.globalRules.NewLineBeforeOpenBraceInFunction);
                            rules.push(this.globalRules.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock);
                        }
                        rules = rules.concat(this.globalRules.LowPriorityCommonRules);
                        return rules;
                    };
                    return RulesProvider;
                })();
                formatting.RulesProvider = RulesProvider;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        ///<reference path='..\services.ts' />
        ///<reference path='formattingScanner.ts' />
        ///<reference path='rulesProvider.ts' />
        ///<reference path='references.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var Constants;
                (function (Constants) {
                    Constants[Constants["Unknown"] = -1] = "Unknown";
                })(Constants || (Constants = {}));
                function formatOnEnter(position, sourceFile, rulesProvider, options) {
                    var line = sourceFile.getLineAndCharacterOfPosition(position).line;
                    if (line === 0) {
                        return [];
                    }
                    // get the span for the previous\current line
                    var span = {
                        // get start position for the previous line
                        pos: ts.getStartPositionOfLine(line - 1, sourceFile),
                        // get end position for the current line (end value is exclusive so add 1 to the result)
                        end: ts.getEndLinePosition(line, sourceFile) + 1
                    };
                    return formatSpan(span, sourceFile, options, rulesProvider, 2 /* FormatOnEnter */);
                }
                formatting.formatOnEnter = formatOnEnter;
                function formatOnSemicolon(position, sourceFile, rulesProvider, options) {
                    return formatOutermostParent(position, 22 /* SemicolonToken */, sourceFile, options, rulesProvider, 3 /* FormatOnSemicolon */);
                }
                formatting.formatOnSemicolon = formatOnSemicolon;
                function formatOnClosingCurly(position, sourceFile, rulesProvider, options) {
                    return formatOutermostParent(position, 15 /* CloseBraceToken */, sourceFile, options, rulesProvider, 4 /* FormatOnClosingCurlyBrace */);
                }
                formatting.formatOnClosingCurly = formatOnClosingCurly;
                function formatDocument(sourceFile, rulesProvider, options) {
                    var span = {
                        pos: 0,
                        end: sourceFile.text.length
                    };
                    return formatSpan(span, sourceFile, options, rulesProvider, 0 /* FormatDocument */);
                }
                formatting.formatDocument = formatDocument;
                function formatSelection(start, end, sourceFile, rulesProvider, options) {
                    // format from the beginning of the line
                    var span = {
                        pos: ts.getLineStartPositionForPosition(start, sourceFile),
                        end: end
                    };
                    return formatSpan(span, sourceFile, options, rulesProvider, 1 /* FormatSelection */);
                }
                formatting.formatSelection = formatSelection;
                function formatOutermostParent(position, expectedLastToken, sourceFile, options, rulesProvider, requestKind) {
                    var parent = findOutermostParent(position, expectedLastToken, sourceFile);
                    if (!parent) {
                        return [];
                    }
                    var span = {
                        pos: ts.getLineStartPositionForPosition(parent.getStart(sourceFile), sourceFile),
                        end: parent.end
                    };
                    return formatSpan(span, sourceFile, options, rulesProvider, requestKind);
                }
                function findOutermostParent(position, expectedTokenKind, sourceFile) {
                    var precedingToken = ts.findPrecedingToken(position, sourceFile);
                    // when it is claimed that trigger character was typed at given position 
                    // we verify that there is a token with a matching kind whose end is equal to position (because the character was just typed).
                    // If this condition is not hold - then trigger character was typed in some other context, 
                    // i.e.in comment and thus should not trigger autoformatting
                    if (!precedingToken ||
                        precedingToken.kind !== expectedTokenKind ||
                        position !== precedingToken.getEnd()) {
                        return undefined;
                    }
                    // walk up and search for the parent node that ends at the same position with precedingToken.
                    // for cases like this
                    // 
                    // let x = 1;
                    // while (true) {
                    // } 
                    // after typing close curly in while statement we want to reformat just the while statement.
                    // However if we just walk upwards searching for the parent that has the same end value - 
                    // we'll end up with the whole source file. isListElement allows to stop on the list element level
                    var current = precedingToken;
                    while (current &&
                        current.parent &&
                        current.parent.end === precedingToken.end &&
                        !isListElement(current.parent, current)) {
                        current = current.parent;
                    }
                    return current;
                }
                // Returns true if node is a element in some list in parent
                // i.e. parent is class declaration with the list of members and node is one of members.
                function isListElement(parent, node) {
                    switch (parent.kind) {
                        case 201 /* ClassDeclaration */:
                        case 202 /* InterfaceDeclaration */:
                            return ts.rangeContainsRange(parent.members, node);
                        case 205 /* ModuleDeclaration */:
                            var body = parent.body;
                            return body && body.kind === 179 /* Block */ && ts.rangeContainsRange(body.statements, node);
                        case 227 /* SourceFile */:
                        case 179 /* Block */:
                        case 206 /* ModuleBlock */:
                            return ts.rangeContainsRange(parent.statements, node);
                        case 223 /* CatchClause */:
                            return ts.rangeContainsRange(parent.block.statements, node);
                    }
                    return false;
                }
                /** find node that fully contains given text range */
                function findEnclosingNode(range, sourceFile) {
                    return find(sourceFile);
                    function find(n) {
                        var candidate = ts.forEachChild(n, function (c) { return ts.startEndContainsRange(c.getStart(sourceFile), c.end, range) && c; });
                        if (candidate) {
                            var result = find(candidate);
                            if (result) {
                                return result;
                            }
                        }
                        return n;
                    }
                }
                /** formatting is not applied to ranges that contain parse errors.
                  * This function will return a predicate that for a given text range will tell
                  * if there are any parse errors that overlap with the range.
                  */
                function prepareRangeContainsErrorFunction(errors, originalRange) {
                    if (!errors.length) {
                        return rangeHasNoErrors;
                    }
                    // pick only errors that fall in range
                    var sorted = errors
                        .filter(function (d) { return ts.rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length); })
                        .sort(function (e1, e2) { return e1.start - e2.start; });
                    if (!sorted.length) {
                        return rangeHasNoErrors;
                    }
                    var index = 0;
                    return function (r) {
                        // in current implementation sequence of arguments [r1, r2...] is monotonically increasing.
                        // 'index' tracks the index of the most recent error that was checked.
                        while (true) {
                            if (index >= sorted.length) {
                                // all errors in the range were already checked -> no error in specified range 
                                return false;
                            }
                            var error = sorted[index];
                            if (r.end <= error.start) {
                                // specified range ends before the error refered by 'index' - no error in range
                                return false;
                            }
                            if (ts.startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) {
                                // specified range overlaps with error range
                                return true;
                            }
                            index++;
                        }
                    };
                    function rangeHasNoErrors(r) {
                        return false;
                    }
                }
                /**
                  * Start of the original range might fall inside the comment - scanner will not yield appropriate results
                  * This function will look for token that is located before the start of target range
                  * and return its end as start position for the scanner.
                  */
                function getScanStartPosition(enclosingNode, originalRange, sourceFile) {
                    var start = enclosingNode.getStart(sourceFile);
                    if (start === originalRange.pos && enclosingNode.end === originalRange.end) {
                        return start;
                    }
                    var precedingToken = ts.findPrecedingToken(originalRange.pos, sourceFile);
                    if (!precedingToken) {
                        // no preceding token found - start from the beginning of enclosing node
                        return enclosingNode.pos;
                    }
                    // preceding token ends after the start of original range (i.e when originaRange.pos falls in the middle of literal)
                    // start from the beginning of enclosingNode to handle the entire 'originalRange'
                    if (precedingToken.end >= originalRange.pos) {
                        return enclosingNode.pos;
                    }
                    return precedingToken.end;
                }
                /*
                 * For cases like
                 * if (a ||
                 *     b ||$
                 *     c) {...}
                 * If we hit Enter at $ we want line '    b ||' to be indented.
                 * Formatting will be applied to the last two lines.
                 * Node that fully encloses these lines is binary expression 'a ||...'.
                 * Initial indentation for this node will be 0.
                 * Binary expressions don't introduce new indentation scopes, however it is possible
                 * that some parent node on the same line does - like if statement in this case.
                 * Note that we are considering parents only from the same line with initial node -
                 * if parent is on the different line - its delta was already contributed
                 * to the initial indentation.
                 */
                function getOwnOrInheritedDelta(n, options, sourceFile) {
                    var previousLine = -1 /* Unknown */;
                    var childKind = 0 /* Unknown */;
                    while (n) {
                        var line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line;
                        if (previousLine !== -1 /* Unknown */ && line !== previousLine) {
                            break;
                        }
                        if (formatting.SmartIndenter.shouldIndentChildNode(n.kind, childKind)) {
                            return options.IndentSize;
                        }
                        previousLine = line;
                        childKind = n.kind;
                        n = n.parent;
                    }
                    return 0;
                }
                function formatSpan(originalRange, sourceFile, options, rulesProvider, requestKind) {
                    var rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange);
                    // formatting context is used by rules provider
                    var formattingContext = new formatting.FormattingContext(sourceFile, requestKind);
                    // find the smallest node that fully wraps the range and compute the initial indentation for the node
                    var enclosingNode = findEnclosingNode(originalRange, sourceFile);
                    var formattingScanner = formatting.getFormattingScanner(sourceFile, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end);
                    var initialIndentation = formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options);
                    var previousRangeHasError;
                    var previousRange;
                    var previousParent;
                    var previousRangeStartLine;
                    var edits = [];
                    formattingScanner.advance();
                    if (formattingScanner.isOnToken()) {
                        var startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line;
                        var undecoratedStartLine = startLine;
                        if (enclosingNode.decorators) {
                            undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line;
                        }
                        var delta = getOwnOrInheritedDelta(enclosingNode, options, sourceFile);
                        processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta);
                    }
                    formattingScanner.close();
                    return edits;
                    // local functions
                    /** Tries to compute the indentation for a list element.
                      * If list element is not in range then
                      * function will pick its actual indentation
                      * so it can be pushed downstream as inherited indentation.
                      * If list element is in the range - its indentation will be equal
                      * to inherited indentation from its predecessors.
                      */
                    function tryComputeIndentationForListItem(startPos, endPos, parentStartLine, range, inheritedIndentation) {
                        if (ts.rangeOverlapsWithStartEnd(range, startPos, endPos)) {
                            if (inheritedIndentation !== -1 /* Unknown */) {
                                return inheritedIndentation;
                            }
                        }
                        else {
                            var startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line;
                            var startLinePosition = ts.getLineStartPositionForPosition(startPos, sourceFile);
                            var column = formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options);
                            if (startLine !== parentStartLine || startPos === column) {
                                return column;
                            }
                        }
                        return -1 /* Unknown */;
                    }
                    function computeIndentation(node, startLine, inheritedIndentation, parent, parentDynamicIndentation, effectiveParentStartLine) {
                        var indentation = inheritedIndentation;
                        if (indentation === -1 /* Unknown */) {
                            if (isSomeBlock(node.kind)) {
                                // blocks should be indented in 
                                // - other blocks
                                // - source file 
                                // - switch\default clauses
                                if (isSomeBlock(parent.kind) ||
                                    parent.kind === 227 /* SourceFile */ ||
                                    parent.kind === 220 /* CaseClause */ ||
                                    parent.kind === 221 /* DefaultClause */) {
                                    indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta();
                                }
                                else {
                                    indentation = parentDynamicIndentation.getIndentation();
                                }
                            }
                            else {
                                if (formatting.SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) {
                                    indentation = parentDynamicIndentation.getIndentation();
                                }
                                else {
                                    indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta();
                                }
                            }
                        }
                        var delta = formatting.SmartIndenter.shouldIndentChildNode(node.kind, 0 /* Unknown */) ? options.IndentSize : 0;
                        if (effectiveParentStartLine === startLine) {
                            // if node is located on the same line with the parent
                            // - inherit indentation from the parent
                            // - push children if either parent of node itself has non-zero delta
                            indentation = parentDynamicIndentation.getIndentation();
                            delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta() + delta);
                        }
                        return {
                            indentation: indentation,
                            delta: delta
                        };
                    }
                    function getFirstNonDecoratorTokenOfNode(node) {
                        if (node.modifiers && node.modifiers.length) {
                            return node.modifiers[0].kind;
                        }
                        switch (node.kind) {
                            case 201 /* ClassDeclaration */: return 69 /* ClassKeyword */;
                            case 202 /* InterfaceDeclaration */: return 103 /* InterfaceKeyword */;
                            case 200 /* FunctionDeclaration */: return 83 /* FunctionKeyword */;
                            case 204 /* EnumDeclaration */: return 204 /* EnumDeclaration */;
                            case 136 /* GetAccessor */: return 116 /* GetKeyword */;
                            case 137 /* SetAccessor */: return 120 /* SetKeyword */;
                            case 134 /* MethodDeclaration */:
                                if (node.asteriskToken) {
                                    return 35 /* AsteriskToken */;
                                }
                            // fall-through
                            case 132 /* PropertyDeclaration */:
                            case 129 /* Parameter */:
                                return node.name.kind;
                        }
                    }
                    function getDynamicIndentation(node, nodeStartLine, indentation, delta) {
                        return {
                            getIndentationForComment: function (kind) {
                                switch (kind) {
                                    // preceding comment to the token that closes the indentation scope inherits the indentation from the scope
                                    // ..  {
                                    //     // comment
                                    // }
                                    case 15 /* CloseBraceToken */:
                                    case 19 /* CloseBracketToken */:
                                        return indentation + delta;
                                }
                                return indentation;
                            },
                            getIndentationForToken: function (line, kind) {
                                if (nodeStartLine !== line && node.decorators) {
                                    if (kind === getFirstNonDecoratorTokenOfNode(node)) {
                                        // if this token is the first token following the list of decorators, we do not need to indent
                                        return indentation;
                                    }
                                }
                                switch (kind) {
                                    // open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent
                                    case 14 /* OpenBraceToken */:
                                    case 15 /* CloseBraceToken */:
                                    case 18 /* OpenBracketToken */:
                                    case 19 /* CloseBracketToken */:
                                    case 76 /* ElseKeyword */:
                                    case 100 /* WhileKeyword */:
                                    case 52 /* AtToken */:
                                        return indentation;
                                    default:
                                        // if token line equals to the line of containing node (this is a first token in the node) - use node indentation
                                        return nodeStartLine !== line ? indentation + delta : indentation;
                                }
                            },
                            getIndentation: function () { return indentation; },
                            getDelta: function () { return delta; },
                            recomputeIndentation: function (lineAdded) {
                                if (node.parent && formatting.SmartIndenter.shouldIndentChildNode(node.parent.kind, node.kind)) {
                                    if (lineAdded) {
                                        indentation += options.IndentSize;
                                    }
                                    else {
                                        indentation -= options.IndentSize;
                                    }
                                    if (formatting.SmartIndenter.shouldIndentChildNode(node.kind, 0 /* Unknown */)) {
                                        delta = options.IndentSize;
                                    }
                                    else {
                                        delta = 0;
                                    }
                                }
                            }
                        };
                    }
                    function processNode(node, contextNode, nodeStartLine, undecoratedNodeStartLine, indentation, delta) {
                        if (!ts.rangeOverlapsWithStartEnd(originalRange, node.getStart(sourceFile), node.getEnd())) {
                            return;
                        }
                        var nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta);
                        // a useful observations when tracking context node
                        //        /
                        //      [a]
                        //   /   |   \ 
                        //  [b] [c] [d]
                        // node 'a' is a context node for nodes 'b', 'c', 'd' 
                        // except for the leftmost leaf token in [b] - in this case context node ('e') is located somewhere above 'a'
                        // this rule can be applied recursively to child nodes of 'a'.
                        // 
                        // context node is set to parent node value after processing every child node
                        // context node is set to parent of the token after processing every token
                        var childContextNode = contextNode;
                        // if there are any tokens that logically belong to node and interleave child nodes
                        // such tokens will be consumed in processChildNode for for the child that follows them
                        ts.forEachChild(node, function (child) {
                            processChildNode(child, -1 /* Unknown */, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, false);
                        }, function (nodes) {
                            processChildNodes(nodes, node, nodeStartLine, nodeDynamicIndentation);
                        });
                        // proceed any tokens in the node that are located after child nodes
                        while (formattingScanner.isOnToken()) {
                            var tokenInfo = formattingScanner.readTokenInfo(node);
                            if (tokenInfo.token.end > node.end) {
                                break;
                            }
                            consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation);
                        }
                        function processChildNode(child, inheritedIndentation, parent, parentDynamicIndentation, parentStartLine, undecoratedParentStartLine, isListItem) {
                            var childStartPos = child.getStart(sourceFile);
                            var childStartLine = sourceFile.getLineAndCharacterOfPosition(childStartPos).line;
                            var undecoratedChildStartLine = childStartLine;
                            if (child.decorators) {
                                undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(child, sourceFile)).line;
                            }
                            // if child is a list item - try to get its indentation
                            var childIndentationAmount = -1 /* Unknown */;
                            if (isListItem) {
                                childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation);
                                if (childIndentationAmount !== -1 /* Unknown */) {
                                    inheritedIndentation = childIndentationAmount;
                                }
                            }
                            // child node is outside the target range - do not dive inside
                            if (!ts.rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) {
                                return inheritedIndentation;
                            }
                            if (child.getFullWidth() === 0) {
                                return inheritedIndentation;
                            }
                            while (formattingScanner.isOnToken()) {
                                // proceed any parent tokens that are located prior to child.getStart()
                                var tokenInfo = formattingScanner.readTokenInfo(node);
                                if (tokenInfo.token.end > childStartPos) {
                                    // stop when formatting scanner advances past the beginning of the child
                                    break;
                                }
                                consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation);
                            }
                            if (!formattingScanner.isOnToken()) {
                                return inheritedIndentation;
                            }
                            if (ts.isToken(child)) {
                                // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules
                                var tokenInfo = formattingScanner.readTokenInfo(child);
                                ts.Debug.assert(tokenInfo.token.end === child.end);
                                consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation);
                                return inheritedIndentation;
                            }
                            var effectiveParentStartLine = child.kind === 130 /* Decorator */ ? childStartLine : undecoratedParentStartLine;
                            var childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine);
                            processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta);
                            childContextNode = node;
                            return inheritedIndentation;
                        }
                        function processChildNodes(nodes, parent, parentStartLine, parentDynamicIndentation) {
                            var listStartToken = getOpenTokenForList(parent, nodes);
                            var listEndToken = getCloseTokenForOpenToken(listStartToken);
                            var listDynamicIndentation = parentDynamicIndentation;
                            var startLine = parentStartLine;
                            if (listStartToken !== 0 /* Unknown */) {
                                // introduce a new indentation scope for lists (including list start and end tokens)
                                while (formattingScanner.isOnToken()) {
                                    var tokenInfo = formattingScanner.readTokenInfo(parent);
                                    if (tokenInfo.token.end > nodes.pos) {
                                        // stop when formatting scanner moves past the beginning of node list
                                        break;
                                    }
                                    else if (tokenInfo.token.kind === listStartToken) {
                                        // consume list start token
                                        startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line;
                                        var indentation_1 = computeIndentation(tokenInfo.token, startLine, -1 /* Unknown */, parent, parentDynamicIndentation, startLine);
                                        listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation_1.indentation, indentation_1.delta);
                                        consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation);
                                    }
                                    else {
                                        // consume any tokens that precede the list as child elements of 'node' using its indentation scope
                                        consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation);
                                    }
                                }
                            }
                            var inheritedIndentation = -1 /* Unknown */;
                            for (var _i = 0; _i < nodes.length; _i++) {
                                var child = nodes[_i];
                                inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, true);
                            }
                            if (listEndToken !== 0 /* Unknown */) {
                                if (formattingScanner.isOnToken()) {
                                    var tokenInfo = formattingScanner.readTokenInfo(parent);
                                    // consume the list end token only if it is still belong to the parent
                                    // there might be the case when current token matches end token but does not considered as one
                                    // function (x: function) <-- 
                                    // without this check close paren will be interpreted as list end token for function expression which is wrong
                                    if (tokenInfo.token.kind === listEndToken && ts.rangeContainsRange(parent, tokenInfo.token)) {
                                        // consume list end token
                                        consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation);
                                    }
                                }
                            }
                        }
                        function consumeTokenAndAdvanceScanner(currentTokenInfo, parent, dynamicIndentation) {
                            ts.Debug.assert(ts.rangeContainsRange(parent, currentTokenInfo.token));
                            var lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine();
                            var indentToken = false;
                            if (currentTokenInfo.leadingTrivia) {
                                processTrivia(currentTokenInfo.leadingTrivia, parent, childContextNode, dynamicIndentation);
                            }
                            var lineAdded;
                            var isTokenInRange = ts.rangeContainsRange(originalRange, currentTokenInfo.token);
                            var tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos);
                            if (isTokenInRange) {
                                var rangeHasError = rangeContainsError(currentTokenInfo.token);
                                // save prevStartLine since processRange will overwrite this value with current ones
                                var prevStartLine = previousRangeStartLine;
                                lineAdded = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation);
                                if (rangeHasError) {
                                    // do not indent comments\token if token range overlaps with some error
                                    indentToken = false;
                                }
                                else {
                                    if (lineAdded !== undefined) {
                                        indentToken = lineAdded;
                                    }
                                    else {
                                        indentToken = lastTriviaWasNewLine && tokenStart.line !== prevStartLine;
                                    }
                                }
                            }
                            if (currentTokenInfo.trailingTrivia) {
                                processTrivia(currentTokenInfo.trailingTrivia, parent, childContextNode, dynamicIndentation);
                            }
                            if (indentToken) {
                                var indentNextTokenOrTrivia = true;
                                if (currentTokenInfo.leadingTrivia) {
                                    for (var _i = 0, _a = currentTokenInfo.leadingTrivia; _i < _a.length; _i++) {
                                        var triviaItem = _a[_i];
                                        if (!ts.rangeContainsRange(originalRange, triviaItem)) {
                                            continue;
                                        }
                                        var triviaStartLine = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos).line;
                                        switch (triviaItem.kind) {
                                            case 3 /* MultiLineCommentTrivia */:
                                                var commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
                                                indentMultilineComment(triviaItem, commentIndentation, !indentNextTokenOrTrivia);
                                                indentNextTokenOrTrivia = false;
                                                break;
                                            case 2 /* SingleLineCommentTrivia */:
                                                if (indentNextTokenOrTrivia) {
                                                    var commentIndentation_1 = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
                                                    insertIndentation(triviaItem.pos, commentIndentation_1, false);
                                                    indentNextTokenOrTrivia = false;
                                                }
                                                break;
                                            case 4 /* NewLineTrivia */:
                                                indentNextTokenOrTrivia = true;
                                                break;
                                        }
                                    }
                                }
                                // indent token only if is it is in target range and does not overlap with any error ranges
                                if (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) {
                                    var tokenIndentation = dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind);
                                    insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAdded);
                                }
                            }
                            formattingScanner.advance();
                            childContextNode = parent;
                        }
                    }
                    function processTrivia(trivia, parent, contextNode, dynamicIndentation) {
                        for (var _i = 0; _i < trivia.length; _i++) {
                            var triviaItem = trivia[_i];
                            if (ts.isComment(triviaItem.kind) && ts.rangeContainsRange(originalRange, triviaItem)) {
                                var triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos);
                                processRange(triviaItem, triviaItemStart, parent, contextNode, dynamicIndentation);
                            }
                        }
                    }
                    function processRange(range, rangeStart, parent, contextNode, dynamicIndentation) {
                        var rangeHasError = rangeContainsError(range);
                        var lineAdded;
                        if (!rangeHasError && !previousRangeHasError) {
                            if (!previousRange) {
                                // trim whitespaces starting from the beginning of the span up to the current line
                                var originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos);
                                trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line);
                            }
                            else {
                                lineAdded =
                                    processPair(range, rangeStart.line, parent, previousRange, previousRangeStartLine, previousParent, contextNode, dynamicIndentation);
                            }
                        }
                        previousRange = range;
                        previousParent = parent;
                        previousRangeStartLine = rangeStart.line;
                        previousRangeHasError = rangeHasError;
                        return lineAdded;
                    }
                    function processPair(currentItem, currentStartLine, currentParent, previousItem, previousStartLine, previousParent, contextNode, dynamicIndentation) {
                        formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode);
                        var rule = rulesProvider.getRulesMap().GetRule(formattingContext);
                        var trimTrailingWhitespaces;
                        var lineAdded;
                        if (rule) {
                            applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine);
                            if (rule.Operation.Action & (2 /* Space */ | 8 /* Delete */) && currentStartLine !== previousStartLine) {
                                lineAdded = false;
                                // Handle the case where the next line is moved to be the end of this line. 
                                // In this case we don't indent the next line in the next pass.
                                if (currentParent.getStart(sourceFile) === currentItem.pos) {
                                    dynamicIndentation.recomputeIndentation(false);
                                }
                            }
                            else if (rule.Operation.Action & 4 /* NewLine */ && currentStartLine === previousStartLine) {
                                lineAdded = true;
                                // Handle the case where token2 is moved to the new line. 
                                // In this case we indent token2 in the next pass but we set
                                // sameLineIndent flag to notify the indenter that the indentation is within the line.
                                if (currentParent.getStart(sourceFile) === currentItem.pos) {
                                    dynamicIndentation.recomputeIndentation(true);
                                }
                            }
                            // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line
                            trimTrailingWhitespaces =
                                (rule.Operation.Action & (4 /* NewLine */ | 2 /* Space */)) &&
                                    rule.Flag !== 1 /* CanDeleteNewLines */;
                        }
                        else {
                            trimTrailingWhitespaces = true;
                        }
                        if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) {
                            // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line
                            trimTrailingWhitespacesForLines(previousStartLine, currentStartLine, previousItem);
                        }
                        return lineAdded;
                    }
                    function insertIndentation(pos, indentation, lineAdded) {
                        var indentationString = getIndentationString(indentation, options);
                        if (lineAdded) {
                            // new line is added before the token by the formatting rules
                            // insert indentation string at the very beginning of the token
                            recordReplace(pos, 0, indentationString);
                        }
                        else {
                            var tokenStart = sourceFile.getLineAndCharacterOfPosition(pos);
                            if (indentation !== tokenStart.character) {
                                var startLinePosition = ts.getStartPositionOfLine(tokenStart.line, sourceFile);
                                recordReplace(startLinePosition, tokenStart.character, indentationString);
                            }
                        }
                    }
                    function indentMultilineComment(commentRange, indentation, firstLineIsIndented) {
                        // split comment in lines
                        var startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line;
                        var endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line;
                        var parts;
                        if (startLine === endLine) {
                            if (!firstLineIsIndented) {
                                // treat as single line comment
                                insertIndentation(commentRange.pos, indentation, false);
                            }
                            return;
                        }
                        else {
                            parts = [];
                            var startPos = commentRange.pos;
                            for (var line = startLine; line < endLine; ++line) {
                                var endOfLine = ts.getEndLinePosition(line, sourceFile);
                                parts.push({ pos: startPos, end: endOfLine });
                                startPos = ts.getStartPositionOfLine(line + 1, sourceFile);
                            }
                            parts.push({ pos: startPos, end: commentRange.end });
                        }
                        var startLinePos = ts.getStartPositionOfLine(startLine, sourceFile);
                        var nonWhitespaceColumnInFirstPart = formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options);
                        if (indentation === nonWhitespaceColumnInFirstPart.column) {
                            return;
                        }
                        var startIndex = 0;
                        if (firstLineIsIndented) {
                            startIndex = 1;
                            startLine++;
                        }
                        // shift all parts on the delta size
                        var delta = indentation - nonWhitespaceColumnInFirstPart.column;
                        for (var i = startIndex, len = parts.length; i < len; ++i, ++startLine) {
                            var startLinePos_1 = ts.getStartPositionOfLine(startLine, sourceFile);
                            var nonWhitespaceCharacterAndColumn = i === 0
                                ? nonWhitespaceColumnInFirstPart
                                : formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options);
                            var newIndentation = nonWhitespaceCharacterAndColumn.column + delta;
                            if (newIndentation > 0) {
                                var indentationString = getIndentationString(newIndentation, options);
                                recordReplace(startLinePos_1, nonWhitespaceCharacterAndColumn.character, indentationString);
                            }
                            else {
                                recordDelete(startLinePos_1, nonWhitespaceCharacterAndColumn.character);
                            }
                        }
                    }
                    function trimTrailingWhitespacesForLines(line1, line2, range) {
                        for (var line = line1; line < line2; ++line) {
                            var lineStartPosition = ts.getStartPositionOfLine(line, sourceFile);
                            var lineEndPosition = ts.getEndLinePosition(line, sourceFile);
                            // do not trim whitespaces in comments
                            if (range && ts.isComment(range.kind) && range.pos <= lineEndPosition && range.end > lineEndPosition) {
                                continue;
                            }
                            var pos = lineEndPosition;
                            while (pos >= lineStartPosition && ts.isWhiteSpace(sourceFile.text.charCodeAt(pos))) {
                                pos--;
                            }
                            if (pos !== lineEndPosition) {
                                ts.Debug.assert(pos === lineStartPosition || !ts.isWhiteSpace(sourceFile.text.charCodeAt(pos)));
                                recordDelete(pos + 1, lineEndPosition - pos);
                            }
                        }
                    }
                    function newTextChange(start, len, newText) {
                        return { span: ts.createTextSpan(start, len), newText: newText };
                    }
                    function recordDelete(start, len) {
                        if (len) {
                            edits.push(newTextChange(start, len, ""));
                        }
                    }
                    function recordReplace(start, len, newText) {
                        if (len || newText) {
                            edits.push(newTextChange(start, len, newText));
                        }
                    }
                    function applyRuleEdits(rule, previousRange, previousStartLine, currentRange, currentStartLine) {
                        var between;
                        switch (rule.Operation.Action) {
                            case 1 /* Ignore */:
                                // no action required
                                return;
                            case 8 /* Delete */:
                                if (previousRange.end !== currentRange.pos) {
                                    // delete characters starting from t1.end up to t2.pos exclusive
                                    recordDelete(previousRange.end, currentRange.pos - previousRange.end);
                                }
                                break;
                            case 4 /* NewLine */:
                                // exit early if we on different lines and rule cannot change number of newlines
                                // if line1 and line2 are on subsequent lines then no edits are required - ok to exit
                                // if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines
                                if (rule.Flag !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) {
                                    return;
                                }
                                // edit should not be applied only if we have one line feed between elements
                                var lineDelta = currentStartLine - previousStartLine;
                                if (lineDelta !== 1) {
                                    recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.NewLineCharacter);
                                }
                                break;
                            case 2 /* Space */:
                                // exit early if we on different lines and rule cannot change number of newlines
                                if (rule.Flag !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) {
                                    return;
                                }
                                var posDelta = currentRange.pos - previousRange.end;
                                if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32 /* space */) {
                                    recordReplace(previousRange.end, currentRange.pos - previousRange.end, " ");
                                }
                                break;
                        }
                    }
                }
                function isSomeBlock(kind) {
                    switch (kind) {
                        case 179 /* Block */:
                        case 206 /* ModuleBlock */:
                            return true;
                    }
                    return false;
                }
                function getOpenTokenForList(node, list) {
                    switch (node.kind) {
                        case 135 /* Constructor */:
                        case 200 /* FunctionDeclaration */:
                        case 162 /* FunctionExpression */:
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                        case 163 /* ArrowFunction */:
                            if (node.typeParameters === list) {
                                return 24 /* LessThanToken */;
                            }
                            else if (node.parameters === list) {
                                return 16 /* OpenParenToken */;
                            }
                            break;
                        case 157 /* CallExpression */:
                        case 158 /* NewExpression */:
                            if (node.typeArguments === list) {
                                return 24 /* LessThanToken */;
                            }
                            else if (node.arguments === list) {
                                return 16 /* OpenParenToken */;
                            }
                            break;
                        case 141 /* TypeReference */:
                            if (node.typeArguments === list) {
                                return 24 /* LessThanToken */;
                            }
                    }
                    return 0 /* Unknown */;
                }
                function getCloseTokenForOpenToken(kind) {
                    switch (kind) {
                        case 16 /* OpenParenToken */:
                            return 17 /* CloseParenToken */;
                        case 24 /* LessThanToken */:
                            return 25 /* GreaterThanToken */;
                    }
                    return 0 /* Unknown */;
                }
                var internedSizes;
                var internedTabsIndentation;
                var internedSpacesIndentation;
                function getIndentationString(indentation, options) {
                    // reset interned strings if FormatCodeOptions were changed
                    var resetInternedStrings = !internedSizes || (internedSizes.tabSize !== options.TabSize || internedSizes.indentSize !== options.IndentSize);
                    if (resetInternedStrings) {
                        internedSizes = { tabSize: options.TabSize, indentSize: options.IndentSize };
                        internedTabsIndentation = internedSpacesIndentation = undefined;
                    }
                    if (!options.ConvertTabsToSpaces) {
                        var tabs = Math.floor(indentation / options.TabSize);
                        var spaces = indentation - tabs * options.TabSize;
                        var tabString;
                        if (!internedTabsIndentation) {
                            internedTabsIndentation = [];
                        }
                        if (internedTabsIndentation[tabs] === undefined) {
                            internedTabsIndentation[tabs] = tabString = repeat('\t', tabs);
                        }
                        else {
                            tabString = internedTabsIndentation[tabs];
                        }
                        return spaces ? tabString + repeat(" ", spaces) : tabString;
                    }
                    else {
                        var spacesString;
                        var quotient = Math.floor(indentation / options.IndentSize);
                        var remainder = indentation % options.IndentSize;
                        if (!internedSpacesIndentation) {
                            internedSpacesIndentation = [];
                        }
                        if (internedSpacesIndentation[quotient] === undefined) {
                            spacesString = repeat(" ", options.IndentSize * quotient);
                            internedSpacesIndentation[quotient] = spacesString;
                        }
                        else {
                            spacesString = internedSpacesIndentation[quotient];
                        }
                        return remainder ? spacesString + repeat(" ", remainder) : spacesString;
                    }
                    function repeat(value, count) {
                        var s = "";
                        for (var i = 0; i < count; ++i) {
                            s += value;
                        }
                        return s;
                    }
                }
                formatting.getIndentationString = getIndentationString;
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        ///<reference path='..\services.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var formatting;
            (function (formatting) {
                var SmartIndenter;
                (function (SmartIndenter) {
                    var Value;
                    (function (Value) {
                        Value[Value["Unknown"] = -1] = "Unknown";
                    })(Value || (Value = {}));
                    function getIndentation(position, sourceFile, options) {
                        if (position > sourceFile.text.length) {
                            return 0; // past EOF
                        }
                        var precedingToken = ts.findPrecedingToken(position, sourceFile);
                        if (!precedingToken) {
                            return 0;
                        }
                        // no indentation in string \regex\template literals
                        var precedingTokenIsLiteral = precedingToken.kind === 8 /* StringLiteral */ ||
                            precedingToken.kind === 9 /* RegularExpressionLiteral */ ||
                            precedingToken.kind === 10 /* NoSubstitutionTemplateLiteral */ ||
                            precedingToken.kind === 11 /* TemplateHead */ ||
                            precedingToken.kind === 12 /* TemplateMiddle */ ||
                            precedingToken.kind === 13 /* TemplateTail */;
                        if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && precedingToken.end > position) {
                            return 0;
                        }
                        var lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
                        if (precedingToken.kind === 23 /* CommaToken */ && precedingToken.parent.kind !== 169 /* BinaryExpression */) {
                            // previous token is comma that separates items in list - find the previous item and try to derive indentation from it
                            var actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options);
                            if (actualIndentation !== -1 /* Unknown */) {
                                return actualIndentation;
                            }
                        }
                        // try to find node that can contribute to indentation and includes 'position' starting from 'precedingToken'
                        // if such node is found - compute initial indentation for 'position' inside this node
                        var previous;
                        var current = precedingToken;
                        var currentStart;
                        var indentationDelta;
                        while (current) {
                            if (ts.positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current.kind, previous ? previous.kind : 0 /* Unknown */)) {
                                currentStart = getStartLineAndCharacterForNode(current, sourceFile);
                                if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) {
                                    indentationDelta = 0;
                                }
                                else {
                                    indentationDelta = lineAtPosition !== currentStart.line ? options.IndentSize : 0;
                                }
                                break;
                            }
                            // check if current node is a list item - if yes, take indentation from it
                            var actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
                            if (actualIndentation !== -1 /* Unknown */) {
                                return actualIndentation;
                            }
                            previous = current;
                            current = current.parent;
                        }
                        if (!current) {
                            // no parent was found - return 0 to be indented on the level of SourceFile
                            return 0;
                        }
                        return getIndentationForNodeWorker(current, currentStart, undefined, indentationDelta, sourceFile, options);
                    }
                    SmartIndenter.getIndentation = getIndentation;
                    function getIndentationForNode(n, ignoreActualIndentationRange, sourceFile, options) {
                        var start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
                        return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, 0, sourceFile, options);
                    }
                    SmartIndenter.getIndentationForNode = getIndentationForNode;
                    function getIndentationForNodeWorker(current, currentStart, ignoreActualIndentationRange, indentationDelta, sourceFile, options) {
                        var parent = current.parent;
                        var parentStart;
                        // walk upwards and collect indentations for pairs of parent-child nodes
                        // indentation is not added if parent and child nodes start on the same line or if parent is IfStatement and child starts on the same line with 'else clause'
                        while (parent) {
                            var useActualIndentation = true;
                            if (ignoreActualIndentationRange) {
                                var start = current.getStart(sourceFile);
                                useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end;
                            }
                            if (useActualIndentation) {
                                // check if current node is a list item - if yes, take indentation from it
                                var actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
                                if (actualIndentation !== -1 /* Unknown */) {
                                    return actualIndentation + indentationDelta;
                                }
                            }
                            parentStart = getParentStart(parent, current, sourceFile);
                            var parentAndChildShareLine = parentStart.line === currentStart.line ||
                                childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile);
                            if (useActualIndentation) {
                                // try to fetch actual indentation for current node from source text
                                var actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options);
                                if (actualIndentation !== -1 /* Unknown */) {
                                    return actualIndentation + indentationDelta;
                                }
                            }
                            // increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line
                            if (shouldIndentChildNode(parent.kind, current.kind) && !parentAndChildShareLine) {
                                indentationDelta += options.IndentSize;
                            }
                            current = parent;
                            currentStart = parentStart;
                            parent = current.parent;
                        }
                        return indentationDelta;
                    }
                    function getParentStart(parent, child, sourceFile) {
                        var containingList = getContainingList(child, sourceFile);
                        if (containingList) {
                            return sourceFile.getLineAndCharacterOfPosition(containingList.pos);
                        }
                        return sourceFile.getLineAndCharacterOfPosition(parent.getStart(sourceFile));
                    }
                    /*
                     * Function returns Value.Unknown if indentation cannot be determined
                     */
                    function getActualIndentationForListItemBeforeComma(commaToken, sourceFile, options) {
                        // previous token is comma that separates items in list - find the previous item and try to derive indentation from it
                        var commaItemInfo = ts.findListItemInfo(commaToken);
                        if (commaItemInfo && commaItemInfo.listItemIndex > 0) {
                            return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options);
                        }
                        else {
                            // handle broken code gracefully
                            return -1 /* Unknown */;
                        }
                    }
                    /*
                     * Function returns Value.Unknown if actual indentation for node should not be used (i.e because node is nested expression)
                     */
                    function getActualIndentationForNode(current, parent, currentLineAndChar, parentAndChildShareLine, sourceFile, options) {
                        // actual indentation is used for statements\declarations if one of cases below is true:
                        // - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually
                        // - parent and child are not on the same line
                        var useActualIndentation = (ts.isDeclaration(current) || ts.isStatement(current)) &&
                            (parent.kind === 227 /* SourceFile */ || !parentAndChildShareLine);
                        if (!useActualIndentation) {
                            return -1 /* Unknown */;
                        }
                        return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options);
                    }
                    function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile) {
                        var nextToken = ts.findNextToken(precedingToken, current);
                        if (!nextToken) {
                            return false;
                        }
                        if (nextToken.kind === 14 /* OpenBraceToken */) {
                            // open braces are always indented at the parent level
                            return true;
                        }
                        else if (nextToken.kind === 15 /* CloseBraceToken */) {
                            // close braces are indented at the parent level if they are located on the same line with cursor
                            // this means that if new line will be added at $ position, this case will be indented
                            // class A {
                            //    $
                            // }
                            /// and this one - not
                            // class A {
                            // $}
                            var nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line;
                            return lineAtPosition === nextTokenStartLine;
                        }
                        return false;
                    }
                    function getStartLineAndCharacterForNode(n, sourceFile) {
                        return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
                    }
                    function childStartsOnTheSameLineWithElseInIfStatement(parent, child, childStartLine, sourceFile) {
                        if (parent.kind === 183 /* IfStatement */ && parent.elseStatement === child) {
                            var elseKeyword = ts.findChildOfKind(parent, 76 /* ElseKeyword */, sourceFile);
                            ts.Debug.assert(elseKeyword !== undefined);
                            var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line;
                            return elseKeywordStartLine === childStartLine;
                        }
                        return false;
                    }
                    SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement = childStartsOnTheSameLineWithElseInIfStatement;
                    function getContainingList(node, sourceFile) {
                        if (node.parent) {
                            switch (node.parent.kind) {
                                case 141 /* TypeReference */:
                                    if (node.parent.typeArguments &&
                                        ts.rangeContainsStartEnd(node.parent.typeArguments, node.getStart(sourceFile), node.getEnd())) {
                                        return node.parent.typeArguments;
                                    }
                                    break;
                                case 154 /* ObjectLiteralExpression */:
                                    return node.parent.properties;
                                case 153 /* ArrayLiteralExpression */:
                                    return node.parent.elements;
                                case 200 /* FunctionDeclaration */:
                                case 162 /* FunctionExpression */:
                                case 163 /* ArrowFunction */:
                                case 134 /* MethodDeclaration */:
                                case 133 /* MethodSignature */:
                                case 138 /* CallSignature */:
                                case 139 /* ConstructSignature */: {
                                    var start = node.getStart(sourceFile);
                                    if (node.parent.typeParameters &&
                                        ts.rangeContainsStartEnd(node.parent.typeParameters, start, node.getEnd())) {
                                        return node.parent.typeParameters;
                                    }
                                    if (ts.rangeContainsStartEnd(node.parent.parameters, start, node.getEnd())) {
                                        return node.parent.parameters;
                                    }
                                    break;
                                }
                                case 158 /* NewExpression */:
                                case 157 /* CallExpression */: {
                                    var start = node.getStart(sourceFile);
                                    if (node.parent.typeArguments &&
                                        ts.rangeContainsStartEnd(node.parent.typeArguments, start, node.getEnd())) {
                                        return node.parent.typeArguments;
                                    }
                                    if (node.parent.arguments &&
                                        ts.rangeContainsStartEnd(node.parent.arguments, start, node.getEnd())) {
                                        return node.parent.arguments;
                                    }
                                    break;
                                }
                            }
                        }
                        return undefined;
                    }
                    function getActualIndentationForListItem(node, sourceFile, options) {
                        var containingList = getContainingList(node, sourceFile);
                        return containingList ? getActualIndentationFromList(containingList) : -1 /* Unknown */;
                        function getActualIndentationFromList(list) {
                            var index = ts.indexOf(list, node);
                            return index !== -1 ? deriveActualIndentationFromList(list, index, sourceFile, options) : -1 /* Unknown */;
                        }
                    }
                    function deriveActualIndentationFromList(list, index, sourceFile, options) {
                        ts.Debug.assert(index >= 0 && index < list.length);
                        var node = list[index];
                        // walk toward the start of the list starting from current node and check if the line is the same for all items.
                        // if end line for item [i - 1] differs from the start line for item [i] - find column of the first non-whitespace character on the line of item [i]
                        var lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile);
                        for (var i = index - 1; i >= 0; --i) {
                            if (list[i].kind === 23 /* CommaToken */) {
                                continue;
                            }
                            // skip list items that ends on the same line with the current list element
                            var prevEndLine = sourceFile.getLineAndCharacterOfPosition(list[i].end).line;
                            if (prevEndLine !== lineAndCharacter.line) {
                                return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options);
                            }
                            lineAndCharacter = getStartLineAndCharacterForNode(list[i], sourceFile);
                        }
                        return -1 /* Unknown */;
                    }
                    function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options) {
                        var lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0);
                        return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options);
                    }
                    /*
                        Character is the actual index of the character since the beginning of the line.
                        Column - position of the character after expanding tabs to spaces
                        "0\t2$"
                        value of 'character' for '$' is 3
                        value of 'column' for '$' is 6 (assuming that tab size is 4)
                    */
                    function findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options) {
                        var character = 0;
                        var column = 0;
                        for (var pos = startPos; pos < endPos; ++pos) {
                            var ch = sourceFile.text.charCodeAt(pos);
                            if (!ts.isWhiteSpace(ch)) {
                                break;
                            }
                            if (ch === 9 /* tab */) {
                                column += options.TabSize + (column % options.TabSize);
                            }
                            else {
                                column++;
                            }
                            character++;
                        }
                        return { column: column, character: character };
                    }
                    SmartIndenter.findFirstNonWhitespaceCharacterAndColumn = findFirstNonWhitespaceCharacterAndColumn;
                    function findFirstNonWhitespaceColumn(startPos, endPos, sourceFile, options) {
                        return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column;
                    }
                    SmartIndenter.findFirstNonWhitespaceColumn = findFirstNonWhitespaceColumn;
                    function nodeContentIsAlwaysIndented(kind) {
                        switch (kind) {
                            case 201 /* ClassDeclaration */:
                            case 202 /* InterfaceDeclaration */:
                            case 204 /* EnumDeclaration */:
                            case 153 /* ArrayLiteralExpression */:
                            case 179 /* Block */:
                            case 206 /* ModuleBlock */:
                            case 154 /* ObjectLiteralExpression */:
                            case 145 /* TypeLiteral */:
                            case 147 /* TupleType */:
                            case 207 /* CaseBlock */:
                            case 221 /* DefaultClause */:
                            case 220 /* CaseClause */:
                            case 161 /* ParenthesizedExpression */:
                            case 157 /* CallExpression */:
                            case 158 /* NewExpression */:
                            case 180 /* VariableStatement */:
                            case 198 /* VariableDeclaration */:
                            case 214 /* ExportAssignment */:
                            case 191 /* ReturnStatement */:
                            case 170 /* ConditionalExpression */:
                            case 151 /* ArrayBindingPattern */:
                            case 150 /* ObjectBindingPattern */:
                                return true;
                        }
                        return false;
                    }
                    function shouldIndentChildNode(parent, child) {
                        if (nodeContentIsAlwaysIndented(parent)) {
                            return true;
                        }
                        switch (parent) {
                            case 184 /* DoStatement */:
                            case 185 /* WhileStatement */:
                            case 187 /* ForInStatement */:
                            case 188 /* ForOfStatement */:
                            case 186 /* ForStatement */:
                            case 183 /* IfStatement */:
                            case 200 /* FunctionDeclaration */:
                            case 162 /* FunctionExpression */:
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                            case 138 /* CallSignature */:
                            case 163 /* ArrowFunction */:
                            case 135 /* Constructor */:
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                                return child !== 179 /* Block */;
                            default:
                                return false;
                        }
                    }
                    SmartIndenter.shouldIndentChildNode = shouldIndentChildNode;
                })(SmartIndenter = formatting.SmartIndenter || (formatting.SmartIndenter = {}));
            })(formatting = ts.formatting || (ts.formatting = {}));
        })(ts || (ts = {}));
        /// <reference path="..\compiler\program.ts"/>
        var __extends = this.__extends || function (d, b) {
            for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            function __() { this.constructor = d; }
            __.prototype = b.prototype;
            d.prototype = new __();
        };
        /// <reference path='breakpoints.ts' />
        /// <reference path='outliningElementsCollector.ts' />
        /// <reference path='navigateTo.ts' />
        /// <reference path='navigationBar.ts' />
        /// <reference path='patternMatcher.ts' />
        /// <reference path='signatureHelp.ts' />
        /// <reference path='utilities.ts' />
        /// <reference path='formatting\formatting.ts' />
        /// <reference path='formatting\smartIndenter.ts' />
        var ts;
        (function (ts) {
            /** The version of the language service API */
            ts.servicesVersion = "0.4";
            var ScriptSnapshot;
            (function (ScriptSnapshot) {
                var StringScriptSnapshot = (function () {
                    function StringScriptSnapshot(text) {
                        this.text = text;
                        this._lineStartPositions = undefined;
                    }
                    StringScriptSnapshot.prototype.getText = function (start, end) {
                        return this.text.substring(start, end);
                    };
                    StringScriptSnapshot.prototype.getLength = function () {
                        return this.text.length;
                    };
                    StringScriptSnapshot.prototype.getChangeRange = function (oldSnapshot) {
                        // Text-based snapshots do not support incremental parsing. Return undefined
                        // to signal that to the caller.
                        return undefined;
                    };
                    return StringScriptSnapshot;
                })();
                function fromString(text) {
                    return new StringScriptSnapshot(text);
                }
                ScriptSnapshot.fromString = fromString;
            })(ScriptSnapshot = ts.ScriptSnapshot || (ts.ScriptSnapshot = {}));
            var scanner = ts.createScanner(2 /* Latest */, true);
            var emptyArray = [];
            function createNode(kind, pos, end, flags, parent) {
                var node = new (ts.getNodeConstructor(kind))();
                node.pos = pos;
                node.end = end;
                node.flags = flags;
                node.parent = parent;
                return node;
            }
            var NodeObject = (function () {
                function NodeObject() {
                }
                NodeObject.prototype.getSourceFile = function () {
                    return ts.getSourceFileOfNode(this);
                };
                NodeObject.prototype.getStart = function (sourceFile) {
                    return ts.getTokenPosOfNode(this, sourceFile);
                };
                NodeObject.prototype.getFullStart = function () {
                    return this.pos;
                };
                NodeObject.prototype.getEnd = function () {
                    return this.end;
                };
                NodeObject.prototype.getWidth = function (sourceFile) {
                    return this.getEnd() - this.getStart(sourceFile);
                };
                NodeObject.prototype.getFullWidth = function () {
                    return this.end - this.getFullStart();
                };
                NodeObject.prototype.getLeadingTriviaWidth = function (sourceFile) {
                    return this.getStart(sourceFile) - this.pos;
                };
                NodeObject.prototype.getFullText = function (sourceFile) {
                    return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end);
                };
                NodeObject.prototype.getText = function (sourceFile) {
                    return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd());
                };
                NodeObject.prototype.addSyntheticNodes = function (nodes, pos, end) {
                    scanner.setTextPos(pos);
                    while (pos < end) {
                        var token = scanner.scan();
                        var textPos = scanner.getTextPos();
                        nodes.push(createNode(token, pos, textPos, 1024 /* Synthetic */, this));
                        pos = textPos;
                    }
                    return pos;
                };
                NodeObject.prototype.createSyntaxList = function (nodes) {
                    var list = createNode(228 /* SyntaxList */, nodes.pos, nodes.end, 1024 /* Synthetic */, this);
                    list._children = [];
                    var pos = nodes.pos;
                    for (var _i = 0; _i < nodes.length; _i++) {
                        var node = nodes[_i];
                        if (pos < node.pos) {
                            pos = this.addSyntheticNodes(list._children, pos, node.pos);
                        }
                        list._children.push(node);
                        pos = node.end;
                    }
                    if (pos < nodes.end) {
                        this.addSyntheticNodes(list._children, pos, nodes.end);
                    }
                    return list;
                };
                NodeObject.prototype.createChildren = function (sourceFile) {
                    var _this = this;
                    var children;
                    if (this.kind >= 126 /* FirstNode */) {
                        scanner.setText((sourceFile || this.getSourceFile()).text);
                        children = [];
                        var pos = this.pos;
                        var processNode = function (node) {
                            if (pos < node.pos) {
                                pos = _this.addSyntheticNodes(children, pos, node.pos);
                            }
                            children.push(node);
                            pos = node.end;
                        };
                        var processNodes = function (nodes) {
                            if (pos < nodes.pos) {
                                pos = _this.addSyntheticNodes(children, pos, nodes.pos);
                            }
                            children.push(_this.createSyntaxList(nodes));
                            pos = nodes.end;
                        };
                        ts.forEachChild(this, processNode, processNodes);
                        if (pos < this.end) {
                            this.addSyntheticNodes(children, pos, this.end);
                        }
                        scanner.setText(undefined);
                    }
                    this._children = children || emptyArray;
                };
                NodeObject.prototype.getChildCount = function (sourceFile) {
                    if (!this._children)
                        this.createChildren(sourceFile);
                    return this._children.length;
                };
                NodeObject.prototype.getChildAt = function (index, sourceFile) {
                    if (!this._children)
                        this.createChildren(sourceFile);
                    return this._children[index];
                };
                NodeObject.prototype.getChildren = function (sourceFile) {
                    if (!this._children)
                        this.createChildren(sourceFile);
                    return this._children;
                };
                NodeObject.prototype.getFirstToken = function (sourceFile) {
                    var children = this.getChildren();
                    for (var _i = 0; _i < children.length; _i++) {
                        var child = children[_i];
                        if (child.kind < 126 /* FirstNode */) {
                            return child;
                        }
                        return child.getFirstToken(sourceFile);
                    }
                };
                NodeObject.prototype.getLastToken = function (sourceFile) {
                    var children = this.getChildren(sourceFile);
                    for (var i = children.length - 1; i >= 0; i--) {
                        var child = children[i];
                        if (child.kind < 126 /* FirstNode */) {
                            return child;
                        }
                        return child.getLastToken(sourceFile);
                    }
                };
                return NodeObject;
            })();
            var SymbolObject = (function () {
                function SymbolObject(flags, name) {
                    this.flags = flags;
                    this.name = name;
                }
                SymbolObject.prototype.getFlags = function () {
                    return this.flags;
                };
                SymbolObject.prototype.getName = function () {
                    return this.name;
                };
                SymbolObject.prototype.getDeclarations = function () {
                    return this.declarations;
                };
                SymbolObject.prototype.getDocumentationComment = function () {
                    if (this.documentationComment === undefined) {
                        this.documentationComment = getJsDocCommentsFromDeclarations(this.declarations, this.name, !(this.flags & 4 /* Property */));
                    }
                    return this.documentationComment;
                };
                return SymbolObject;
            })();
            function getJsDocCommentsFromDeclarations(declarations, name, canUseParsedParamTagComments) {
                var documentationComment = [];
                var docComments = getJsDocCommentsSeparatedByNewLines();
                ts.forEach(docComments, function (docComment) {
                    if (documentationComment.length) {
                        documentationComment.push(ts.lineBreakPart());
                    }
                    documentationComment.push(docComment);
                });
                return documentationComment;
                function getJsDocCommentsSeparatedByNewLines() {
                    var paramTag = "@param";
                    var jsDocCommentParts = [];
                    ts.forEach(declarations, function (declaration, indexOfDeclaration) {
                        // Make sure we are collecting doc comment from declaration once,
                        // In case of union property there might be same declaration multiple times 
                        // which only varies in type parameter
                        // Eg. let a: Array<string> | Array<number>; a.length
                        // The property length will have two declarations of property length coming 
                        // from Array<T> - Array<string> and Array<number>
                        if (ts.indexOf(declarations, declaration) === indexOfDeclaration) {
                            var sourceFileOfDeclaration = ts.getSourceFileOfNode(declaration);
                            // If it is parameter - try and get the jsDoc comment with @param tag from function declaration's jsDoc comments
                            if (canUseParsedParamTagComments && declaration.kind === 129 /* Parameter */) {
                                ts.forEach(getJsDocCommentTextRange(declaration.parent, sourceFileOfDeclaration), function (jsDocCommentTextRange) {
                                    var cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration);
                                    if (cleanedParamJsDocComment) {
                                        jsDocCommentParts.push.apply(jsDocCommentParts, cleanedParamJsDocComment);
                                    }
                                });
                            }
                            // If this is left side of dotted module declaration, there is no doc comments associated with this node
                            if (declaration.kind === 205 /* ModuleDeclaration */ && declaration.body.kind === 205 /* ModuleDeclaration */) {
                                return;
                            }
                            // If this is dotted module name, get the doc comments from the parent
                            while (declaration.kind === 205 /* ModuleDeclaration */ && declaration.parent.kind === 205 /* ModuleDeclaration */) {
                                declaration = declaration.parent;
                            }
                            // Get the cleaned js doc comment text from the declaration
                            ts.forEach(getJsDocCommentTextRange(declaration.kind === 198 /* VariableDeclaration */ ? declaration.parent.parent : declaration, sourceFileOfDeclaration), function (jsDocCommentTextRange) {
                                var cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration);
                                if (cleanedJsDocComment) {
                                    jsDocCommentParts.push.apply(jsDocCommentParts, cleanedJsDocComment);
                                }
                            });
                        }
                    });
                    return jsDocCommentParts;
                    function getJsDocCommentTextRange(node, sourceFile) {
                        return ts.map(ts.getJsDocComments(node, sourceFile), function (jsDocComment) {
                            return {
                                pos: jsDocComment.pos + "/*".length,
                                end: jsDocComment.end - "*/".length // Trim off comment end indicator 
                            };
                        });
                    }
                    function consumeWhiteSpacesOnTheLine(pos, end, sourceFile, maxSpacesToRemove) {
                        if (maxSpacesToRemove !== undefined) {
                            end = Math.min(end, pos + maxSpacesToRemove);
                        }
                        for (; pos < end; pos++) {
                            var ch = sourceFile.text.charCodeAt(pos);
                            if (!ts.isWhiteSpace(ch) || ts.isLineBreak(ch)) {
                                // Either found lineBreak or non whiteSpace
                                return pos;
                            }
                        }
                        return end;
                    }
                    function consumeLineBreaks(pos, end, sourceFile) {
                        while (pos < end && ts.isLineBreak(sourceFile.text.charCodeAt(pos))) {
                            pos++;
                        }
                        return pos;
                    }
                    function isName(pos, end, sourceFile, name) {
                        return pos + name.length < end &&
                            sourceFile.text.substr(pos, name.length) === name &&
                            (ts.isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length)) ||
                                ts.isLineBreak(sourceFile.text.charCodeAt(pos + name.length)));
                    }
                    function isParamTag(pos, end, sourceFile) {
                        // If it is @param tag
                        return isName(pos, end, sourceFile, paramTag);
                    }
                    function pushDocCommentLineText(docComments, text, blankLineCount) {
                        // Add the empty lines in between texts
                        while (blankLineCount--) {
                            docComments.push(ts.textPart(""));
                        }
                        docComments.push(ts.textPart(text));
                    }
                    function getCleanedJsDocComment(pos, end, sourceFile) {
                        var spacesToRemoveAfterAsterisk;
                        var docComments = [];
                        var blankLineCount = 0;
                        var isInParamTag = false;
                        while (pos < end) {
                            var docCommentTextOfLine = "";
                            // First consume leading white space
                            pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile);
                            // If the comment starts with '*' consume the spaces on this line
                            if (pos < end && sourceFile.text.charCodeAt(pos) === 42 /* asterisk */) {
                                var lineStartPos = pos + 1;
                                pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk);
                                // Set the spaces to remove after asterisk as margin if not already set
                                if (spacesToRemoveAfterAsterisk === undefined && pos < end && !ts.isLineBreak(sourceFile.text.charCodeAt(pos))) {
                                    spacesToRemoveAfterAsterisk = pos - lineStartPos;
                                }
                            }
                            else if (spacesToRemoveAfterAsterisk === undefined) {
                                spacesToRemoveAfterAsterisk = 0;
                            }
                            // Analyse text on this line
                            while (pos < end && !ts.isLineBreak(sourceFile.text.charCodeAt(pos))) {
                                var ch = sourceFile.text.charAt(pos);
                                if (ch === "@") {
                                    // If it is @param tag
                                    if (isParamTag(pos, end, sourceFile)) {
                                        isInParamTag = true;
                                        pos += paramTag.length;
                                        continue;
                                    }
                                    else {
                                        isInParamTag = false;
                                    }
                                }
                                // Add the ch to doc text if we arent in param tag
                                if (!isInParamTag) {
                                    docCommentTextOfLine += ch;
                                }
                                // Scan next character
                                pos++;
                            }
                            // Continue with next line
                            pos = consumeLineBreaks(pos, end, sourceFile);
                            if (docCommentTextOfLine) {
                                pushDocCommentLineText(docComments, docCommentTextOfLine, blankLineCount);
                                blankLineCount = 0;
                            }
                            else if (!isInParamTag && docComments.length) {
                                // This is blank line when there is text already parsed
                                blankLineCount++;
                            }
                        }
                        return docComments;
                    }
                    function getCleanedParamJsDocComment(pos, end, sourceFile) {
                        var paramHelpStringMargin;
                        var paramDocComments = [];
                        while (pos < end) {
                            if (isParamTag(pos, end, sourceFile)) {
                                var blankLineCount = 0;
                                var recordedParamTag = false;
                                // Consume leading spaces 
                                pos = consumeWhiteSpaces(pos + paramTag.length);
                                if (pos >= end) {
                                    break;
                                }
                                // Ignore type expression
                                if (sourceFile.text.charCodeAt(pos) === 123 /* openBrace */) {
                                    pos++;
                                    for (var curlies = 1; pos < end; pos++) {
                                        var charCode = sourceFile.text.charCodeAt(pos);
                                        // { character means we need to find another } to match the found one
                                        if (charCode === 123 /* openBrace */) {
                                            curlies++;
                                            continue;
                                        }
                                        // } char
                                        if (charCode === 125 /* closeBrace */) {
                                            curlies--;
                                            if (curlies === 0) {
                                                // We do not have any more } to match the type expression is ignored completely
                                                pos++;
                                                break;
                                            }
                                            else {
                                                // there are more { to be matched with }
                                                continue;
                                            }
                                        }
                                        // Found start of another tag
                                        if (charCode === 64 /* at */) {
                                            break;
                                        }
                                    }
                                    // Consume white spaces
                                    pos = consumeWhiteSpaces(pos);
                                    if (pos >= end) {
                                        break;
                                    }
                                }
                                // Parameter name
                                if (isName(pos, end, sourceFile, name)) {
                                    // Found the parameter we are looking for consume white spaces
                                    pos = consumeWhiteSpaces(pos + name.length);
                                    if (pos >= end) {
                                        break;
                                    }
                                    var paramHelpString = "";
                                    var firstLineParamHelpStringPos = pos;
                                    while (pos < end) {
                                        var ch = sourceFile.text.charCodeAt(pos);
                                        // at line break, set this comment line text and go to next line 
                                        if (ts.isLineBreak(ch)) {
                                            if (paramHelpString) {
                                                pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount);
                                                paramHelpString = "";
                                                blankLineCount = 0;
                                                recordedParamTag = true;
                                            }
                                            else if (recordedParamTag) {
                                                blankLineCount++;
                                            }
                                            // Get the pos after cleaning start of the line
                                            setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos);
                                            continue;
                                        }
                                        // Done scanning param help string - next tag found
                                        if (ch === 64 /* at */) {
                                            break;
                                        }
                                        paramHelpString += sourceFile.text.charAt(pos);
                                        // Go to next character
                                        pos++;
                                    }
                                    // If there is param help text, add it top the doc comments
                                    if (paramHelpString) {
                                        pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount);
                                    }
                                    paramHelpStringMargin = undefined;
                                }
                                // If this is the start of another tag, continue with the loop in seach of param tag with symbol name
                                if (sourceFile.text.charCodeAt(pos) === 64 /* at */) {
                                    continue;
                                }
                            }
                            // Next character
                            pos++;
                        }
                        return paramDocComments;
                        function consumeWhiteSpaces(pos) {
                            while (pos < end && ts.isWhiteSpace(sourceFile.text.charCodeAt(pos))) {
                                pos++;
                            }
                            return pos;
                        }
                        function setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos) {
                            // Get the pos after consuming line breaks
                            pos = consumeLineBreaks(pos, end, sourceFile);
                            if (pos >= end) {
                                return;
                            }
                            if (paramHelpStringMargin === undefined) {
                                paramHelpStringMargin = sourceFile.getLineAndCharacterOfPosition(firstLineParamHelpStringPos).character;
                            }
                            // Now consume white spaces max 
                            var startOfLinePos = pos;
                            pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin);
                            if (pos >= end) {
                                return;
                            }
                            var consumedSpaces = pos - startOfLinePos;
                            if (consumedSpaces < paramHelpStringMargin) {
                                var ch = sourceFile.text.charCodeAt(pos);
                                if (ch === 42 /* asterisk */) {
                                    // Consume more spaces after asterisk
                                    pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1);
                                }
                            }
                        }
                    }
                }
            }
            var TypeObject = (function () {
                function TypeObject(checker, flags) {
                    this.checker = checker;
                    this.flags = flags;
                }
                TypeObject.prototype.getFlags = function () {
                    return this.flags;
                };
                TypeObject.prototype.getSymbol = function () {
                    return this.symbol;
                };
                TypeObject.prototype.getProperties = function () {
                    return this.checker.getPropertiesOfType(this);
                };
                TypeObject.prototype.getProperty = function (propertyName) {
                    return this.checker.getPropertyOfType(this, propertyName);
                };
                TypeObject.prototype.getApparentProperties = function () {
                    return this.checker.getAugmentedPropertiesOfType(this);
                };
                TypeObject.prototype.getCallSignatures = function () {
                    return this.checker.getSignaturesOfType(this, 0 /* Call */);
                };
                TypeObject.prototype.getConstructSignatures = function () {
                    return this.checker.getSignaturesOfType(this, 1 /* Construct */);
                };
                TypeObject.prototype.getStringIndexType = function () {
                    return this.checker.getIndexTypeOfType(this, 0 /* String */);
                };
                TypeObject.prototype.getNumberIndexType = function () {
                    return this.checker.getIndexTypeOfType(this, 1 /* Number */);
                };
                return TypeObject;
            })();
            var SignatureObject = (function () {
                function SignatureObject(checker) {
                    this.checker = checker;
                }
                SignatureObject.prototype.getDeclaration = function () {
                    return this.declaration;
                };
                SignatureObject.prototype.getTypeParameters = function () {
                    return this.typeParameters;
                };
                SignatureObject.prototype.getParameters = function () {
                    return this.parameters;
                };
                SignatureObject.prototype.getReturnType = function () {
                    return this.checker.getReturnTypeOfSignature(this);
                };
                SignatureObject.prototype.getDocumentationComment = function () {
                    if (this.documentationComment === undefined) {
                        this.documentationComment = this.declaration ? getJsDocCommentsFromDeclarations([this.declaration], 
                        /*name*/ undefined, 
                        /*canUseParsedParamTagComments*/ false) : [];
                    }
                    return this.documentationComment;
                };
                return SignatureObject;
            })();
            var SourceFileObject = (function (_super) {
                __extends(SourceFileObject, _super);
                function SourceFileObject() {
                    _super.apply(this, arguments);
                }
                SourceFileObject.prototype.update = function (newText, textChangeRange) {
                    return ts.updateSourceFile(this, newText, textChangeRange);
                };
                SourceFileObject.prototype.getLineAndCharacterOfPosition = function (position) {
                    return ts.getLineAndCharacterOfPosition(this, position);
                };
                SourceFileObject.prototype.getLineStarts = function () {
                    return ts.getLineStarts(this);
                };
                SourceFileObject.prototype.getPositionOfLineAndCharacter = function (line, character) {
                    return ts.getPositionOfLineAndCharacter(this, line, character);
                };
                SourceFileObject.prototype.getNamedDeclarations = function () {
                    if (!this.namedDeclarations) {
                        this.namedDeclarations = this.computeNamedDeclarations();
                    }
                    return this.namedDeclarations;
                };
                SourceFileObject.prototype.computeNamedDeclarations = function () {
                    var result = {};
                    ts.forEachChild(this, visit);
                    return result;
                    function addDeclaration(declaration) {
                        var name = getDeclarationName(declaration);
                        if (name) {
                            var declarations = getDeclarations(name);
                            declarations.push(declaration);
                        }
                    }
                    function getDeclarations(name) {
                        return ts.getProperty(result, name) || (result[name] = []);
                    }
                    function getDeclarationName(declaration) {
                        if (declaration.name) {
                            var result_2 = getTextOfIdentifierOrLiteral(declaration.name);
                            if (result_2 !== undefined) {
                                return result_2;
                            }
                            if (declaration.name.kind === 127 /* ComputedPropertyName */) {
                                var expr = declaration.name.expression;
                                if (expr.kind === 155 /* PropertyAccessExpression */) {
                                    return expr.name.text;
                                }
                                return getTextOfIdentifierOrLiteral(expr);
                            }
                        }
                        return undefined;
                    }
                    function getTextOfIdentifierOrLiteral(node) {
                        if (node) {
                            if (node.kind === 65 /* Identifier */ ||
                                node.kind === 8 /* StringLiteral */ ||
                                node.kind === 7 /* NumericLiteral */) {
                                return node.text;
                            }
                        }
                        return undefined;
                    }
                    function visit(node) {
                        switch (node.kind) {
                            case 200 /* FunctionDeclaration */:
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                                var functionDeclaration = node;
                                var declarationName = getDeclarationName(functionDeclaration);
                                if (declarationName) {
                                    var declarations = getDeclarations(declarationName);
                                    var lastDeclaration = ts.lastOrUndefined(declarations);
                                    // Check whether this declaration belongs to an "overload group".
                                    if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) {
                                        // Overwrite the last declaration if it was an overload
                                        // and this one is an implementation.
                                        if (functionDeclaration.body && !lastDeclaration.body) {
                                            declarations[declarations.length - 1] = functionDeclaration;
                                        }
                                    }
                                    else {
                                        declarations.push(functionDeclaration);
                                    }
                                    ts.forEachChild(node, visit);
                                }
                                break;
                            case 201 /* ClassDeclaration */:
                            case 202 /* InterfaceDeclaration */:
                            case 203 /* TypeAliasDeclaration */:
                            case 204 /* EnumDeclaration */:
                            case 205 /* ModuleDeclaration */:
                            case 208 /* ImportEqualsDeclaration */:
                            case 217 /* ExportSpecifier */:
                            case 213 /* ImportSpecifier */:
                            case 208 /* ImportEqualsDeclaration */:
                            case 210 /* ImportClause */:
                            case 211 /* NamespaceImport */:
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                            case 145 /* TypeLiteral */:
                                addDeclaration(node);
                            // fall through
                            case 135 /* Constructor */:
                            case 180 /* VariableStatement */:
                            case 199 /* VariableDeclarationList */:
                            case 150 /* ObjectBindingPattern */:
                            case 151 /* ArrayBindingPattern */:
                            case 206 /* ModuleBlock */:
                                ts.forEachChild(node, visit);
                                break;
                            case 179 /* Block */:
                                if (ts.isFunctionBlock(node)) {
                                    ts.forEachChild(node, visit);
                                }
                                break;
                            case 129 /* Parameter */:
                                // Only consider properties defined as constructor parameters
                                if (!(node.flags & 112 /* AccessibilityModifier */)) {
                                    break;
                                }
                            // fall through
                            case 198 /* VariableDeclaration */:
                            case 152 /* BindingElement */:
                                if (ts.isBindingPattern(node.name)) {
                                    ts.forEachChild(node.name, visit);
                                    break;
                                }
                            case 226 /* EnumMember */:
                            case 132 /* PropertyDeclaration */:
                            case 131 /* PropertySignature */:
                                addDeclaration(node);
                                break;
                            case 215 /* ExportDeclaration */:
                                // Handle named exports case e.g.:
                                //    export {a, b as B} from "mod";
                                if (node.exportClause) {
                                    ts.forEach(node.exportClause.elements, visit);
                                }
                                break;
                            case 209 /* ImportDeclaration */:
                                var importClause = node.importClause;
                                if (importClause) {
                                    // Handle default import case e.g.:
                                    //    import d from "mod";
                                    if (importClause.name) {
                                        addDeclaration(importClause);
                                    }
                                    // Handle named bindings in imports e.g.:
                                    //    import * as NS from "mod";
                                    //    import {a, b as B} from "mod";
                                    if (importClause.namedBindings) {
                                        if (importClause.namedBindings.kind === 211 /* NamespaceImport */) {
                                            addDeclaration(importClause.namedBindings);
                                        }
                                        else {
                                            ts.forEach(importClause.namedBindings.elements, visit);
                                        }
                                    }
                                }
                                break;
                        }
                    }
                };
                return SourceFileObject;
            })(NodeObject);
            var TextChange = (function () {
                function TextChange() {
                }
                return TextChange;
            })();
            ts.TextChange = TextChange;
            var HighlightSpanKind;
            (function (HighlightSpanKind) {
                HighlightSpanKind.none = "none";
                HighlightSpanKind.definition = "definition";
                HighlightSpanKind.reference = "reference";
                HighlightSpanKind.writtenReference = "writtenReference";
            })(HighlightSpanKind = ts.HighlightSpanKind || (ts.HighlightSpanKind = {}));
            (function (SymbolDisplayPartKind) {
                SymbolDisplayPartKind[SymbolDisplayPartKind["aliasName"] = 0] = "aliasName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["className"] = 1] = "className";
                SymbolDisplayPartKind[SymbolDisplayPartKind["enumName"] = 2] = "enumName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["fieldName"] = 3] = "fieldName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["interfaceName"] = 4] = "interfaceName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["keyword"] = 5] = "keyword";
                SymbolDisplayPartKind[SymbolDisplayPartKind["lineBreak"] = 6] = "lineBreak";
                SymbolDisplayPartKind[SymbolDisplayPartKind["numericLiteral"] = 7] = "numericLiteral";
                SymbolDisplayPartKind[SymbolDisplayPartKind["stringLiteral"] = 8] = "stringLiteral";
                SymbolDisplayPartKind[SymbolDisplayPartKind["localName"] = 9] = "localName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["methodName"] = 10] = "methodName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["moduleName"] = 11] = "moduleName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["operator"] = 12] = "operator";
                SymbolDisplayPartKind[SymbolDisplayPartKind["parameterName"] = 13] = "parameterName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["propertyName"] = 14] = "propertyName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["punctuation"] = 15] = "punctuation";
                SymbolDisplayPartKind[SymbolDisplayPartKind["space"] = 16] = "space";
                SymbolDisplayPartKind[SymbolDisplayPartKind["text"] = 17] = "text";
                SymbolDisplayPartKind[SymbolDisplayPartKind["typeParameterName"] = 18] = "typeParameterName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["enumMemberName"] = 19] = "enumMemberName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["functionName"] = 20] = "functionName";
                SymbolDisplayPartKind[SymbolDisplayPartKind["regularExpressionLiteral"] = 21] = "regularExpressionLiteral";
            })(ts.SymbolDisplayPartKind || (ts.SymbolDisplayPartKind = {}));
            var SymbolDisplayPartKind = ts.SymbolDisplayPartKind;
            (function (OutputFileType) {
                OutputFileType[OutputFileType["JavaScript"] = 0] = "JavaScript";
                OutputFileType[OutputFileType["SourceMap"] = 1] = "SourceMap";
                OutputFileType[OutputFileType["Declaration"] = 2] = "Declaration";
            })(ts.OutputFileType || (ts.OutputFileType = {}));
            var OutputFileType = ts.OutputFileType;
            (function (EndOfLineState) {
                EndOfLineState[EndOfLineState["Start"] = 0] = "Start";
                EndOfLineState[EndOfLineState["InMultiLineCommentTrivia"] = 1] = "InMultiLineCommentTrivia";
                EndOfLineState[EndOfLineState["InSingleQuoteStringLiteral"] = 2] = "InSingleQuoteStringLiteral";
                EndOfLineState[EndOfLineState["InDoubleQuoteStringLiteral"] = 3] = "InDoubleQuoteStringLiteral";
                EndOfLineState[EndOfLineState["InTemplateHeadOrNoSubstitutionTemplate"] = 4] = "InTemplateHeadOrNoSubstitutionTemplate";
                EndOfLineState[EndOfLineState["InTemplateMiddleOrTail"] = 5] = "InTemplateMiddleOrTail";
                EndOfLineState[EndOfLineState["InTemplateSubstitutionPosition"] = 6] = "InTemplateSubstitutionPosition";
            })(ts.EndOfLineState || (ts.EndOfLineState = {}));
            var EndOfLineState = ts.EndOfLineState;
            (function (TokenClass) {
                TokenClass[TokenClass["Punctuation"] = 0] = "Punctuation";
                TokenClass[TokenClass["Keyword"] = 1] = "Keyword";
                TokenClass[TokenClass["Operator"] = 2] = "Operator";
                TokenClass[TokenClass["Comment"] = 3] = "Comment";
                TokenClass[TokenClass["Whitespace"] = 4] = "Whitespace";
                TokenClass[TokenClass["Identifier"] = 5] = "Identifier";
                TokenClass[TokenClass["NumberLiteral"] = 6] = "NumberLiteral";
                TokenClass[TokenClass["StringLiteral"] = 7] = "StringLiteral";
                TokenClass[TokenClass["RegExpLiteral"] = 8] = "RegExpLiteral";
            })(ts.TokenClass || (ts.TokenClass = {}));
            var TokenClass = ts.TokenClass;
            // TODO: move these to enums
            var ScriptElementKind;
            (function (ScriptElementKind) {
                ScriptElementKind.unknown = "";
                ScriptElementKind.warning = "warning";
                // predefined type (void) or keyword (class)
                ScriptElementKind.keyword = "keyword";
                // top level script node
                ScriptElementKind.scriptElement = "script";
                // module foo {}
                ScriptElementKind.moduleElement = "module";
                // class X {}
                ScriptElementKind.classElement = "class";
                // interface Y {}
                ScriptElementKind.interfaceElement = "interface";
                // type T = ...
                ScriptElementKind.typeElement = "type";
                // enum E
                ScriptElementKind.enumElement = "enum";
                // Inside module and script only
                // let v = ..
                ScriptElementKind.variableElement = "var";
                // Inside function
                ScriptElementKind.localVariableElement = "local var";
                // Inside module and script only
                // function f() { }
                ScriptElementKind.functionElement = "function";
                // Inside function
                ScriptElementKind.localFunctionElement = "local function";
                // class X { [public|private]* foo() {} }
                ScriptElementKind.memberFunctionElement = "method";
                // class X { [public|private]* [get|set] foo:number; }
                ScriptElementKind.memberGetAccessorElement = "getter";
                ScriptElementKind.memberSetAccessorElement = "setter";
                // class X { [public|private]* foo:number; }
                // interface Y { foo:number; }
                ScriptElementKind.memberVariableElement = "property";
                // class X { constructor() { } }
                ScriptElementKind.constructorImplementationElement = "constructor";
                // interface Y { ():number; }
                ScriptElementKind.callSignatureElement = "call";
                // interface Y { []:number; }
                ScriptElementKind.indexSignatureElement = "index";
                // interface Y { new():Y; }
                ScriptElementKind.constructSignatureElement = "construct";
                // function foo(*Y*: string)
                ScriptElementKind.parameterElement = "parameter";
                ScriptElementKind.typeParameterElement = "type parameter";
                ScriptElementKind.primitiveType = "primitive type";
                ScriptElementKind.label = "label";
                ScriptElementKind.alias = "alias";
                ScriptElementKind.constElement = "const";
                ScriptElementKind.letElement = "let";
            })(ScriptElementKind = ts.ScriptElementKind || (ts.ScriptElementKind = {}));
            var ScriptElementKindModifier;
            (function (ScriptElementKindModifier) {
                ScriptElementKindModifier.none = "";
                ScriptElementKindModifier.publicMemberModifier = "public";
                ScriptElementKindModifier.privateMemberModifier = "private";
                ScriptElementKindModifier.protectedMemberModifier = "protected";
                ScriptElementKindModifier.exportedModifier = "export";
                ScriptElementKindModifier.ambientModifier = "declare";
                ScriptElementKindModifier.staticModifier = "static";
            })(ScriptElementKindModifier = ts.ScriptElementKindModifier || (ts.ScriptElementKindModifier = {}));
            var ClassificationTypeNames = (function () {
                function ClassificationTypeNames() {
                }
                ClassificationTypeNames.comment = "comment";
                ClassificationTypeNames.identifier = "identifier";
                ClassificationTypeNames.keyword = "keyword";
                ClassificationTypeNames.numericLiteral = "number";
                ClassificationTypeNames.operator = "operator";
                ClassificationTypeNames.stringLiteral = "string";
                ClassificationTypeNames.whiteSpace = "whitespace";
                ClassificationTypeNames.text = "text";
                ClassificationTypeNames.punctuation = "punctuation";
                ClassificationTypeNames.className = "class name";
                ClassificationTypeNames.enumName = "enum name";
                ClassificationTypeNames.interfaceName = "interface name";
                ClassificationTypeNames.moduleName = "module name";
                ClassificationTypeNames.typeParameterName = "type parameter name";
                ClassificationTypeNames.typeAlias = "type alias name";
                return ClassificationTypeNames;
            })();
            ts.ClassificationTypeNames = ClassificationTypeNames;
            function displayPartsToString(displayParts) {
                if (displayParts) {
                    return ts.map(displayParts, function (displayPart) { return displayPart.text; }).join("");
                }
                return "";
            }
            ts.displayPartsToString = displayPartsToString;
            function isLocalVariableOrFunction(symbol) {
                if (symbol.parent) {
                    return false; // This is exported symbol
                }
                return ts.forEach(symbol.declarations, function (declaration) {
                    // Function expressions are local
                    if (declaration.kind === 162 /* FunctionExpression */) {
                        return true;
                    }
                    if (declaration.kind !== 198 /* VariableDeclaration */ && declaration.kind !== 200 /* FunctionDeclaration */) {
                        return false;
                    }
                    // If the parent is not sourceFile or module block it is local variable
                    for (var parent_7 = declaration.parent; !ts.isFunctionBlock(parent_7); parent_7 = parent_7.parent) {
                        // Reached source file or module block
                        if (parent_7.kind === 227 /* SourceFile */ || parent_7.kind === 206 /* ModuleBlock */) {
                            return false;
                        }
                    }
                    // parent is in function block
                    return true;
                });
            }
            function getDefaultCompilerOptions() {
                // Always default to "ScriptTarget.ES5" for the language service
                return {
                    target: 1 /* ES5 */,
                    module: 0 /* None */
                };
            }
            ts.getDefaultCompilerOptions = getDefaultCompilerOptions;
            var OperationCanceledException = (function () {
                function OperationCanceledException() {
                }
                return OperationCanceledException;
            })();
            ts.OperationCanceledException = OperationCanceledException;
            var CancellationTokenObject = (function () {
                function CancellationTokenObject(cancellationToken) {
                    this.cancellationToken = cancellationToken;
                }
                CancellationTokenObject.prototype.isCancellationRequested = function () {
                    return this.cancellationToken && this.cancellationToken.isCancellationRequested();
                };
                CancellationTokenObject.prototype.throwIfCancellationRequested = function () {
                    if (this.isCancellationRequested()) {
                        throw new OperationCanceledException();
                    }
                };
                CancellationTokenObject.None = new CancellationTokenObject(null);
                return CancellationTokenObject;
            })();
            ts.CancellationTokenObject = CancellationTokenObject;
            // Cache host information about scrip Should be refreshed 
            // at each language service public entry point, since we don't know when 
            // set of scripts handled by the host changes.
            var HostCache = (function () {
                function HostCache(host) {
                    this.host = host;
                    // script id => script index
                    this.fileNameToEntry = {};
                    // Initialize the list with the root file names
                    var rootFileNames = host.getScriptFileNames();
                    for (var _i = 0; _i < rootFileNames.length; _i++) {
                        var fileName = rootFileNames[_i];
                        this.createEntry(fileName);
                    }
                    // store the compilation settings
                    this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions();
                }
                HostCache.prototype.compilationSettings = function () {
                    return this._compilationSettings;
                };
                HostCache.prototype.createEntry = function (fileName) {
                    var entry;
                    var scriptSnapshot = this.host.getScriptSnapshot(fileName);
                    if (scriptSnapshot) {
                        entry = {
                            hostFileName: fileName,
                            version: this.host.getScriptVersion(fileName),
                            scriptSnapshot: scriptSnapshot
                        };
                    }
                    return this.fileNameToEntry[ts.normalizeSlashes(fileName)] = entry;
                };
                HostCache.prototype.getEntry = function (fileName) {
                    return ts.lookUp(this.fileNameToEntry, ts.normalizeSlashes(fileName));
                };
                HostCache.prototype.contains = function (fileName) {
                    return ts.hasProperty(this.fileNameToEntry, ts.normalizeSlashes(fileName));
                };
                HostCache.prototype.getOrCreateEntry = function (fileName) {
                    if (this.contains(fileName)) {
                        return this.getEntry(fileName);
                    }
                    return this.createEntry(fileName);
                };
                HostCache.prototype.getRootFileNames = function () {
                    var _this = this;
                    var fileNames = [];
                    ts.forEachKey(this.fileNameToEntry, function (key) {
                        if (ts.hasProperty(_this.fileNameToEntry, key) && _this.fileNameToEntry[key])
                            fileNames.push(key);
                    });
                    return fileNames;
                };
                HostCache.prototype.getVersion = function (fileName) {
                    var file = this.getEntry(fileName);
                    return file && file.version;
                };
                HostCache.prototype.getScriptSnapshot = function (fileName) {
                    var file = this.getEntry(fileName);
                    return file && file.scriptSnapshot;
                };
                return HostCache;
            })();
            var SyntaxTreeCache = (function () {
                function SyntaxTreeCache(host) {
                    this.host = host;
                }
                SyntaxTreeCache.prototype.getCurrentSourceFile = function (fileName) {
                    var scriptSnapshot = this.host.getScriptSnapshot(fileName);
                    if (!scriptSnapshot) {
                        // The host does not know about this file.
                        throw new Error("Could not find file: '" + fileName + "'.");
                    }
                    var version = this.host.getScriptVersion(fileName);
                    var sourceFile;
                    if (this.currentFileName !== fileName) {
                        // This is a new file, just parse it
                        sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 2 /* Latest */, version, true);
                    }
                    else if (this.currentFileVersion !== version) {
                        // This is the same file, just a newer version. Incrementally parse the file.
                        var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot);
                        sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange);
                    }
                    if (sourceFile) {
                        // All done, ensure state is up to date
                        this.currentFileVersion = version;
                        this.currentFileName = fileName;
                        this.currentFileScriptSnapshot = scriptSnapshot;
                        this.currentSourceFile = sourceFile;
                    }
                    return this.currentSourceFile;
                };
                return SyntaxTreeCache;
            })();
            function setSourceFileFields(sourceFile, scriptSnapshot, version) {
                sourceFile.version = version;
                sourceFile.scriptSnapshot = scriptSnapshot;
            }
            /*
             * This function will compile source text from 'input' argument using specified compiler options.
             * If not options are provided - it will use a set of default compiler options.
             * Extra compiler options that will unconditionally be used bu this function are:
             * - separateCompilation = true
             * - allowNonTsExtensions = true
             */
            function transpile(input, compilerOptions, fileName, diagnostics) {
                var options = compilerOptions ? ts.clone(compilerOptions) : getDefaultCompilerOptions();
                options.separateCompilation = true;
                // Filename can be non-ts file.
                options.allowNonTsExtensions = true;
                // Parse
                var inputFileName = fileName || "module.ts";
                var sourceFile = ts.createSourceFile(inputFileName, input, options.target);
                // Store syntactic diagnostics
                if (diagnostics && sourceFile.parseDiagnostics) {
                    diagnostics.push.apply(diagnostics, sourceFile.parseDiagnostics);
                }
                // Output
                var outputText;
                // Create a compilerHost object to allow the compiler to read and write files
                var compilerHost = {
                    getSourceFile: function (fileName, target) { return fileName === inputFileName ? sourceFile : undefined; },
                    writeFile: function (name, text, writeByteOrderMark) {
                        ts.Debug.assert(outputText === undefined, "Unexpected multiple outputs for the file: " + name);
                        outputText = text;
                    },
                    getDefaultLibFileName: function () { return "lib.d.ts"; },
                    useCaseSensitiveFileNames: function () { return false; },
                    getCanonicalFileName: function (fileName) { return fileName; },
                    getCurrentDirectory: function () { return ""; },
                    getNewLine: function () { return (ts.sys && ts.sys.newLine) || "\r\n"; }
                };
                var program = ts.createProgram([inputFileName], options, compilerHost);
                if (diagnostics) {
                    diagnostics.push.apply(diagnostics, program.getGlobalDiagnostics());
                }
                // Emit
                program.emit();
                ts.Debug.assert(outputText !== undefined, "Output generation failed");
                return outputText;
            }
            ts.transpile = transpile;
            function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents) {
                var sourceFile = ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), scriptTarget, setNodeParents);
                setSourceFileFields(sourceFile, scriptSnapshot, version);
                // after full parsing we can use table with interned strings as name table
                sourceFile.nameTable = sourceFile.identifiers;
                return sourceFile;
            }
            ts.createLanguageServiceSourceFile = createLanguageServiceSourceFile;
            ts.disableIncrementalParsing = false;
            function updateLanguageServiceSourceFile(sourceFile, scriptSnapshot, version, textChangeRange, aggressiveChecks) {
                // If we were given a text change range, and our version or open-ness changed, then 
                // incrementally parse this file.
                if (textChangeRange) {
                    if (version !== sourceFile.version) {
                        // Once incremental parsing is ready, then just call into this function.
                        if (!ts.disableIncrementalParsing) {
                            var newSourceFile = ts.updateSourceFile(sourceFile, scriptSnapshot.getText(0, scriptSnapshot.getLength()), textChangeRange, aggressiveChecks);
                            setSourceFileFields(newSourceFile, scriptSnapshot, version);
                            // after incremental parsing nameTable might not be up-to-date
                            // drop it so it can be lazily recreated later
                            newSourceFile.nameTable = undefined;
                            return newSourceFile;
                        }
                    }
                }
                // Otherwise, just create a new source file.
                return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, true);
            }
            ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile;
            function createDocumentRegistry() {
                // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have
                // for those settings.
                var buckets = {};
                function getKeyFromCompilationSettings(settings) {
                    return "_" + settings.target; //  + "|" + settings.propagateEnumConstantoString()
                }
                function getBucketForCompilationSettings(settings, createIfMissing) {
                    var key = getKeyFromCompilationSettings(settings);
                    var bucket = ts.lookUp(buckets, key);
                    if (!bucket && createIfMissing) {
                        buckets[key] = bucket = {};
                    }
                    return bucket;
                }
                function reportStats() {
                    var bucketInfoArray = Object.keys(buckets).filter(function (name) { return name && name.charAt(0) === '_'; }).map(function (name) {
                        var entries = ts.lookUp(buckets, name);
                        var sourceFiles = [];
                        for (var i in entries) {
                            var entry = entries[i];
                            sourceFiles.push({
                                name: i,
                                refCount: entry.languageServiceRefCount,
                                references: entry.owners.slice(0)
                            });
                        }
                        sourceFiles.sort(function (x, y) { return y.refCount - x.refCount; });
                        return {
                            bucket: name,
                            sourceFiles: sourceFiles
                        };
                    });
                    return JSON.stringify(bucketInfoArray, null, 2);
                }
                function acquireDocument(fileName, compilationSettings, scriptSnapshot, version) {
                    return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, true);
                }
                function updateDocument(fileName, compilationSettings, scriptSnapshot, version) {
                    return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, false);
                }
                function acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, acquiring) {
                    var bucket = getBucketForCompilationSettings(compilationSettings, true);
                    var entry = ts.lookUp(bucket, fileName);
                    if (!entry) {
                        ts.Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?");
                        // Have never seen this file with these settings.  Create a new source file for it.
                        var sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, false);
                        bucket[fileName] = entry = {
                            sourceFile: sourceFile,
                            languageServiceRefCount: 0,
                            owners: []
                        };
                    }
                    else {
                        // We have an entry for this file.  However, it may be for a different version of 
                        // the script snapshot.  If so, update it appropriately.  Otherwise, we can just
                        // return it as is.
                        if (entry.sourceFile.version !== version) {
                            entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot));
                        }
                    }
                    // If we're acquiring, then this is the first time this LS is asking for this document.
                    // Increase our ref count so we know there's another LS using the document.  If we're
                    // not acquiring, then that means the LS is 'updating' the file instead, and that means
                    // it has already acquired the document previously.  As such, we do not need to increase
                    // the ref count.
                    if (acquiring) {
                        entry.languageServiceRefCount++;
                    }
                    return entry.sourceFile;
                }
                function releaseDocument(fileName, compilationSettings) {
                    var bucket = getBucketForCompilationSettings(compilationSettings, false);
                    ts.Debug.assert(bucket !== undefined);
                    var entry = ts.lookUp(bucket, fileName);
                    entry.languageServiceRefCount--;
                    ts.Debug.assert(entry.languageServiceRefCount >= 0);
                    if (entry.languageServiceRefCount === 0) {
                        delete bucket[fileName];
                    }
                }
                return {
                    acquireDocument: acquireDocument,
                    updateDocument: updateDocument,
                    releaseDocument: releaseDocument,
                    reportStats: reportStats
                };
            }
            ts.createDocumentRegistry = createDocumentRegistry;
            function preProcessFile(sourceText, readImportFiles) {
                if (readImportFiles === void 0) { readImportFiles = true; }
                var referencedFiles = [];
                var importedFiles = [];
                var isNoDefaultLib = false;
                function processTripleSlashDirectives() {
                    var commentRanges = ts.getLeadingCommentRanges(sourceText, 0);
                    ts.forEach(commentRanges, function (commentRange) {
                        var comment = sourceText.substring(commentRange.pos, commentRange.end);
                        var referencePathMatchResult = ts.getFileReferenceFromReferencePath(comment, commentRange);
                        if (referencePathMatchResult) {
                            isNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
                            var fileReference = referencePathMatchResult.fileReference;
                            if (fileReference) {
                                referencedFiles.push(fileReference);
                            }
                        }
                    });
                }
                function recordModuleName() {
                    var importPath = scanner.getTokenValue();
                    var pos = scanner.getTokenPos();
                    importedFiles.push({
                        fileName: importPath,
                        pos: pos,
                        end: pos + importPath.length
                    });
                }
                function processImport() {
                    scanner.setText(sourceText);
                    var token = scanner.scan();
                    // Look for:
                    //    import "mod";
                    //    import d from "mod"
                    //    import {a as A } from "mod";
                    //    import * as NS  from "mod"
                    //    import d, {a, b as B} from "mod"
                    //    import i = require("mod");
                    //
                    //    export * from "mod"
                    //    export {a as b} from "mod"
                    while (token !== 1 /* EndOfFileToken */) {
                        if (token === 85 /* ImportKeyword */) {
                            token = scanner.scan();
                            if (token === 8 /* StringLiteral */) {
                                // import "mod";
                                recordModuleName();
                                continue;
                            }
                            else {
                                if (token === 65 /* Identifier */) {
                                    token = scanner.scan();
                                    if (token === 124 /* FromKeyword */) {
                                        token = scanner.scan();
                                        if (token === 8 /* StringLiteral */) {
                                            // import d from "mod";
                                            recordModuleName();
                                            continue;
                                        }
                                    }
                                    else if (token === 53 /* EqualsToken */) {
                                        token = scanner.scan();
                                        if (token === 118 /* RequireKeyword */) {
                                            token = scanner.scan();
                                            if (token === 16 /* OpenParenToken */) {
                                                token = scanner.scan();
                                                if (token === 8 /* StringLiteral */) {
                                                    //  import i = require("mod");
                                                    recordModuleName();
                                                    continue;
                                                }
                                            }
                                        }
                                    }
                                    else if (token === 23 /* CommaToken */) {
                                        // consume comma and keep going
                                        token = scanner.scan();
                                    }
                                    else {
                                        // unknown syntax
                                        continue;
                                    }
                                }
                                if (token === 14 /* OpenBraceToken */) {
                                    token = scanner.scan();
                                    // consume "{ a as B, c, d as D}" clauses
                                    while (token !== 15 /* CloseBraceToken */) {
                                        token = scanner.scan();
                                    }
                                    if (token === 15 /* CloseBraceToken */) {
                                        token = scanner.scan();
                                        if (token === 124 /* FromKeyword */) {
                                            token = scanner.scan();
                                            if (token === 8 /* StringLiteral */) {
                                                // import {a as A} from "mod";
                                                // import d, {a, b as B} from "mod"
                                                recordModuleName();
                                            }
                                        }
                                    }
                                }
                                else if (token === 35 /* AsteriskToken */) {
                                    token = scanner.scan();
                                    if (token === 111 /* AsKeyword */) {
                                        token = scanner.scan();
                                        if (token === 65 /* Identifier */) {
                                            token = scanner.scan();
                                            if (token === 124 /* FromKeyword */) {
                                                token = scanner.scan();
                                                if (token === 8 /* StringLiteral */) {
                                                    // import * as NS from "mod"
                                                    // import d, * as NS from "mod"
                                                    recordModuleName();
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else if (token === 78 /* ExportKeyword */) {
                            token = scanner.scan();
                            if (token === 14 /* OpenBraceToken */) {
                                token = scanner.scan();
                                // consume "{ a as B, c, d as D}" clauses
                                while (token !== 15 /* CloseBraceToken */) {
                                    token = scanner.scan();
                                }
                                if (token === 15 /* CloseBraceToken */) {
                                    token = scanner.scan();
                                    if (token === 124 /* FromKeyword */) {
                                        token = scanner.scan();
                                        if (token === 8 /* StringLiteral */) {
                                            // export {a as A} from "mod";
                                            // export {a, b as B} from "mod"
                                            recordModuleName();
                                        }
                                    }
                                }
                            }
                            else if (token === 35 /* AsteriskToken */) {
                                token = scanner.scan();
                                if (token === 124 /* FromKeyword */) {
                                    token = scanner.scan();
                                    if (token === 8 /* StringLiteral */) {
                                        // export * from "mod"
                                        recordModuleName();
                                    }
                                }
                            }
                        }
                        token = scanner.scan();
                    }
                    scanner.setText(undefined);
                }
                if (readImportFiles) {
                    processImport();
                }
                processTripleSlashDirectives();
                return { referencedFiles: referencedFiles, importedFiles: importedFiles, isLibFile: isNoDefaultLib };
            }
            ts.preProcessFile = preProcessFile;
            /// Helpers
            function getTargetLabel(referenceNode, labelName) {
                while (referenceNode) {
                    if (referenceNode.kind === 194 /* LabeledStatement */ && referenceNode.label.text === labelName) {
                        return referenceNode.label;
                    }
                    referenceNode = referenceNode.parent;
                }
                return undefined;
            }
            function isJumpStatementTarget(node) {
                return node.kind === 65 /* Identifier */ &&
                    (node.parent.kind === 190 /* BreakStatement */ || node.parent.kind === 189 /* ContinueStatement */) &&
                    node.parent.label === node;
            }
            function isLabelOfLabeledStatement(node) {
                return node.kind === 65 /* Identifier */ &&
                    node.parent.kind === 194 /* LabeledStatement */ &&
                    node.parent.label === node;
            }
            /**
             * Whether or not a 'node' is preceded by a label of the given string.
             * Note: 'node' cannot be a SourceFile.
             */
            function isLabeledBy(node, labelName) {
                for (var owner = node.parent; owner.kind === 194 /* LabeledStatement */; owner = owner.parent) {
                    if (owner.label.text === labelName) {
                        return true;
                    }
                }
                return false;
            }
            function isLabelName(node) {
                return isLabelOfLabeledStatement(node) || isJumpStatementTarget(node);
            }
            function isRightSideOfQualifiedName(node) {
                return node.parent.kind === 126 /* QualifiedName */ && node.parent.right === node;
            }
            function isRightSideOfPropertyAccess(node) {
                return node && node.parent && node.parent.kind === 155 /* PropertyAccessExpression */ && node.parent.name === node;
            }
            function isCallExpressionTarget(node) {
                if (isRightSideOfPropertyAccess(node)) {
                    node = node.parent;
                }
                return node && node.parent && node.parent.kind === 157 /* CallExpression */ && node.parent.expression === node;
            }
            function isNewExpressionTarget(node) {
                if (isRightSideOfPropertyAccess(node)) {
                    node = node.parent;
                }
                return node && node.parent && node.parent.kind === 158 /* NewExpression */ && node.parent.expression === node;
            }
            function isNameOfModuleDeclaration(node) {
                return node.parent.kind === 205 /* ModuleDeclaration */ && node.parent.name === node;
            }
            function isNameOfFunctionDeclaration(node) {
                return node.kind === 65 /* Identifier */ &&
                    ts.isFunctionLike(node.parent) && node.parent.name === node;
            }
            /** Returns true if node is a name of an object literal property, e.g. "a" in x = { "a": 1 } */
            function isNameOfPropertyAssignment(node) {
                return (node.kind === 65 /* Identifier */ || node.kind === 8 /* StringLiteral */ || node.kind === 7 /* NumericLiteral */) &&
                    (node.parent.kind === 224 /* PropertyAssignment */ || node.parent.kind === 225 /* ShorthandPropertyAssignment */) && node.parent.name === node;
            }
            function isLiteralNameOfPropertyDeclarationOrIndexAccess(node) {
                if (node.kind === 8 /* StringLiteral */ || node.kind === 7 /* NumericLiteral */) {
                    switch (node.parent.kind) {
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                        case 224 /* PropertyAssignment */:
                        case 226 /* EnumMember */:
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                        case 205 /* ModuleDeclaration */:
                            return node.parent.name === node;
                        case 156 /* ElementAccessExpression */:
                            return node.parent.argumentExpression === node;
                    }
                }
                return false;
            }
            function isNameOfExternalModuleImportOrDeclaration(node) {
                if (node.kind === 8 /* StringLiteral */) {
                    return isNameOfModuleDeclaration(node) ||
                        (ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) && ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node);
                }
                return false;
            }
            /** Returns true if the position is within a comment */
            function isInsideComment(sourceFile, token, position) {
                // The position has to be: 1. in the leading trivia (before token.getStart()), and 2. within a comment
                return position <= token.getStart(sourceFile) &&
                    (isInsideCommentRange(ts.getTrailingCommentRanges(sourceFile.text, token.getFullStart())) ||
                        isInsideCommentRange(ts.getLeadingCommentRanges(sourceFile.text, token.getFullStart())));
                function isInsideCommentRange(comments) {
                    return ts.forEach(comments, function (comment) {
                        // either we are 1. completely inside the comment, or 2. at the end of the comment
                        if (comment.pos < position && position < comment.end) {
                            return true;
                        }
                        else if (position === comment.end) {
                            var text = sourceFile.text;
                            var width = comment.end - comment.pos;
                            // is single line comment or just /*
                            if (width <= 2 || text.charCodeAt(comment.pos + 1) === 47 /* slash */) {
                                return true;
                            }
                            else {
                                // is unterminated multi-line comment
                                return !(text.charCodeAt(comment.end - 1) === 47 /* slash */ &&
                                    text.charCodeAt(comment.end - 2) === 42 /* asterisk */);
                            }
                        }
                        return false;
                    });
                }
            }
            var SemanticMeaning;
            (function (SemanticMeaning) {
                SemanticMeaning[SemanticMeaning["None"] = 0] = "None";
                SemanticMeaning[SemanticMeaning["Value"] = 1] = "Value";
                SemanticMeaning[SemanticMeaning["Type"] = 2] = "Type";
                SemanticMeaning[SemanticMeaning["Namespace"] = 4] = "Namespace";
                SemanticMeaning[SemanticMeaning["All"] = 7] = "All";
            })(SemanticMeaning || (SemanticMeaning = {}));
            var BreakContinueSearchType;
            (function (BreakContinueSearchType) {
                BreakContinueSearchType[BreakContinueSearchType["None"] = 0] = "None";
                BreakContinueSearchType[BreakContinueSearchType["Unlabeled"] = 1] = "Unlabeled";
                BreakContinueSearchType[BreakContinueSearchType["Labeled"] = 2] = "Labeled";
                BreakContinueSearchType[BreakContinueSearchType["All"] = 3] = "All";
            })(BreakContinueSearchType || (BreakContinueSearchType = {}));
            // A cache of completion entries for keywords, these do not change between sessions
            var keywordCompletions = [];
            for (var i = 66 /* FirstKeyword */; i <= 125 /* LastKeyword */; i++) {
                keywordCompletions.push({
                    name: ts.tokenToString(i),
                    kind: ScriptElementKind.keyword,
                    kindModifiers: ScriptElementKindModifier.none,
                    sortText: "0"
                });
            }
            /* @internal */ function getContainerNode(node) {
                while (true) {
                    node = node.parent;
                    if (!node) {
                        return undefined;
                    }
                    switch (node.kind) {
                        case 227 /* SourceFile */:
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                        case 200 /* FunctionDeclaration */:
                        case 162 /* FunctionExpression */:
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                        case 201 /* ClassDeclaration */:
                        case 202 /* InterfaceDeclaration */:
                        case 204 /* EnumDeclaration */:
                        case 205 /* ModuleDeclaration */:
                            return node;
                    }
                }
            }
            ts.getContainerNode = getContainerNode;
            /* @internal */ function getNodeKind(node) {
                switch (node.kind) {
                    case 205 /* ModuleDeclaration */: return ScriptElementKind.moduleElement;
                    case 201 /* ClassDeclaration */: return ScriptElementKind.classElement;
                    case 202 /* InterfaceDeclaration */: return ScriptElementKind.interfaceElement;
                    case 203 /* TypeAliasDeclaration */: return ScriptElementKind.typeElement;
                    case 204 /* EnumDeclaration */: return ScriptElementKind.enumElement;
                    case 198 /* VariableDeclaration */:
                        return ts.isConst(node)
                            ? ScriptElementKind.constElement
                            : ts.isLet(node)
                                ? ScriptElementKind.letElement
                                : ScriptElementKind.variableElement;
                    case 200 /* FunctionDeclaration */: return ScriptElementKind.functionElement;
                    case 136 /* GetAccessor */: return ScriptElementKind.memberGetAccessorElement;
                    case 137 /* SetAccessor */: return ScriptElementKind.memberSetAccessorElement;
                    case 134 /* MethodDeclaration */:
                    case 133 /* MethodSignature */:
                        return ScriptElementKind.memberFunctionElement;
                    case 132 /* PropertyDeclaration */:
                    case 131 /* PropertySignature */:
                        return ScriptElementKind.memberVariableElement;
                    case 140 /* IndexSignature */: return ScriptElementKind.indexSignatureElement;
                    case 139 /* ConstructSignature */: return ScriptElementKind.constructSignatureElement;
                    case 138 /* CallSignature */: return ScriptElementKind.callSignatureElement;
                    case 135 /* Constructor */: return ScriptElementKind.constructorImplementationElement;
                    case 128 /* TypeParameter */: return ScriptElementKind.typeParameterElement;
                    case 226 /* EnumMember */: return ScriptElementKind.variableElement;
                    case 129 /* Parameter */: return (node.flags & 112 /* AccessibilityModifier */) ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement;
                    case 208 /* ImportEqualsDeclaration */:
                    case 213 /* ImportSpecifier */:
                    case 210 /* ImportClause */:
                    case 217 /* ExportSpecifier */:
                    case 211 /* NamespaceImport */:
                        return ScriptElementKind.alias;
                }
                return ScriptElementKind.unknown;
            }
            ts.getNodeKind = getNodeKind;
            function createLanguageService(host, documentRegistry) {
                if (documentRegistry === void 0) { documentRegistry = createDocumentRegistry(); }
                var syntaxTreeCache = new SyntaxTreeCache(host);
                var ruleProvider;
                var program;
                var useCaseSensitivefileNames = false;
                var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken());
                // Check if the localized messages json is set, otherwise query the host for it
                if (!ts.localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) {
                    ts.localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages();
                }
                function log(message) {
                    if (host.log) {
                        host.log(message);
                    }
                }
                function getCanonicalFileName(fileName) {
                    return useCaseSensitivefileNames ? fileName : fileName.toLowerCase();
                }
                function getValidSourceFile(fileName) {
                    fileName = ts.normalizeSlashes(fileName);
                    var sourceFile = program.getSourceFile(getCanonicalFileName(fileName));
                    if (!sourceFile) {
                        throw new Error("Could not find file: '" + fileName + "'.");
                    }
                    return sourceFile;
                }
                function getRuleProvider(options) {
                    // Ensure rules are initialized and up to date wrt to formatting options
                    if (!ruleProvider) {
                        ruleProvider = new ts.formatting.RulesProvider();
                    }
                    ruleProvider.ensureUpToDate(options);
                    return ruleProvider;
                }
                function synchronizeHostData() {
                    // Get a fresh cache of the host information
                    var hostCache = new HostCache(host);
                    // If the program is already up-to-date, we can reuse it
                    if (programUpToDate()) {
                        return;
                    }
                    // IMPORTANT - It is critical from this moment onward that we do not check 
                    // cancellation tokens.  We are about to mutate source files from a previous program
                    // instance.  If we cancel midway through, we may end up in an inconsistent state where
                    // the program points to old source files that have been invalidated because of 
                    // incremental parsing.
                    var oldSettings = program && program.getCompilerOptions();
                    var newSettings = hostCache.compilationSettings();
                    var changesInCompilationSettingsAffectSyntax = oldSettings && oldSettings.target !== newSettings.target;
                    // Now create a new compiler
                    var newProgram = ts.createProgram(hostCache.getRootFileNames(), newSettings, {
                        getSourceFile: getOrCreateSourceFile,
                        getCancellationToken: function () { return cancellationToken; },
                        getCanonicalFileName: function (fileName) { return useCaseSensitivefileNames ? fileName : fileName.toLowerCase(); },
                        useCaseSensitiveFileNames: function () { return useCaseSensitivefileNames; },
                        getNewLine: function () { return host.getNewLine ? host.getNewLine() : "\r\n"; },
                        getDefaultLibFileName: function (options) { return host.getDefaultLibFileName(options); },
                        writeFile: function (fileName, data, writeByteOrderMark) { },
                        getCurrentDirectory: function () { return host.getCurrentDirectory(); }
                    });
                    // Release any files we have acquired in the old program but are 
                    // not part of the new program.
                    if (program) {
                        var oldSourceFiles = program.getSourceFiles();
                        for (var _i = 0; _i < oldSourceFiles.length; _i++) {
                            var oldSourceFile = oldSourceFiles[_i];
                            var fileName = oldSourceFile.fileName;
                            if (!newProgram.getSourceFile(fileName) || changesInCompilationSettingsAffectSyntax) {
                                documentRegistry.releaseDocument(fileName, oldSettings);
                            }
                        }
                    }
                    program = newProgram;
                    // Make sure all the nodes in the program are both bound, and have their parent 
                    // pointers set property.
                    program.getTypeChecker();
                    return;
                    function getOrCreateSourceFile(fileName) {
                        // The program is asking for this file, check first if the host can locate it.
                        // If the host can not locate the file, then it does not exist. return undefined
                        // to the program to allow reporting of errors for missing files.
                        var hostFileInformation = hostCache.getOrCreateEntry(fileName);
                        if (!hostFileInformation) {
                            return undefined;
                        }
                        // Check if the language version has changed since we last created a program; if they are the same,
                        // it is safe to reuse the souceFiles; if not, then the shape of the AST can change, and the oldSourceFile
                        // can not be reused. we have to dump all syntax trees and create new ones.
                        if (!changesInCompilationSettingsAffectSyntax) {
                            // Check if the old program had this file already
                            var oldSourceFile = program && program.getSourceFile(fileName);
                            if (oldSourceFile) {
                                // We already had a source file for this file name.  Go to the registry to 
                                // ensure that we get the right up to date version of it.  We need this to
                                // address the following 'race'.  Specifically, say we have the following:
                                //
                                //      LS1
                                //          \
                                //           DocumentRegistry
                                //          /
                                //      LS2
                                //
                                // Each LS has a reference to file 'foo.ts' at version 1.  LS2 then updates
                                // it's version of 'foo.ts' to version 2.  This will cause LS2 and the 
                                // DocumentRegistry to have version 2 of the document.  HOwever, LS1 will 
                                // have version 1.  And *importantly* this source file will be *corrupt*.
                                // The act of creating version 2 of the file irrevocably damages the version
                                // 1 file.
                                //
                                // So, later when we call into LS1, we need to make sure that it doesn't use
                                // it's source file any more, and instead defers to DocumentRegistry to get
                                // either version 1, version 2 (or some other version) depending on what the 
                                // host says should be used.
                                return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version);
                            }
                        }
                        // Could not find this file in the old program, create a new SourceFile for it.
                        return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version);
                    }
                    function sourceFileUpToDate(sourceFile) {
                        return sourceFile && sourceFile.version === hostCache.getVersion(sourceFile.fileName);
                    }
                    function programUpToDate() {
                        // If we haven't create a program yet, then it is not up-to-date
                        if (!program) {
                            return false;
                        }
                        // If number of files in the program do not match, it is not up-to-date
                        var rootFileNames = hostCache.getRootFileNames();
                        if (program.getSourceFiles().length !== rootFileNames.length) {
                            return false;
                        }
                        // If any file is not up-to-date, then the whole program is not up-to-date
                        for (var _i = 0; _i < rootFileNames.length; _i++) {
                            var fileName = rootFileNames[_i];
                            if (!sourceFileUpToDate(program.getSourceFile(fileName))) {
                                return false;
                            }
                        }
                        // If the compilation settings do no match, then the program is not up-to-date
                        return ts.compareDataObjects(program.getCompilerOptions(), hostCache.compilationSettings());
                    }
                }
                function getProgram() {
                    synchronizeHostData();
                    return program;
                }
                function cleanupSemanticCache() {
                    // TODO: Should we jettison the program (or it's type checker) here?
                }
                function dispose() {
                    if (program) {
                        ts.forEach(program.getSourceFiles(), function (f) {
                            return documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions());
                        });
                    }
                }
                /// Diagnostics
                function getSyntacticDiagnostics(fileName) {
                    synchronizeHostData();
                    return program.getSyntacticDiagnostics(getValidSourceFile(fileName));
                }
                /**
                 * getSemanticDiagnostiscs return array of Diagnostics. If '-d' is not enabled, only report semantic errors
                 * If '-d' enabled, report both semantic and emitter errors
                 */
                function getSemanticDiagnostics(fileName) {
                    synchronizeHostData();
                    var targetSourceFile = getValidSourceFile(fileName);
                    // For JavaScript files, we don't want to report the normal typescript semantic errors.
                    // Instead, we just report errors for using TypeScript-only constructs from within a 
                    // JavaScript file.
                    if (ts.isJavaScript(fileName)) {
                        return getJavaScriptSemanticDiagnostics(targetSourceFile);
                    }
                    // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file.
                    // Therefore only get diagnostics for given file.
                    var semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile);
                    if (!program.getCompilerOptions().declaration) {
                        return semanticDiagnostics;
                    }
                    // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface
                    var declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile);
                    return ts.concatenate(semanticDiagnostics, declarationDiagnostics);
                }
                function getJavaScriptSemanticDiagnostics(sourceFile) {
                    var diagnostics = [];
                    walk(sourceFile);
                    return diagnostics;
                    function walk(node) {
                        if (!node) {
                            return false;
                        }
                        switch (node.kind) {
                            case 208 /* ImportEqualsDeclaration */:
                                diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.import_can_only_be_used_in_a_ts_file));
                                return true;
                            case 214 /* ExportAssignment */:
                                diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.export_can_only_be_used_in_a_ts_file));
                                return true;
                            case 201 /* ClassDeclaration */:
                                var classDeclaration = node;
                                if (checkModifiers(classDeclaration.modifiers) ||
                                    checkTypeParameters(classDeclaration.typeParameters)) {
                                    return true;
                                }
                                break;
                            case 222 /* HeritageClause */:
                                var heritageClause = node;
                                if (heritageClause.token === 102 /* ImplementsKeyword */) {
                                    diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.implements_clauses_can_only_be_used_in_a_ts_file));
                                    return true;
                                }
                                break;
                            case 202 /* InterfaceDeclaration */:
                                diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.interface_declarations_can_only_be_used_in_a_ts_file));
                                return true;
                            case 205 /* ModuleDeclaration */:
                                diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.module_declarations_can_only_be_used_in_a_ts_file));
                                return true;
                            case 203 /* TypeAliasDeclaration */:
                                diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.type_aliases_can_only_be_used_in_a_ts_file));
                                return true;
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                            case 135 /* Constructor */:
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                            case 162 /* FunctionExpression */:
                            case 200 /* FunctionDeclaration */:
                            case 163 /* ArrowFunction */:
                            case 200 /* FunctionDeclaration */:
                                var functionDeclaration = node;
                                if (checkModifiers(functionDeclaration.modifiers) ||
                                    checkTypeParameters(functionDeclaration.typeParameters) ||
                                    checkTypeAnnotation(functionDeclaration.type)) {
                                    return true;
                                }
                                break;
                            case 180 /* VariableStatement */:
                                var variableStatement = node;
                                if (checkModifiers(variableStatement.modifiers)) {
                                    return true;
                                }
                                break;
                            case 198 /* VariableDeclaration */:
                                var variableDeclaration = node;
                                if (checkTypeAnnotation(variableDeclaration.type)) {
                                    return true;
                                }
                                break;
                            case 157 /* CallExpression */:
                            case 158 /* NewExpression */:
                                var expression = node;
                                if (expression.typeArguments && expression.typeArguments.length > 0) {
                                    var start = expression.typeArguments.pos;
                                    diagnostics.push(ts.createFileDiagnostic(sourceFile, start, expression.typeArguments.end - start, ts.Diagnostics.type_arguments_can_only_be_used_in_a_ts_file));
                                    return true;
                                }
                                break;
                            case 129 /* Parameter */:
                                var parameter = node;
                                if (parameter.modifiers) {
                                    var start = parameter.modifiers.pos;
                                    diagnostics.push(ts.createFileDiagnostic(sourceFile, start, parameter.modifiers.end - start, ts.Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file));
                                    return true;
                                }
                                if (parameter.questionToken) {
                                    diagnostics.push(ts.createDiagnosticForNode(parameter.questionToken, ts.Diagnostics.can_only_be_used_in_a_ts_file));
                                    return true;
                                }
                                if (parameter.type) {
                                    diagnostics.push(ts.createDiagnosticForNode(parameter.type, ts.Diagnostics.types_can_only_be_used_in_a_ts_file));
                                    return true;
                                }
                                break;
                            case 132 /* PropertyDeclaration */:
                                diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.property_declarations_can_only_be_used_in_a_ts_file));
                                return true;
                            case 204 /* EnumDeclaration */:
                                diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file));
                                return true;
                            case 160 /* TypeAssertionExpression */:
                                var typeAssertionExpression = node;
                                diagnostics.push(ts.createDiagnosticForNode(typeAssertionExpression.type, ts.Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file));
                                return true;
                            case 130 /* Decorator */:
                                diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.decorators_can_only_be_used_in_a_ts_file));
                                return true;
                        }
                        return ts.forEachChild(node, walk);
                    }
                    function checkTypeParameters(typeParameters) {
                        if (typeParameters) {
                            var start = typeParameters.pos;
                            diagnostics.push(ts.createFileDiagnostic(sourceFile, start, typeParameters.end - start, ts.Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file));
                            return true;
                        }
                        return false;
                    }
                    function checkTypeAnnotation(type) {
                        if (type) {
                            diagnostics.push(ts.createDiagnosticForNode(type, ts.Diagnostics.types_can_only_be_used_in_a_ts_file));
                            return true;
                        }
                        return false;
                    }
                    function checkModifiers(modifiers) {
                        if (modifiers) {
                            for (var _i = 0; _i < modifiers.length; _i++) {
                                var modifier = modifiers[_i];
                                switch (modifier.kind) {
                                    case 108 /* PublicKeyword */:
                                    case 106 /* PrivateKeyword */:
                                    case 107 /* ProtectedKeyword */:
                                    case 115 /* DeclareKeyword */:
                                        diagnostics.push(ts.createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind)));
                                        return true;
                                    // These are all legal modifiers.
                                    case 109 /* StaticKeyword */:
                                    case 78 /* ExportKeyword */:
                                    case 70 /* ConstKeyword */:
                                    case 73 /* DefaultKeyword */:
                                }
                            }
                        }
                        return false;
                    }
                }
                function getCompilerOptionsDiagnostics() {
                    synchronizeHostData();
                    return program.getGlobalDiagnostics();
                }
                /// Completion
                function getCompletionEntryDisplayNameForSymbol(symbol, target, performCharacterChecks) {
                    var displayName = symbol.getName();
                    if (displayName) {
                        // If this is the default export, get the name of the declaration if it exists
                        if (displayName === "default") {
                            var localSymbol = ts.getLocalSymbolForExportDefault(symbol);
                            if (localSymbol && localSymbol.name) {
                                displayName = symbol.valueDeclaration.localSymbol.name;
                            }
                        }
                        var firstCharCode = displayName.charCodeAt(0);
                        // First check of the displayName is not external module; if it is an external module, it is not valid entry
                        if ((symbol.flags & 1536 /* Namespace */) && (firstCharCode === 39 /* singleQuote */ || firstCharCode === 34 /* doubleQuote */)) {
                            // If the symbol is external module, don't show it in the completion list
                            // (i.e declare module "http" { let x; } | // <= request completion here, "http" should not be there)
                            return undefined;
                        }
                    }
                    return getCompletionEntryDisplayName(displayName, target, performCharacterChecks);
                }
                function getCompletionEntryDisplayName(displayName, target, performCharacterChecks) {
                    if (!displayName) {
                        return undefined;
                    }
                    var firstCharCode = displayName.charCodeAt(0);
                    if (displayName.length >= 2 &&
                        firstCharCode === displayName.charCodeAt(displayName.length - 1) &&
                        (firstCharCode === 39 /* singleQuote */ || firstCharCode === 34 /* doubleQuote */)) {
                        // If the user entered name for the symbol was quoted, removing the quotes is not enough, as the name could be an
                        // invalid identifier name. We need to check if whatever was inside the quotes is actually a valid identifier name.
                        displayName = displayName.substring(1, displayName.length - 1);
                    }
                    if (!displayName) {
                        return undefined;
                    }
                    if (performCharacterChecks) {
                        if (!ts.isIdentifierStart(displayName.charCodeAt(0), target)) {
                            return undefined;
                        }
                        for (var i = 1, n = displayName.length; i < n; i++) {
                            if (!ts.isIdentifierPart(displayName.charCodeAt(i), target)) {
                                return undefined;
                            }
                        }
                    }
                    return ts.unescapeIdentifier(displayName);
                }
                function getCompletionData(fileName, position) {
                    var typeChecker = program.getTypeChecker();
                    var syntacticStart = new Date().getTime();
                    var sourceFile = getValidSourceFile(fileName);
                    var start = new Date().getTime();
                    var currentToken = ts.getTokenAtPosition(sourceFile, position);
                    log("getCompletionData: Get current token: " + (new Date().getTime() - start));
                    start = new Date().getTime();
                    // Completion not allowed inside comments, bail out if this is the case
                    var insideComment = isInsideComment(sourceFile, currentToken, position);
                    log("getCompletionData: Is inside comment: " + (new Date().getTime() - start));
                    if (insideComment) {
                        log("Returning an empty list because completion was inside a comment.");
                        return undefined;
                    }
                    start = new Date().getTime();
                    var previousToken = ts.findPrecedingToken(position, sourceFile);
                    log("getCompletionData: Get previous token 1: " + (new Date().getTime() - start));
                    // The decision to provide completion depends on the contextToken, which is determined through the previousToken.
                    // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file
                    var contextToken = previousToken;
                    // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS|
                    // Skip this partial identifier and adjust the contextToken to the token that precedes it.
                    if (contextToken && position <= contextToken.end && ts.isWord(contextToken.kind)) {
                        var start_2 = new Date().getTime();
                        contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile);
                        log("getCompletionData: Get previous token 2: " + (new Date().getTime() - start_2));
                    }
                    // Check if this is a valid completion location
                    if (contextToken && isCompletionListBlocker(contextToken)) {
                        log("Returning an empty list because completion was requested in an invalid position.");
                        return undefined;
                    }
                    // Find the node where completion is requested on, in the case of a completion after 
                    // a dot, it is the member access expression other wise, it is a request for all 
                    // visible symbols in the scope, and the node is the current location.
                    var node = currentToken;
                    var isRightOfDot = false;
                    if (contextToken && contextToken.kind === 20 /* DotToken */ && contextToken.parent.kind === 155 /* PropertyAccessExpression */) {
                        node = contextToken.parent.expression;
                        isRightOfDot = true;
                    }
                    else if (contextToken && contextToken.kind === 20 /* DotToken */ && contextToken.parent.kind === 126 /* QualifiedName */) {
                        node = contextToken.parent.left;
                        isRightOfDot = true;
                    }
                    var location = ts.getTouchingPropertyName(sourceFile, position);
                    var target = program.getCompilerOptions().target;
                    var semanticStart = new Date().getTime();
                    var isMemberCompletion;
                    var isNewIdentifierLocation;
                    var symbols = [];
                    if (isRightOfDot) {
                        getTypeScriptMemberSymbols();
                    }
                    else {
                        // For JavaScript or TypeScript, if we're not after a dot, then just try to get the
                        // global symbols in scope.  These results should be valid for either language as
                        // the set of symbols that can be referenced from this location.
                        if (!tryGetGlobalSymbols()) {
                            return undefined;
                        }
                    }
                    log("getCompletionData: Semantic work: " + (new Date().getTime() - semanticStart));
                    return { symbols: symbols, isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, location: location, isRightOfDot: isRightOfDot };
                    function getTypeScriptMemberSymbols() {
                        // Right of dot member completion list
                        isMemberCompletion = true;
                        isNewIdentifierLocation = false;
                        if (node.kind === 65 /* Identifier */ || node.kind === 126 /* QualifiedName */ || node.kind === 155 /* PropertyAccessExpression */) {
                            var symbol = typeChecker.getSymbolAtLocation(node);
                            // This is an alias, follow what it aliases
                            if (symbol && symbol.flags & 8388608 /* Alias */) {
                                symbol = typeChecker.getAliasedSymbol(symbol);
                            }
                            if (symbol && symbol.flags & 1952 /* HasExports */) {
                                // Extract module or enum members
                                var exportedSymbols = typeChecker.getExportsOfModule(symbol);
                                ts.forEach(exportedSymbols, function (symbol) {
                                    if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) {
                                        symbols.push(symbol);
                                    }
                                });
                            }
                        }
                        var type = typeChecker.getTypeAtLocation(node);
                        if (type) {
                            // Filter private properties
                            ts.forEach(type.getApparentProperties(), function (symbol) {
                                if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) {
                                    symbols.push(symbol);
                                }
                            });
                        }
                    }
                    function tryGetGlobalSymbols() {
                        var containingObjectLiteral = getContainingObjectLiteralApplicableForCompletion(contextToken);
                        if (containingObjectLiteral) {
                            // Object literal expression, look up possible property names from contextual type
                            isMemberCompletion = true;
                            isNewIdentifierLocation = true;
                            var contextualType = typeChecker.getContextualType(containingObjectLiteral);
                            if (!contextualType) {
                                return false;
                            }
                            var contextualTypeMembers = typeChecker.getPropertiesOfType(contextualType);
                            if (contextualTypeMembers && contextualTypeMembers.length > 0) {
                                // Add filtered items to the completion list
                                symbols = filterContextualMembersList(contextualTypeMembers, containingObjectLiteral.properties);
                            }
                        }
                        else if (ts.getAncestor(contextToken, 210 /* ImportClause */)) {
                            // cursor is in import clause
                            // try to show exported member for imported module
                            isMemberCompletion = true;
                            isNewIdentifierLocation = true;
                            if (showCompletionsInImportsClause(contextToken)) {
                                var importDeclaration = ts.getAncestor(contextToken, 209 /* ImportDeclaration */);
                                ts.Debug.assert(importDeclaration !== undefined);
                                var exports;
                                if (importDeclaration.moduleSpecifier) {
                                    var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importDeclaration.moduleSpecifier);
                                    if (moduleSpecifierSymbol) {
                                        exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol);
                                    }
                                }
                                //let exports = typeInfoResolver.getExportsOfImportDeclaration(importDeclaration);
                                symbols = exports ? filterModuleExports(exports, importDeclaration) : emptyArray;
                            }
                        }
                        else {
                            // Get all entities in the current scope.
                            isMemberCompletion = false;
                            isNewIdentifierLocation = isNewIdentifierDefinitionLocation(contextToken);
                            if (previousToken !== contextToken) {
                                ts.Debug.assert(!!previousToken, "Expected 'contextToken' to be defined when different from 'previousToken'.");
                            }
                            // We need to find the node that will give us an appropriate scope to begin
                            // aggregating completion candidates. This is achieved in 'getScopeNode'
                            // by finding the first node that encompasses a position, accounting for whether a node
                            // is "complete" to decide whether a position belongs to the node.
                            // 
                            // However, at the end of an identifier, we are interested in the scope of the identifier
                            // itself, but fall outside of the identifier. For instance:
                            // 
                            //      xyz => x$
                            //
                            // the cursor is outside of both the 'x' and the arrow function 'xyz => x',
                            // so 'xyz' is not returned in our results.
                            //
                            // We define 'adjustedPosition' so that we may appropriately account for
                            // being at the end of an identifier. The intention is that if requesting completion
                            // at the end of an identifier, it should be effectively equivalent to requesting completion
                            // anywhere inside/at the beginning of the identifier. So in the previous case, the
                            // 'adjustedPosition' will work as if requesting completion in the following:
                            //
                            //      xyz => $x
                            //
                            // If previousToken !== contextToken, then
                            //   - 'contextToken' was adjusted to the token prior to 'previousToken'
                            //      because we were at the end of an identifier.
                            //   - 'previousToken' is defined.
                            var adjustedPosition = previousToken !== contextToken ?
                                previousToken.getStart() :
                                position;
                            var scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile;
                            /// TODO filter meaning based on the current context
                            var symbolMeanings = 793056 /* Type */ | 107455 /* Value */ | 1536 /* Namespace */ | 8388608 /* Alias */;
                            symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings);
                        }
                        return true;
                    }
                    /**
                     * Finds the first node that "embraces" the position, so that one may
                     * accurately aggregate locals from the closest containing scope.
                     */
                    function getScopeNode(initialToken, position, sourceFile) {
                        var scope = initialToken;
                        while (scope && !ts.positionBelongsToNode(scope, position, sourceFile)) {
                            scope = scope.parent;
                        }
                        return scope;
                    }
                    function isCompletionListBlocker(previousToken) {
                        var start = new Date().getTime();
                        var result = isInStringOrRegularExpressionOrTemplateLiteral(previousToken) ||
                            isIdentifierDefinitionLocation(previousToken) ||
                            isRightOfIllegalDot(previousToken);
                        log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start));
                        return result;
                    }
                    function showCompletionsInImportsClause(node) {
                        if (node) {
                            // import {| 
                            // import {a,|
                            if (node.kind === 14 /* OpenBraceToken */ || node.kind === 23 /* CommaToken */) {
                                return node.parent.kind === 212 /* NamedImports */;
                            }
                        }
                        return false;
                    }
                    function isNewIdentifierDefinitionLocation(previousToken) {
                        if (previousToken) {
                            var containingNodeKind = previousToken.parent.kind;
                            switch (previousToken.kind) {
                                case 23 /* CommaToken */:
                                    return containingNodeKind === 157 /* CallExpression */ // func( a, |
                                        || containingNodeKind === 135 /* Constructor */ // constructor( a, |   public, protected, private keywords are allowed here, so show completion
                                        || containingNodeKind === 158 /* NewExpression */ // new C(a, |
                                        || containingNodeKind === 153 /* ArrayLiteralExpression */ // [a, |
                                        || containingNodeKind === 169 /* BinaryExpression */; // let x = (a, |
                                case 16 /* OpenParenToken */:
                                    return containingNodeKind === 157 /* CallExpression */ // func( |
                                        || containingNodeKind === 135 /* Constructor */ // constructor( |
                                        || containingNodeKind === 158 /* NewExpression */ // new C(a|
                                        || containingNodeKind === 161 /* ParenthesizedExpression */; // let x = (a|
                                case 18 /* OpenBracketToken */:
                                    return containingNodeKind === 153 /* ArrayLiteralExpression */; // [ |
                                case 117 /* ModuleKeyword */:
                                    return true;
                                case 20 /* DotToken */:
                                    return containingNodeKind === 205 /* ModuleDeclaration */; // module A.|
                                case 14 /* OpenBraceToken */:
                                    return containingNodeKind === 201 /* ClassDeclaration */; // class A{ |
                                case 53 /* EqualsToken */:
                                    return containingNodeKind === 198 /* VariableDeclaration */ // let x = a|
                                        || containingNodeKind === 169 /* BinaryExpression */; // x = a|
                                case 11 /* TemplateHead */:
                                    return containingNodeKind === 171 /* TemplateExpression */; // `aa ${|
                                case 12 /* TemplateMiddle */:
                                    return containingNodeKind === 176 /* TemplateSpan */; // `aa ${10} dd ${|
                                case 108 /* PublicKeyword */:
                                case 106 /* PrivateKeyword */:
                                case 107 /* ProtectedKeyword */:
                                    return containingNodeKind === 132 /* PropertyDeclaration */; // class A{ public |
                            }
                            // Previous token may have been a keyword that was converted to an identifier.
                            switch (previousToken.getText()) {
                                case "public":
                                case "protected":
                                case "private":
                                    return true;
                            }
                        }
                        return false;
                    }
                    function isInStringOrRegularExpressionOrTemplateLiteral(previousToken) {
                        if (previousToken.kind === 8 /* StringLiteral */
                            || previousToken.kind === 9 /* RegularExpressionLiteral */
                            || ts.isTemplateLiteralKind(previousToken.kind)) {
                            // The position has to be either: 1. entirely within the token text, or 
                            // 2. at the end position of an unterminated token.
                            var start_3 = previousToken.getStart();
                            var end = previousToken.getEnd();
                            if (start_3 < position && position < end) {
                                return true;
                            }
                            else if (position === end) {
                                return !!previousToken.isUnterminated;
                            }
                        }
                        return false;
                    }
                    function getContainingObjectLiteralApplicableForCompletion(previousToken) {
                        // The locations in an object literal expression that are applicable for completion are property name definition locations.
                        if (previousToken) {
                            var parent_8 = previousToken.parent;
                            switch (previousToken.kind) {
                                case 14 /* OpenBraceToken */: // let x = { |
                                case 23 /* CommaToken */:
                                    if (parent_8 && parent_8.kind === 154 /* ObjectLiteralExpression */) {
                                        return parent_8;
                                    }
                                    break;
                            }
                        }
                        return undefined;
                    }
                    function isFunction(kind) {
                        switch (kind) {
                            case 162 /* FunctionExpression */:
                            case 163 /* ArrowFunction */:
                            case 200 /* FunctionDeclaration */:
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                            case 138 /* CallSignature */:
                            case 139 /* ConstructSignature */:
                            case 140 /* IndexSignature */:
                                return true;
                        }
                        return false;
                    }
                    function isIdentifierDefinitionLocation(previousToken) {
                        if (previousToken) {
                            var containingNodeKind = previousToken.parent.kind;
                            switch (previousToken.kind) {
                                case 23 /* CommaToken */:
                                    return containingNodeKind === 198 /* VariableDeclaration */ ||
                                        containingNodeKind === 199 /* VariableDeclarationList */ ||
                                        containingNodeKind === 180 /* VariableStatement */ ||
                                        containingNodeKind === 204 /* EnumDeclaration */ ||
                                        isFunction(containingNodeKind) ||
                                        containingNodeKind === 201 /* ClassDeclaration */ ||
                                        containingNodeKind === 200 /* FunctionDeclaration */ ||
                                        containingNodeKind === 202 /* InterfaceDeclaration */ ||
                                        containingNodeKind === 151 /* ArrayBindingPattern */ ||
                                        containingNodeKind === 150 /* ObjectBindingPattern */; // function func({ x, y|
                                case 20 /* DotToken */:
                                    return containingNodeKind === 151 /* ArrayBindingPattern */; // var [.|
                                case 18 /* OpenBracketToken */:
                                    return containingNodeKind === 151 /* ArrayBindingPattern */; //  var [x|
                                case 16 /* OpenParenToken */:
                                    return containingNodeKind === 223 /* CatchClause */ ||
                                        isFunction(containingNodeKind);
                                case 14 /* OpenBraceToken */:
                                    return containingNodeKind === 204 /* EnumDeclaration */ ||
                                        containingNodeKind === 202 /* InterfaceDeclaration */ ||
                                        containingNodeKind === 145 /* TypeLiteral */ ||
                                        containingNodeKind === 150 /* ObjectBindingPattern */; // function func({ x|
                                case 22 /* SemicolonToken */:
                                    return containingNodeKind === 131 /* PropertySignature */ &&
                                        previousToken.parent && previousToken.parent.parent &&
                                        (previousToken.parent.parent.kind === 202 /* InterfaceDeclaration */ ||
                                            previousToken.parent.parent.kind === 145 /* TypeLiteral */); //  let x : { a; |
                                case 24 /* LessThanToken */:
                                    return containingNodeKind === 201 /* ClassDeclaration */ ||
                                        containingNodeKind === 200 /* FunctionDeclaration */ ||
                                        containingNodeKind === 202 /* InterfaceDeclaration */ ||
                                        isFunction(containingNodeKind);
                                case 109 /* StaticKeyword */:
                                    return containingNodeKind === 132 /* PropertyDeclaration */;
                                case 21 /* DotDotDotToken */:
                                    return containingNodeKind === 129 /* Parameter */ ||
                                        containingNodeKind === 135 /* Constructor */ ||
                                        (previousToken.parent && previousToken.parent.parent &&
                                            previousToken.parent.parent.kind === 151 /* ArrayBindingPattern */); // var [ ...z|
                                case 108 /* PublicKeyword */:
                                case 106 /* PrivateKeyword */:
                                case 107 /* ProtectedKeyword */:
                                    return containingNodeKind === 129 /* Parameter */;
                                case 69 /* ClassKeyword */:
                                case 77 /* EnumKeyword */:
                                case 103 /* InterfaceKeyword */:
                                case 83 /* FunctionKeyword */:
                                case 98 /* VarKeyword */:
                                case 116 /* GetKeyword */:
                                case 120 /* SetKeyword */:
                                case 85 /* ImportKeyword */:
                                case 104 /* LetKeyword */:
                                case 70 /* ConstKeyword */:
                                case 110 /* YieldKeyword */:
                                    return true;
                            }
                            // Previous token may have been a keyword that was converted to an identifier.
                            switch (previousToken.getText()) {
                                case "class":
                                case "interface":
                                case "enum":
                                case "function":
                                case "var":
                                case "static":
                                case "let":
                                case "const":
                                case "yield":
                                    return true;
                            }
                        }
                        return false;
                    }
                    function isRightOfIllegalDot(previousToken) {
                        if (previousToken && previousToken.kind === 7 /* NumericLiteral */) {
                            var text = previousToken.getFullText();
                            return text.charAt(text.length - 1) === ".";
                        }
                        return false;
                    }
                    function filterModuleExports(exports, importDeclaration) {
                        var exisingImports = {};
                        if (!importDeclaration.importClause) {
                            return exports;
                        }
                        if (importDeclaration.importClause.namedBindings &&
                            importDeclaration.importClause.namedBindings.kind === 212 /* NamedImports */) {
                            ts.forEach(importDeclaration.importClause.namedBindings.elements, function (el) {
                                var name = el.propertyName || el.name;
                                exisingImports[name.text] = true;
                            });
                        }
                        if (ts.isEmpty(exisingImports)) {
                            return exports;
                        }
                        return ts.filter(exports, function (e) { return !ts.lookUp(exisingImports, e.name); });
                    }
                    function filterContextualMembersList(contextualMemberSymbols, existingMembers) {
                        if (!existingMembers || existingMembers.length === 0) {
                            return contextualMemberSymbols;
                        }
                        var existingMemberNames = {};
                        ts.forEach(existingMembers, function (m) {
                            if (m.kind !== 224 /* PropertyAssignment */ && m.kind !== 225 /* ShorthandPropertyAssignment */) {
                                // Ignore omitted expressions for missing members in the object literal
                                return;
                            }
                            if (m.getStart() <= position && position <= m.getEnd()) {
                                // If this is the current item we are editing right now, do not filter it out
                                return;
                            }
                            // TODO(jfreeman): Account for computed property name
                            existingMemberNames[m.name.text] = true;
                        });
                        var filteredMembers = [];
                        ts.forEach(contextualMemberSymbols, function (s) {
                            if (!existingMemberNames[s.name]) {
                                filteredMembers.push(s);
                            }
                        });
                        return filteredMembers;
                    }
                }
                function getCompletionsAtPosition(fileName, position) {
                    synchronizeHostData();
                    var completionData = getCompletionData(fileName, position);
                    if (!completionData) {
                        return undefined;
                    }
                    var symbols = completionData.symbols, isMemberCompletion = completionData.isMemberCompletion, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, isRightOfDot = completionData.isRightOfDot;
                    var entries;
                    if (isRightOfDot && ts.isJavaScript(fileName)) {
                        entries = getCompletionEntriesFromSymbols(symbols);
                        ts.addRange(entries, getJavaScriptCompletionEntries());
                    }
                    else {
                        if (!symbols || symbols.length === 0) {
                            return undefined;
                        }
                        entries = getCompletionEntriesFromSymbols(symbols);
                    }
                    // Add keywords if this is not a member completion list
                    if (!isMemberCompletion) {
                        ts.addRange(entries, keywordCompletions);
                    }
                    return { isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, entries: entries };
                    function getJavaScriptCompletionEntries() {
                        var entries = [];
                        var allNames = {};
                        var target = program.getCompilerOptions().target;
                        for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) {
                            var sourceFile = _a[_i];
                            var nameTable = getNameTable(sourceFile);
                            for (var name_24 in nameTable) {
                                if (!allNames[name_24]) {
                                    allNames[name_24] = name_24;
                                    var displayName = getCompletionEntryDisplayName(name_24, target, true);
                                    if (displayName) {
                                        var entry = {
                                            name: displayName,
                                            kind: ScriptElementKind.warning,
                                            kindModifiers: "",
                                            sortText: "1"
                                        };
                                        entries.push(entry);
                                    }
                                }
                            }
                        }
                        return entries;
                    }
                    function createCompletionEntry(symbol, location) {
                        // Try to get a valid display name for this symbol, if we could not find one, then ignore it. 
                        // We would like to only show things that can be added after a dot, so for instance numeric properties can
                        // not be accessed with a dot (a.1 <- invalid)
                        var displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, true);
                        if (!displayName) {
                            return undefined;
                        }
                        // TODO(drosen): Right now we just permit *all* semantic meanings when calling 
                        // 'getSymbolKind' which is permissible given that it is backwards compatible; but 
                        // really we should consider passing the meaning for the node so that we don't report
                        // that a suggestion for a value is an interface.  We COULD also just do what 
                        // 'getSymbolModifiers' does, which is to use the first declaration.
                        // Use a 'sortText' of 0' so that all symbol completion entries come before any other
                        // entries (like JavaScript identifier entries).
                        return {
                            name: displayName,
                            kind: getSymbolKind(symbol, location),
                            kindModifiers: getSymbolModifiers(symbol),
                            sortText: "0"
                        };
                    }
                    function getCompletionEntriesFromSymbols(symbols) {
                        var start = new Date().getTime();
                        var entries = [];
                        if (symbols) {
                            var nameToSymbol = {};
                            for (var _i = 0; _i < symbols.length; _i++) {
                                var symbol = symbols[_i];
                                var entry = createCompletionEntry(symbol, location);
                                if (entry) {
                                    var id = ts.escapeIdentifier(entry.name);
                                    if (!ts.lookUp(nameToSymbol, id)) {
                                        entries.push(entry);
                                        nameToSymbol[id] = symbol;
                                    }
                                }
                            }
                        }
                        log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start));
                        return entries;
                    }
                }
                function getCompletionEntryDetails(fileName, position, entryName) {
                    synchronizeHostData();
                    // Compute all the completion symbols again.
                    var completionData = getCompletionData(fileName, position);
                    if (completionData) {
                        var symbols = completionData.symbols, location_2 = completionData.location;
                        // Find the symbol with the matching entry name.
                        var target = program.getCompilerOptions().target;
                        // We don't need to perform character checks here because we're only comparing the 
                        // name against 'entryName' (which is known to be good), not building a new 
                        // completion entry.
                        var symbol = ts.forEach(symbols, function (s) { return getCompletionEntryDisplayNameForSymbol(s, target, false) === entryName ? s : undefined; });
                        if (symbol) {
                            var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location_2, location_2, 7 /* All */);
                            return {
                                name: entryName,
                                kind: displayPartsDocumentationsAndSymbolKind.symbolKind,
                                kindModifiers: getSymbolModifiers(symbol),
                                displayParts: displayPartsDocumentationsAndSymbolKind.displayParts,
                                documentation: displayPartsDocumentationsAndSymbolKind.documentation
                            };
                        }
                    }
                    // Didn't find a symbol with this name.  See if we can find a keyword instead.
                    var keywordCompletion = ts.forEach(keywordCompletions, function (c) { return c.name === entryName; });
                    if (keywordCompletion) {
                        return {
                            name: entryName,
                            kind: ScriptElementKind.keyword,
                            kindModifiers: ScriptElementKindModifier.none,
                            displayParts: [ts.displayPart(entryName, SymbolDisplayPartKind.keyword)],
                            documentation: undefined
                        };
                    }
                    return undefined;
                }
                // TODO(drosen): use contextual SemanticMeaning.
                function getSymbolKind(symbol, location) {
                    var flags = symbol.getFlags();
                    if (flags & 32 /* Class */)
                        return ScriptElementKind.classElement;
                    if (flags & 384 /* Enum */)
                        return ScriptElementKind.enumElement;
                    if (flags & 524288 /* TypeAlias */)
                        return ScriptElementKind.typeElement;
                    if (flags & 64 /* Interface */)
                        return ScriptElementKind.interfaceElement;
                    if (flags & 262144 /* TypeParameter */)
                        return ScriptElementKind.typeParameterElement;
                    var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location);
                    if (result === ScriptElementKind.unknown) {
                        if (flags & 262144 /* TypeParameter */)
                            return ScriptElementKind.typeParameterElement;
                        if (flags & 8 /* EnumMember */)
                            return ScriptElementKind.variableElement;
                        if (flags & 8388608 /* Alias */)
                            return ScriptElementKind.alias;
                        if (flags & 1536 /* Module */)
                            return ScriptElementKind.moduleElement;
                    }
                    return result;
                }
                function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location) {
                    var typeChecker = program.getTypeChecker();
                    if (typeChecker.isUndefinedSymbol(symbol)) {
                        return ScriptElementKind.variableElement;
                    }
                    if (typeChecker.isArgumentsSymbol(symbol)) {
                        return ScriptElementKind.localVariableElement;
                    }
                    if (flags & 3 /* Variable */) {
                        if (ts.isFirstDeclarationOfSymbolParameter(symbol)) {
                            return ScriptElementKind.parameterElement;
                        }
                        else if (symbol.valueDeclaration && ts.isConst(symbol.valueDeclaration)) {
                            return ScriptElementKind.constElement;
                        }
                        else if (ts.forEach(symbol.declarations, ts.isLet)) {
                            return ScriptElementKind.letElement;
                        }
                        return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localVariableElement : ScriptElementKind.variableElement;
                    }
                    if (flags & 16 /* Function */)
                        return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localFunctionElement : ScriptElementKind.functionElement;
                    if (flags & 32768 /* GetAccessor */)
                        return ScriptElementKind.memberGetAccessorElement;
                    if (flags & 65536 /* SetAccessor */)
                        return ScriptElementKind.memberSetAccessorElement;
                    if (flags & 8192 /* Method */)
                        return ScriptElementKind.memberFunctionElement;
                    if (flags & 16384 /* Constructor */)
                        return ScriptElementKind.constructorImplementationElement;
                    if (flags & 4 /* Property */) {
                        if (flags & 268435456 /* UnionProperty */) {
                            // If union property is result of union of non method (property/accessors/variables), it is labeled as property
                            var unionPropertyKind = ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) {
                                var rootSymbolFlags = rootSymbol.getFlags();
                                if (rootSymbolFlags & (98308 /* PropertyOrAccessor */ | 3 /* Variable */)) {
                                    return ScriptElementKind.memberVariableElement;
                                }
                                ts.Debug.assert(!!(rootSymbolFlags & 8192 /* Method */));
                            });
                            if (!unionPropertyKind) {
                                // If this was union of all methods, 
                                //make sure it has call signatures before we can label it as method
                                var typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location);
                                if (typeOfUnionProperty.getCallSignatures().length) {
                                    return ScriptElementKind.memberFunctionElement;
                                }
                                return ScriptElementKind.memberVariableElement;
                            }
                            return unionPropertyKind;
                        }
                        return ScriptElementKind.memberVariableElement;
                    }
                    return ScriptElementKind.unknown;
                }
                function getTypeKind(type) {
                    var flags = type.getFlags();
                    if (flags & 128 /* Enum */)
                        return ScriptElementKind.enumElement;
                    if (flags & 1024 /* Class */)
                        return ScriptElementKind.classElement;
                    if (flags & 2048 /* Interface */)
                        return ScriptElementKind.interfaceElement;
                    if (flags & 512 /* TypeParameter */)
                        return ScriptElementKind.typeParameterElement;
                    if (flags & 1048703 /* Intrinsic */)
                        return ScriptElementKind.primitiveType;
                    if (flags & 256 /* StringLiteral */)
                        return ScriptElementKind.primitiveType;
                    return ScriptElementKind.unknown;
                }
                function getSymbolModifiers(symbol) {
                    return symbol && symbol.declarations && symbol.declarations.length > 0
                        ? ts.getNodeModifiers(symbol.declarations[0])
                        : ScriptElementKindModifier.none;
                }
                // TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location
                function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, enclosingDeclaration, location, semanticMeaning) {
                    if (semanticMeaning === void 0) { semanticMeaning = getMeaningFromLocation(location); }
                    var typeChecker = program.getTypeChecker();
                    var displayParts = [];
                    var documentation;
                    var symbolFlags = symbol.flags;
                    var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location);
                    var hasAddedSymbolInfo;
                    var type;
                    // Class at constructor site need to be shown as constructor apart from property,method, vars
                    if (symbolKind !== ScriptElementKind.unknown || symbolFlags & 32 /* Class */ || symbolFlags & 8388608 /* Alias */) {
                        // If it is accessor they are allowed only if location is at name of the accessor
                        if (symbolKind === ScriptElementKind.memberGetAccessorElement || symbolKind === ScriptElementKind.memberSetAccessorElement) {
                            symbolKind = ScriptElementKind.memberVariableElement;
                        }
                        var signature;
                        type = typeChecker.getTypeOfSymbolAtLocation(symbol, location);
                        if (type) {
                            if (location.parent && location.parent.kind === 155 /* PropertyAccessExpression */) {
                                var right = location.parent.name;
                                // Either the location is on the right of a property access, or on the left and the right is missing
                                if (right === location || (right && right.getFullWidth() === 0)) {
                                    location = location.parent;
                                }
                            }
                            // try get the call/construct signature from the type if it matches
                            var callExpression;
                            if (location.kind === 157 /* CallExpression */ || location.kind === 158 /* NewExpression */) {
                                callExpression = location;
                            }
                            else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) {
                                callExpression = location.parent;
                            }
                            if (callExpression) {
                                var candidateSignatures = [];
                                signature = typeChecker.getResolvedSignature(callExpression, candidateSignatures);
                                if (!signature && candidateSignatures.length) {
                                    // Use the first candidate:
                                    signature = candidateSignatures[0];
                                }
                                var useConstructSignatures = callExpression.kind === 158 /* NewExpression */ || callExpression.expression.kind === 91 /* SuperKeyword */;
                                var allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures();
                                if (!ts.contains(allSignatures, signature.target || signature)) {
                                    // Get the first signature if there 
                                    signature = allSignatures.length ? allSignatures[0] : undefined;
                                }
                                if (signature) {
                                    if (useConstructSignatures && (symbolFlags & 32 /* Class */)) {
                                        // Constructor
                                        symbolKind = ScriptElementKind.constructorImplementationElement;
                                        addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
                                    }
                                    else if (symbolFlags & 8388608 /* Alias */) {
                                        symbolKind = ScriptElementKind.alias;
                                        pushTypePart(symbolKind);
                                        displayParts.push(ts.spacePart());
                                        if (useConstructSignatures) {
                                            displayParts.push(ts.keywordPart(88 /* NewKeyword */));
                                            displayParts.push(ts.spacePart());
                                        }
                                        addFullSymbolName(symbol);
                                    }
                                    else {
                                        addPrefixForAnyFunctionOrVar(symbol, symbolKind);
                                    }
                                    switch (symbolKind) {
                                        case ScriptElementKind.memberVariableElement:
                                        case ScriptElementKind.variableElement:
                                        case ScriptElementKind.constElement:
                                        case ScriptElementKind.letElement:
                                        case ScriptElementKind.parameterElement:
                                        case ScriptElementKind.localVariableElement:
                                            // If it is call or construct signature of lambda's write type name
                                            displayParts.push(ts.punctuationPart(51 /* ColonToken */));
                                            displayParts.push(ts.spacePart());
                                            if (useConstructSignatures) {
                                                displayParts.push(ts.keywordPart(88 /* NewKeyword */));
                                                displayParts.push(ts.spacePart());
                                            }
                                            if (!(type.flags & 32768 /* Anonymous */)) {
                                                displayParts.push.apply(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, undefined, 1 /* WriteTypeParametersOrArguments */));
                                            }
                                            addSignatureDisplayParts(signature, allSignatures, 8 /* WriteArrowStyleSignature */);
                                            break;
                                        default:
                                            // Just signature
                                            addSignatureDisplayParts(signature, allSignatures);
                                    }
                                    hasAddedSymbolInfo = true;
                                }
                            }
                            else if ((isNameOfFunctionDeclaration(location) && !(symbol.flags & 98304 /* Accessor */)) ||
                                (location.kind === 114 /* ConstructorKeyword */ && location.parent.kind === 135 /* Constructor */)) {
                                // get the signature from the declaration and write it
                                var functionDeclaration = location.parent;
                                var allSignatures = functionDeclaration.kind === 135 /* Constructor */ ? type.getConstructSignatures() : type.getCallSignatures();
                                if (!typeChecker.isImplementationOfOverload(functionDeclaration)) {
                                    signature = typeChecker.getSignatureFromDeclaration(functionDeclaration);
                                }
                                else {
                                    signature = allSignatures[0];
                                }
                                if (functionDeclaration.kind === 135 /* Constructor */) {
                                    // show (constructor) Type(...) signature
                                    symbolKind = ScriptElementKind.constructorImplementationElement;
                                    addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
                                }
                                else {
                                    // (function/method) symbol(..signature)
                                    addPrefixForAnyFunctionOrVar(functionDeclaration.kind === 138 /* CallSignature */ &&
                                        !(type.symbol.flags & 2048 /* TypeLiteral */ || type.symbol.flags & 4096 /* ObjectLiteral */) ? type.symbol : symbol, symbolKind);
                                }
                                addSignatureDisplayParts(signature, allSignatures);
                                hasAddedSymbolInfo = true;
                            }
                        }
                    }
                    if (symbolFlags & 32 /* Class */ && !hasAddedSymbolInfo) {
                        displayParts.push(ts.keywordPart(69 /* ClassKeyword */));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                        writeTypeParametersOfSymbol(symbol, sourceFile);
                    }
                    if ((symbolFlags & 64 /* Interface */) && (semanticMeaning & 2 /* Type */)) {
                        addNewLineIfDisplayPartsExist();
                        displayParts.push(ts.keywordPart(103 /* InterfaceKeyword */));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                        writeTypeParametersOfSymbol(symbol, sourceFile);
                    }
                    if (symbolFlags & 524288 /* TypeAlias */) {
                        addNewLineIfDisplayPartsExist();
                        displayParts.push(ts.keywordPart(123 /* TypeKeyword */));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                        displayParts.push(ts.spacePart());
                        displayParts.push(ts.operatorPart(53 /* EqualsToken */));
                        displayParts.push(ts.spacePart());
                        displayParts.push.apply(displayParts, ts.typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration));
                    }
                    if (symbolFlags & 384 /* Enum */) {
                        addNewLineIfDisplayPartsExist();
                        if (ts.forEach(symbol.declarations, ts.isConstEnumDeclaration)) {
                            displayParts.push(ts.keywordPart(70 /* ConstKeyword */));
                            displayParts.push(ts.spacePart());
                        }
                        displayParts.push(ts.keywordPart(77 /* EnumKeyword */));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                    }
                    if (symbolFlags & 1536 /* Module */) {
                        addNewLineIfDisplayPartsExist();
                        displayParts.push(ts.keywordPart(117 /* ModuleKeyword */));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                    }
                    if ((symbolFlags & 262144 /* TypeParameter */) && (semanticMeaning & 2 /* Type */)) {
                        addNewLineIfDisplayPartsExist();
                        displayParts.push(ts.punctuationPart(16 /* OpenParenToken */));
                        displayParts.push(ts.textPart("type parameter"));
                        displayParts.push(ts.punctuationPart(17 /* CloseParenToken */));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                        displayParts.push(ts.spacePart());
                        displayParts.push(ts.keywordPart(86 /* InKeyword */));
                        displayParts.push(ts.spacePart());
                        if (symbol.parent) {
                            // Class/Interface type parameter
                            addFullSymbolName(symbol.parent, enclosingDeclaration);
                            writeTypeParametersOfSymbol(symbol.parent, enclosingDeclaration);
                        }
                        else {
                            // Method/function type parameter
                            var signatureDeclaration = ts.getDeclarationOfKind(symbol, 128 /* TypeParameter */).parent;
                            var signature = typeChecker.getSignatureFromDeclaration(signatureDeclaration);
                            if (signatureDeclaration.kind === 139 /* ConstructSignature */) {
                                displayParts.push(ts.keywordPart(88 /* NewKeyword */));
                                displayParts.push(ts.spacePart());
                            }
                            else if (signatureDeclaration.kind !== 138 /* CallSignature */ && signatureDeclaration.name) {
                                addFullSymbolName(signatureDeclaration.symbol);
                            }
                            displayParts.push.apply(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, 32 /* WriteTypeArgumentsOfSignature */));
                        }
                    }
                    if (symbolFlags & 8 /* EnumMember */) {
                        addPrefixForAnyFunctionOrVar(symbol, "enum member");
                        var declaration = symbol.declarations[0];
                        if (declaration.kind === 226 /* EnumMember */) {
                            var constantValue = typeChecker.getConstantValue(declaration);
                            if (constantValue !== undefined) {
                                displayParts.push(ts.spacePart());
                                displayParts.push(ts.operatorPart(53 /* EqualsToken */));
                                displayParts.push(ts.spacePart());
                                displayParts.push(ts.displayPart(constantValue.toString(), SymbolDisplayPartKind.numericLiteral));
                            }
                        }
                    }
                    if (symbolFlags & 8388608 /* Alias */) {
                        addNewLineIfDisplayPartsExist();
                        displayParts.push(ts.keywordPart(85 /* ImportKeyword */));
                        displayParts.push(ts.spacePart());
                        addFullSymbolName(symbol);
                        ts.forEach(symbol.declarations, function (declaration) {
                            if (declaration.kind === 208 /* ImportEqualsDeclaration */) {
                                var importEqualsDeclaration = declaration;
                                if (ts.isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) {
                                    displayParts.push(ts.spacePart());
                                    displayParts.push(ts.operatorPart(53 /* EqualsToken */));
                                    displayParts.push(ts.spacePart());
                                    displayParts.push(ts.keywordPart(118 /* RequireKeyword */));
                                    displayParts.push(ts.punctuationPart(16 /* OpenParenToken */));
                                    displayParts.push(ts.displayPart(ts.getTextOfNode(ts.getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), SymbolDisplayPartKind.stringLiteral));
                                    displayParts.push(ts.punctuationPart(17 /* CloseParenToken */));
                                }
                                else {
                                    var internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference);
                                    if (internalAliasSymbol) {
                                        displayParts.push(ts.spacePart());
                                        displayParts.push(ts.operatorPart(53 /* EqualsToken */));
                                        displayParts.push(ts.spacePart());
                                        addFullSymbolName(internalAliasSymbol, enclosingDeclaration);
                                    }
                                }
                                return true;
                            }
                        });
                    }
                    if (!hasAddedSymbolInfo) {
                        if (symbolKind !== ScriptElementKind.unknown) {
                            if (type) {
                                addPrefixForAnyFunctionOrVar(symbol, symbolKind);
                                // For properties, variables and local vars: show the type
                                if (symbolKind === ScriptElementKind.memberVariableElement ||
                                    symbolFlags & 3 /* Variable */ ||
                                    symbolKind === ScriptElementKind.localVariableElement) {
                                    displayParts.push(ts.punctuationPart(51 /* ColonToken */));
                                    displayParts.push(ts.spacePart());
                                    // If the type is type parameter, format it specially
                                    if (type.symbol && type.symbol.flags & 262144 /* TypeParameter */) {
                                        var typeParameterParts = ts.mapToDisplayParts(function (writer) {
                                            typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(type, writer, enclosingDeclaration);
                                        });
                                        displayParts.push.apply(displayParts, typeParameterParts);
                                    }
                                    else {
                                        displayParts.push.apply(displayParts, ts.typeToDisplayParts(typeChecker, type, enclosingDeclaration));
                                    }
                                }
                                else if (symbolFlags & 16 /* Function */ ||
                                    symbolFlags & 8192 /* Method */ ||
                                    symbolFlags & 16384 /* Constructor */ ||
                                    symbolFlags & 131072 /* Signature */ ||
                                    symbolFlags & 98304 /* Accessor */ ||
                                    symbolKind === ScriptElementKind.memberFunctionElement) {
                                    var allSignatures = type.getCallSignatures();
                                    addSignatureDisplayParts(allSignatures[0], allSignatures);
                                }
                            }
                        }
                        else {
                            symbolKind = getSymbolKind(symbol, location);
                        }
                    }
                    if (!documentation) {
                        documentation = symbol.getDocumentationComment();
                    }
                    return { displayParts: displayParts, documentation: documentation, symbolKind: symbolKind };
                    function addNewLineIfDisplayPartsExist() {
                        if (displayParts.length) {
                            displayParts.push(ts.lineBreakPart());
                        }
                    }
                    function addFullSymbolName(symbol, enclosingDeclaration) {
                        var fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, undefined, 1 /* WriteTypeParametersOrArguments */ | 2 /* UseOnlyExternalAliasing */);
                        displayParts.push.apply(displayParts, fullSymbolDisplayParts);
                    }
                    function addPrefixForAnyFunctionOrVar(symbol, symbolKind) {
                        addNewLineIfDisplayPartsExist();
                        if (symbolKind) {
                            pushTypePart(symbolKind);
                            displayParts.push(ts.spacePart());
                            addFullSymbolName(symbol);
                        }
                    }
                    function pushTypePart(symbolKind) {
                        switch (symbolKind) {
                            case ScriptElementKind.variableElement:
                            case ScriptElementKind.functionElement:
                            case ScriptElementKind.letElement:
                            case ScriptElementKind.constElement:
                            case ScriptElementKind.constructorImplementationElement:
                                displayParts.push(ts.textOrKeywordPart(symbolKind));
                                return;
                            default:
                                displayParts.push(ts.punctuationPart(16 /* OpenParenToken */));
                                displayParts.push(ts.textOrKeywordPart(symbolKind));
                                displayParts.push(ts.punctuationPart(17 /* CloseParenToken */));
                                return;
                        }
                    }
                    function addSignatureDisplayParts(signature, allSignatures, flags) {
                        displayParts.push.apply(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | 32 /* WriteTypeArgumentsOfSignature */));
                        if (allSignatures.length > 1) {
                            displayParts.push(ts.spacePart());
                            displayParts.push(ts.punctuationPart(16 /* OpenParenToken */));
                            displayParts.push(ts.operatorPart(33 /* PlusToken */));
                            displayParts.push(ts.displayPart((allSignatures.length - 1).toString(), SymbolDisplayPartKind.numericLiteral));
                            displayParts.push(ts.spacePart());
                            displayParts.push(ts.textPart(allSignatures.length === 2 ? "overload" : "overloads"));
                            displayParts.push(ts.punctuationPart(17 /* CloseParenToken */));
                        }
                        documentation = signature.getDocumentationComment();
                    }
                    function writeTypeParametersOfSymbol(symbol, enclosingDeclaration) {
                        var typeParameterParts = ts.mapToDisplayParts(function (writer) {
                            typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration);
                        });
                        displayParts.push.apply(displayParts, typeParameterParts);
                    }
                }
                function getQuickInfoAtPosition(fileName, position) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    var node = ts.getTouchingPropertyName(sourceFile, position);
                    if (!node) {
                        return undefined;
                    }
                    if (isLabelName(node)) {
                        return undefined;
                    }
                    var typeChecker = program.getTypeChecker();
                    var symbol = typeChecker.getSymbolAtLocation(node);
                    if (!symbol) {
                        // Try getting just type at this position and show
                        switch (node.kind) {
                            case 65 /* Identifier */:
                            case 155 /* PropertyAccessExpression */:
                            case 126 /* QualifiedName */:
                            case 93 /* ThisKeyword */:
                            case 91 /* SuperKeyword */:
                                // For the identifiers/this/super etc get the type at position
                                var type = typeChecker.getTypeAtLocation(node);
                                if (type) {
                                    return {
                                        kind: ScriptElementKind.unknown,
                                        kindModifiers: ScriptElementKindModifier.none,
                                        textSpan: ts.createTextSpan(node.getStart(), node.getWidth()),
                                        displayParts: ts.typeToDisplayParts(typeChecker, type, getContainerNode(node)),
                                        documentation: type.symbol ? type.symbol.getDocumentationComment() : undefined
                                    };
                                }
                        }
                        return undefined;
                    }
                    var displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node);
                    return {
                        kind: displayPartsDocumentationsAndKind.symbolKind,
                        kindModifiers: getSymbolModifiers(symbol),
                        textSpan: ts.createTextSpan(node.getStart(), node.getWidth()),
                        displayParts: displayPartsDocumentationsAndKind.displayParts,
                        documentation: displayPartsDocumentationsAndKind.documentation
                    };
                }
                function createDefinitionInfo(node, symbolKind, symbolName, containerName) {
                    return {
                        fileName: node.getSourceFile().fileName,
                        textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()),
                        kind: symbolKind,
                        name: symbolName,
                        containerKind: undefined,
                        containerName: containerName
                    };
                }
                /// Goto definition
                function getDefinitionAtPosition(fileName, position) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    var node = ts.getTouchingPropertyName(sourceFile, position);
                    if (!node) {
                        return undefined;
                    }
                    // Labels
                    if (isJumpStatementTarget(node)) {
                        var labelName = node.text;
                        var label = getTargetLabel(node.parent, node.text);
                        return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, undefined)] : undefined;
                    }
                    /// Triple slash reference comments
                    var comment = ts.forEach(sourceFile.referencedFiles, function (r) { return (r.pos <= position && position < r.end) ? r : undefined; });
                    if (comment) {
                        var referenceFile = ts.tryResolveScriptReference(program, sourceFile, comment);
                        if (referenceFile) {
                            return [{
                                    fileName: referenceFile.fileName,
                                    textSpan: ts.createTextSpanFromBounds(0, 0),
                                    kind: ScriptElementKind.scriptElement,
                                    name: comment.fileName,
                                    containerName: undefined,
                                    containerKind: undefined
                                }];
                        }
                        return undefined;
                    }
                    var typeChecker = program.getTypeChecker();
                    var symbol = typeChecker.getSymbolAtLocation(node);
                    // Could not find a symbol e.g. node is string or number keyword,
                    // or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol
                    if (!symbol) {
                        return undefined;
                    }
                    // If this is an alias, and the request came at the declaration location
                    // get the aliased symbol instead. This allows for goto def on an import e.g.
                    //   import {A, B} from "mod";
                    // to jump to the implementation directly.
                    if (symbol.flags & 8388608 /* Alias */) {
                        var declaration = symbol.declarations[0];
                        if (node.kind === 65 /* Identifier */ && node.parent === declaration) {
                            symbol = typeChecker.getAliasedSymbol(symbol);
                        }
                    }
                    // Because name in short-hand property assignment has two different meanings: property name and property value,
                    // using go-to-definition at such position should go to the variable declaration of the property value rather than
                    // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition 
                    // is performed at the location of property access, we would like to go to definition of the property in the short-hand
                    // assignment. This case and others are handled by the following code.
                    if (node.parent.kind === 225 /* ShorthandPropertyAssignment */) {
                        var shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration);
                        if (!shorthandSymbol) {
                            return [];
                        }
                        var shorthandDeclarations = shorthandSymbol.getDeclarations();
                        var shorthandSymbolKind = getSymbolKind(shorthandSymbol, node);
                        var shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol);
                        var shorthandContainerName = typeChecker.symbolToString(symbol.parent, node);
                        return ts.map(shorthandDeclarations, function (declaration) { return createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName); });
                    }
                    var result = [];
                    var declarations = symbol.getDeclarations();
                    var symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol
                    var symbolKind = getSymbolKind(symbol, node);
                    var containerSymbol = symbol.parent;
                    var containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : "";
                    if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) &&
                        !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) {
                        // Just add all the declarations. 
                        ts.forEach(declarations, function (declaration) {
                            result.push(createDefinitionInfo(declaration, symbolKind, symbolName, containerName));
                        });
                    }
                    return result;
                    function tryAddConstructSignature(symbol, location, symbolKind, symbolName, containerName, result) {
                        // Applicable only if we are in a new expression, or we are on a constructor declaration
                        // and in either case the symbol has a construct signature definition, i.e. class
                        if (isNewExpressionTarget(location) || location.kind === 114 /* ConstructorKeyword */) {
                            if (symbol.flags & 32 /* Class */) {
                                var classDeclaration = symbol.getDeclarations()[0];
                                ts.Debug.assert(classDeclaration && classDeclaration.kind === 201 /* ClassDeclaration */);
                                return tryAddSignature(classDeclaration.members, true, symbolKind, symbolName, containerName, result);
                            }
                        }
                        return false;
                    }
                    function tryAddCallSignature(symbol, location, symbolKind, symbolName, containerName, result) {
                        if (isCallExpressionTarget(location) || isNewExpressionTarget(location) || isNameOfFunctionDeclaration(location)) {
                            return tryAddSignature(symbol.declarations, false, symbolKind, symbolName, containerName, result);
                        }
                        return false;
                    }
                    function tryAddSignature(signatureDeclarations, selectConstructors, symbolKind, symbolName, containerName, result) {
                        var declarations = [];
                        var definition;
                        ts.forEach(signatureDeclarations, function (d) {
                            if ((selectConstructors && d.kind === 135 /* Constructor */) ||
                                (!selectConstructors && (d.kind === 200 /* FunctionDeclaration */ || d.kind === 134 /* MethodDeclaration */ || d.kind === 133 /* MethodSignature */))) {
                                declarations.push(d);
                                if (d.body)
                                    definition = d;
                            }
                        });
                        if (definition) {
                            result.push(createDefinitionInfo(definition, symbolKind, symbolName, containerName));
                            return true;
                        }
                        else if (declarations.length) {
                            result.push(createDefinitionInfo(declarations[declarations.length - 1], symbolKind, symbolName, containerName));
                            return true;
                        }
                        return false;
                    }
                }
                function getOccurrencesAtPosition(fileName, position) {
                    var results = getOccurrencesAtPositionCore(fileName, position);
                    if (results) {
                        var sourceFile = getCanonicalFileName(ts.normalizeSlashes(fileName));
                        // Get occurrences only supports reporting occurrences for the file queried.  So 
                        // filter down to that list.
                        results = ts.filter(results, function (r) { return getCanonicalFileName(ts.normalizeSlashes(r.fileName)) === sourceFile; });
                    }
                    return results;
                }
                function getDocumentHighlights(fileName, position, filesToSearch) {
                    synchronizeHostData();
                    filesToSearch = ts.map(filesToSearch, ts.normalizeSlashes);
                    var sourceFilesToSearch = ts.filter(program.getSourceFiles(), function (f) { return ts.contains(filesToSearch, f.fileName); });
                    var sourceFile = getValidSourceFile(fileName);
                    var node = ts.getTouchingWord(sourceFile, position);
                    if (!node) {
                        return undefined;
                    }
                    return getSemanticDocumentHighlights(node) || getSyntacticDocumentHighlights(node);
                    function getHighlightSpanForNode(node) {
                        var start = node.getStart();
                        var end = node.getEnd();
                        return {
                            fileName: sourceFile.fileName,
                            textSpan: ts.createTextSpanFromBounds(start, end),
                            kind: HighlightSpanKind.none
                        };
                    }
                    function getSemanticDocumentHighlights(node) {
                        if (node.kind === 65 /* Identifier */ ||
                            node.kind === 93 /* ThisKeyword */ ||
                            node.kind === 91 /* SuperKeyword */ ||
                            isLiteralNameOfPropertyDeclarationOrIndexAccess(node) ||
                            isNameOfExternalModuleImportOrDeclaration(node)) {
                            var referencedSymbols = getReferencedSymbolsForNodes(node, sourceFilesToSearch, false, false);
                            return convertReferencedSymbols(referencedSymbols);
                        }
                        return undefined;
                        function convertReferencedSymbols(referencedSymbols) {
                            if (!referencedSymbols) {
                                return undefined;
                            }
                            var fileNameToDocumentHighlights = {};
                            var result = [];
                            for (var _i = 0; _i < referencedSymbols.length; _i++) {
                                var referencedSymbol = referencedSymbols[_i];
                                for (var _a = 0, _b = referencedSymbol.references; _a < _b.length; _a++) {
                                    var referenceEntry = _b[_a];
                                    var fileName_1 = referenceEntry.fileName;
                                    var documentHighlights = ts.getProperty(fileNameToDocumentHighlights, fileName_1);
                                    if (!documentHighlights) {
                                        documentHighlights = { fileName: fileName_1, highlightSpans: [] };
                                        fileNameToDocumentHighlights[fileName_1] = documentHighlights;
                                        result.push(documentHighlights);
                                    }
                                    documentHighlights.highlightSpans.push({
                                        textSpan: referenceEntry.textSpan,
                                        kind: referenceEntry.isWriteAccess ? HighlightSpanKind.writtenReference : HighlightSpanKind.reference
                                    });
                                }
                            }
                            return result;
                        }
                    }
                    function getSyntacticDocumentHighlights(node) {
                        var fileName = sourceFile.fileName;
                        var highlightSpans = getHighlightSpans(node);
                        if (!highlightSpans || highlightSpans.length === 0) {
                            return undefined;
                        }
                        return [{ fileName: fileName, highlightSpans: highlightSpans }];
                        // returns true if 'node' is defined and has a matching 'kind'.
                        function hasKind(node, kind) {
                            return node !== undefined && node.kind === kind;
                        }
                        // Null-propagating 'parent' function.
                        function parent(node) {
                            return node && node.parent;
                        }
                        function getHighlightSpans(node) {
                            if (node) {
                                switch (node.kind) {
                                    case 84 /* IfKeyword */:
                                    case 76 /* ElseKeyword */:
                                        if (hasKind(node.parent, 183 /* IfStatement */)) {
                                            return getIfElseOccurrences(node.parent);
                                        }
                                        break;
                                    case 90 /* ReturnKeyword */:
                                        if (hasKind(node.parent, 191 /* ReturnStatement */)) {
                                            return getReturnOccurrences(node.parent);
                                        }
                                        break;
                                    case 94 /* ThrowKeyword */:
                                        if (hasKind(node.parent, 195 /* ThrowStatement */)) {
                                            return getThrowOccurrences(node.parent);
                                        }
                                        break;
                                    case 68 /* CatchKeyword */:
                                        if (hasKind(parent(parent(node)), 196 /* TryStatement */)) {
                                            return getTryCatchFinallyOccurrences(node.parent.parent);
                                        }
                                        break;
                                    case 96 /* TryKeyword */:
                                    case 81 /* FinallyKeyword */:
                                        if (hasKind(parent(node), 196 /* TryStatement */)) {
                                            return getTryCatchFinallyOccurrences(node.parent);
                                        }
                                        break;
                                    case 92 /* SwitchKeyword */:
                                        if (hasKind(node.parent, 193 /* SwitchStatement */)) {
                                            return getSwitchCaseDefaultOccurrences(node.parent);
                                        }
                                        break;
                                    case 67 /* CaseKeyword */:
                                    case 73 /* DefaultKeyword */:
                                        if (hasKind(parent(parent(parent(node))), 193 /* SwitchStatement */)) {
                                            return getSwitchCaseDefaultOccurrences(node.parent.parent.parent);
                                        }
                                        break;
                                    case 66 /* BreakKeyword */:
                                    case 71 /* ContinueKeyword */:
                                        if (hasKind(node.parent, 190 /* BreakStatement */) || hasKind(node.parent, 189 /* ContinueStatement */)) {
                                            return getBreakOrContinueStatementOccurences(node.parent);
                                        }
                                        break;
                                    case 82 /* ForKeyword */:
                                        if (hasKind(node.parent, 186 /* ForStatement */) ||
                                            hasKind(node.parent, 187 /* ForInStatement */) ||
                                            hasKind(node.parent, 188 /* ForOfStatement */)) {
                                            return getLoopBreakContinueOccurrences(node.parent);
                                        }
                                        break;
                                    case 100 /* WhileKeyword */:
                                    case 75 /* DoKeyword */:
                                        if (hasKind(node.parent, 185 /* WhileStatement */) || hasKind(node.parent, 184 /* DoStatement */)) {
                                            return getLoopBreakContinueOccurrences(node.parent);
                                        }
                                        break;
                                    case 114 /* ConstructorKeyword */:
                                        if (hasKind(node.parent, 135 /* Constructor */)) {
                                            return getConstructorOccurrences(node.parent);
                                        }
                                        break;
                                    case 116 /* GetKeyword */:
                                    case 120 /* SetKeyword */:
                                        if (hasKind(node.parent, 136 /* GetAccessor */) || hasKind(node.parent, 137 /* SetAccessor */)) {
                                            return getGetAndSetOccurrences(node.parent);
                                        }
                                    default:
                                        if (ts.isModifier(node.kind) && node.parent &&
                                            (ts.isDeclaration(node.parent) || node.parent.kind === 180 /* VariableStatement */)) {
                                            return getModifierOccurrences(node.kind, node.parent);
                                        }
                                }
                            }
                            return undefined;
                        }
                        /**
                         * Aggregates all throw-statements within this node *without* crossing
                         * into function boundaries and try-blocks with catch-clauses.
                         */
                        function aggregateOwnedThrowStatements(node) {
                            var statementAccumulator = [];
                            aggregate(node);
                            return statementAccumulator;
                            function aggregate(node) {
                                if (node.kind === 195 /* ThrowStatement */) {
                                    statementAccumulator.push(node);
                                }
                                else if (node.kind === 196 /* TryStatement */) {
                                    var tryStatement = node;
                                    if (tryStatement.catchClause) {
                                        aggregate(tryStatement.catchClause);
                                    }
                                    else {
                                        // Exceptions thrown within a try block lacking a catch clause
                                        // are "owned" in the current context.
                                        aggregate(tryStatement.tryBlock);
                                    }
                                    if (tryStatement.finallyBlock) {
                                        aggregate(tryStatement.finallyBlock);
                                    }
                                }
                                else if (!ts.isFunctionLike(node)) {
                                    ts.forEachChild(node, aggregate);
                                }
                            }
                            ;
                        }
                        /**
                         * For lack of a better name, this function takes a throw statement and returns the
                         * nearest ancestor that is a try-block (whose try statement has a catch clause),
                         * function-block, or source file.
                         */
                        function getThrowStatementOwner(throwStatement) {
                            var child = throwStatement;
                            while (child.parent) {
                                var parent_9 = child.parent;
                                if (ts.isFunctionBlock(parent_9) || parent_9.kind === 227 /* SourceFile */) {
                                    return parent_9;
                                }
                                // A throw-statement is only owned by a try-statement if the try-statement has
                                // a catch clause, and if the throw-statement occurs within the try block.
                                if (parent_9.kind === 196 /* TryStatement */) {
                                    var tryStatement = parent_9;
                                    if (tryStatement.tryBlock === child && tryStatement.catchClause) {
                                        return child;
                                    }
                                }
                                child = parent_9;
                            }
                            return undefined;
                        }
                        function aggregateAllBreakAndContinueStatements(node) {
                            var statementAccumulator = [];
                            aggregate(node);
                            return statementAccumulator;
                            function aggregate(node) {
                                if (node.kind === 190 /* BreakStatement */ || node.kind === 189 /* ContinueStatement */) {
                                    statementAccumulator.push(node);
                                }
                                else if (!ts.isFunctionLike(node)) {
                                    ts.forEachChild(node, aggregate);
                                }
                            }
                            ;
                        }
                        function ownsBreakOrContinueStatement(owner, statement) {
                            var actualOwner = getBreakOrContinueOwner(statement);
                            return actualOwner && actualOwner === owner;
                        }
                        function getBreakOrContinueOwner(statement) {
                            for (var node_1 = statement.parent; node_1; node_1 = node_1.parent) {
                                switch (node_1.kind) {
                                    case 193 /* SwitchStatement */:
                                        if (statement.kind === 189 /* ContinueStatement */) {
                                            continue;
                                        }
                                    // Fall through.
                                    case 186 /* ForStatement */:
                                    case 187 /* ForInStatement */:
                                    case 188 /* ForOfStatement */:
                                    case 185 /* WhileStatement */:
                                    case 184 /* DoStatement */:
                                        if (!statement.label || isLabeledBy(node_1, statement.label.text)) {
                                            return node_1;
                                        }
                                        break;
                                    default:
                                        // Don't cross function boundaries.
                                        if (ts.isFunctionLike(node_1)) {
                                            return undefined;
                                        }
                                        break;
                                }
                            }
                            return undefined;
                        }
                        function getModifierOccurrences(modifier, declaration) {
                            var container = declaration.parent;
                            // Make sure we only highlight the keyword when it makes sense to do so.
                            if (ts.isAccessibilityModifier(modifier)) {
                                if (!(container.kind === 201 /* ClassDeclaration */ ||
                                    (declaration.kind === 129 /* Parameter */ && hasKind(container, 135 /* Constructor */)))) {
                                    return undefined;
                                }
                            }
                            else if (modifier === 109 /* StaticKeyword */) {
                                if (container.kind !== 201 /* ClassDeclaration */) {
                                    return undefined;
                                }
                            }
                            else if (modifier === 78 /* ExportKeyword */ || modifier === 115 /* DeclareKeyword */) {
                                if (!(container.kind === 206 /* ModuleBlock */ || container.kind === 227 /* SourceFile */)) {
                                    return undefined;
                                }
                            }
                            else {
                                // unsupported modifier
                                return undefined;
                            }
                            var keywords = [];
                            var modifierFlag = getFlagFromModifier(modifier);
                            var nodes;
                            switch (container.kind) {
                                case 206 /* ModuleBlock */:
                                case 227 /* SourceFile */:
                                    nodes = container.statements;
                                    break;
                                case 135 /* Constructor */:
                                    nodes = container.parameters.concat(container.parent.members);
                                    break;
                                case 201 /* ClassDeclaration */:
                                    nodes = container.members;
                                    // If we're an accessibility modifier, we're in an instance member and should search
                                    // the constructor's parameter list for instance members as well.
                                    if (modifierFlag & 112 /* AccessibilityModifier */) {
                                        var constructor = ts.forEach(container.members, function (member) {
                                            return member.kind === 135 /* Constructor */ && member;
                                        });
                                        if (constructor) {
                                            nodes = nodes.concat(constructor.parameters);
                                        }
                                    }
                                    break;
                                default:
                                    ts.Debug.fail("Invalid container kind.");
                            }
                            ts.forEach(nodes, function (node) {
                                if (node.modifiers && node.flags & modifierFlag) {
                                    ts.forEach(node.modifiers, function (child) { return pushKeywordIf(keywords, child, modifier); });
                                }
                            });
                            return ts.map(keywords, getHighlightSpanForNode);
                            function getFlagFromModifier(modifier) {
                                switch (modifier) {
                                    case 108 /* PublicKeyword */:
                                        return 16 /* Public */;
                                    case 106 /* PrivateKeyword */:
                                        return 32 /* Private */;
                                    case 107 /* ProtectedKeyword */:
                                        return 64 /* Protected */;
                                    case 109 /* StaticKeyword */:
                                        return 128 /* Static */;
                                    case 78 /* ExportKeyword */:
                                        return 1 /* Export */;
                                    case 115 /* DeclareKeyword */:
                                        return 2 /* Ambient */;
                                    default:
                                        ts.Debug.fail();
                                }
                            }
                        }
                        function pushKeywordIf(keywordList, token) {
                            var expected = [];
                            for (var _i = 2; _i < arguments.length; _i++) {
                                expected[_i - 2] = arguments[_i];
                            }
                            if (token && ts.contains(expected, token.kind)) {
                                keywordList.push(token);
                                return true;
                            }
                            return false;
                        }
                        function getGetAndSetOccurrences(accessorDeclaration) {
                            var keywords = [];
                            tryPushAccessorKeyword(accessorDeclaration.symbol, 136 /* GetAccessor */);
                            tryPushAccessorKeyword(accessorDeclaration.symbol, 137 /* SetAccessor */);
                            return ts.map(keywords, getHighlightSpanForNode);
                            function tryPushAccessorKeyword(accessorSymbol, accessorKind) {
                                var accessor = ts.getDeclarationOfKind(accessorSymbol, accessorKind);
                                if (accessor) {
                                    ts.forEach(accessor.getChildren(), function (child) { return pushKeywordIf(keywords, child, 116 /* GetKeyword */, 120 /* SetKeyword */); });
                                }
                            }
                        }
                        function getConstructorOccurrences(constructorDeclaration) {
                            var declarations = constructorDeclaration.symbol.getDeclarations();
                            var keywords = [];
                            ts.forEach(declarations, function (declaration) {
                                ts.forEach(declaration.getChildren(), function (token) {
                                    return pushKeywordIf(keywords, token, 114 /* ConstructorKeyword */);
                                });
                            });
                            return ts.map(keywords, getHighlightSpanForNode);
                        }
                        function getLoopBreakContinueOccurrences(loopNode) {
                            var keywords = [];
                            if (pushKeywordIf(keywords, loopNode.getFirstToken(), 82 /* ForKeyword */, 100 /* WhileKeyword */, 75 /* DoKeyword */)) {
                                // If we succeeded and got a do-while loop, then start looking for a 'while' keyword.
                                if (loopNode.kind === 184 /* DoStatement */) {
                                    var loopTokens = loopNode.getChildren();
                                    for (var i = loopTokens.length - 1; i >= 0; i--) {
                                        if (pushKeywordIf(keywords, loopTokens[i], 100 /* WhileKeyword */)) {
                                            break;
                                        }
                                    }
                                }
                            }
                            var breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement);
                            ts.forEach(breaksAndContinues, function (statement) {
                                if (ownsBreakOrContinueStatement(loopNode, statement)) {
                                    pushKeywordIf(keywords, statement.getFirstToken(), 66 /* BreakKeyword */, 71 /* ContinueKeyword */);
                                }
                            });
                            return ts.map(keywords, getHighlightSpanForNode);
                        }
                        function getBreakOrContinueStatementOccurences(breakOrContinueStatement) {
                            var owner = getBreakOrContinueOwner(breakOrContinueStatement);
                            if (owner) {
                                switch (owner.kind) {
                                    case 186 /* ForStatement */:
                                    case 187 /* ForInStatement */:
                                    case 188 /* ForOfStatement */:
                                    case 184 /* DoStatement */:
                                    case 185 /* WhileStatement */:
                                        return getLoopBreakContinueOccurrences(owner);
                                    case 193 /* SwitchStatement */:
                                        return getSwitchCaseDefaultOccurrences(owner);
                                }
                            }
                            return undefined;
                        }
                        function getSwitchCaseDefaultOccurrences(switchStatement) {
                            var keywords = [];
                            pushKeywordIf(keywords, switchStatement.getFirstToken(), 92 /* SwitchKeyword */);
                            // Go through each clause in the switch statement, collecting the 'case'/'default' keywords.
                            ts.forEach(switchStatement.caseBlock.clauses, function (clause) {
                                pushKeywordIf(keywords, clause.getFirstToken(), 67 /* CaseKeyword */, 73 /* DefaultKeyword */);
                                var breaksAndContinues = aggregateAllBreakAndContinueStatements(clause);
                                ts.forEach(breaksAndContinues, function (statement) {
                                    if (ownsBreakOrContinueStatement(switchStatement, statement)) {
                                        pushKeywordIf(keywords, statement.getFirstToken(), 66 /* BreakKeyword */);
                                    }
                                });
                            });
                            return ts.map(keywords, getHighlightSpanForNode);
                        }
                        function getTryCatchFinallyOccurrences(tryStatement) {
                            var keywords = [];
                            pushKeywordIf(keywords, tryStatement.getFirstToken(), 96 /* TryKeyword */);
                            if (tryStatement.catchClause) {
                                pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 68 /* CatchKeyword */);
                            }
                            if (tryStatement.finallyBlock) {
                                var finallyKeyword = ts.findChildOfKind(tryStatement, 81 /* FinallyKeyword */, sourceFile);
                                pushKeywordIf(keywords, finallyKeyword, 81 /* FinallyKeyword */);
                            }
                            return ts.map(keywords, getHighlightSpanForNode);
                        }
                        function getThrowOccurrences(throwStatement) {
                            var owner = getThrowStatementOwner(throwStatement);
                            if (!owner) {
                                return undefined;
                            }
                            var keywords = [];
                            ts.forEach(aggregateOwnedThrowStatements(owner), function (throwStatement) {
                                pushKeywordIf(keywords, throwStatement.getFirstToken(), 94 /* ThrowKeyword */);
                            });
                            // If the "owner" is a function, then we equate 'return' and 'throw' statements in their
                            // ability to "jump out" of the function, and include occurrences for both.
                            if (ts.isFunctionBlock(owner)) {
                                ts.forEachReturnStatement(owner, function (returnStatement) {
                                    pushKeywordIf(keywords, returnStatement.getFirstToken(), 90 /* ReturnKeyword */);
                                });
                            }
                            return ts.map(keywords, getHighlightSpanForNode);
                        }
                        function getReturnOccurrences(returnStatement) {
                            var func = ts.getContainingFunction(returnStatement);
                            // If we didn't find a containing function with a block body, bail out.
                            if (!(func && hasKind(func.body, 179 /* Block */))) {
                                return undefined;
                            }
                            var keywords = [];
                            ts.forEachReturnStatement(func.body, function (returnStatement) {
                                pushKeywordIf(keywords, returnStatement.getFirstToken(), 90 /* ReturnKeyword */);
                            });
                            // Include 'throw' statements that do not occur within a try block.
                            ts.forEach(aggregateOwnedThrowStatements(func.body), function (throwStatement) {
                                pushKeywordIf(keywords, throwStatement.getFirstToken(), 94 /* ThrowKeyword */);
                            });
                            return ts.map(keywords, getHighlightSpanForNode);
                        }
                        function getIfElseOccurrences(ifStatement) {
                            var keywords = [];
                            // Traverse upwards through all parent if-statements linked by their else-branches.
                            while (hasKind(ifStatement.parent, 183 /* IfStatement */) && ifStatement.parent.elseStatement === ifStatement) {
                                ifStatement = ifStatement.parent;
                            }
                            // Now traverse back down through the else branches, aggregating if/else keywords of if-statements.
                            while (ifStatement) {
                                var children = ifStatement.getChildren();
                                pushKeywordIf(keywords, children[0], 84 /* IfKeyword */);
                                // Generally the 'else' keyword is second-to-last, so we traverse backwards.
                                for (var i = children.length - 1; i >= 0; i--) {
                                    if (pushKeywordIf(keywords, children[i], 76 /* ElseKeyword */)) {
                                        break;
                                    }
                                }
                                if (!hasKind(ifStatement.elseStatement, 183 /* IfStatement */)) {
                                    break;
                                }
                                ifStatement = ifStatement.elseStatement;
                            }
                            var result = [];
                            // We'd like to highlight else/ifs together if they are only separated by whitespace
                            // (i.e. the keywords are separated by no comments, no newlines).
                            for (var i = 0; i < keywords.length; i++) {
                                if (keywords[i].kind === 76 /* ElseKeyword */ && i < keywords.length - 1) {
                                    var elseKeyword = keywords[i];
                                    var ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword.
                                    var shouldCombindElseAndIf = true;
                                    // Avoid recalculating getStart() by iterating backwards.
                                    for (var j = ifKeyword.getStart() - 1; j >= elseKeyword.end; j--) {
                                        if (!ts.isWhiteSpace(sourceFile.text.charCodeAt(j))) {
                                            shouldCombindElseAndIf = false;
                                            break;
                                        }
                                    }
                                    if (shouldCombindElseAndIf) {
                                        result.push({
                                            fileName: fileName,
                                            textSpan: ts.createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end),
                                            kind: HighlightSpanKind.reference
                                        });
                                        i++; // skip the next keyword
                                        continue;
                                    }
                                }
                                // Ordinary case: just highlight the keyword.
                                result.push(getHighlightSpanForNode(keywords[i]));
                            }
                            return result;
                        }
                    }
                }
                /// References and Occurrences
                function getOccurrencesAtPositionCore(fileName, position) {
                    synchronizeHostData();
                    return convertDocumentHighlights(getDocumentHighlights(fileName, position, [fileName]));
                    function convertDocumentHighlights(documentHighlights) {
                        if (!documentHighlights) {
                            return undefined;
                        }
                        var result = [];
                        for (var _i = 0; _i < documentHighlights.length; _i++) {
                            var entry = documentHighlights[_i];
                            for (var _a = 0, _b = entry.highlightSpans; _a < _b.length; _a++) {
                                var highlightSpan = _b[_a];
                                result.push({
                                    fileName: entry.fileName,
                                    textSpan: highlightSpan.textSpan,
                                    isWriteAccess: highlightSpan.kind === HighlightSpanKind.writtenReference
                                });
                            }
                        }
                        return result;
                    }
                }
                function convertReferences(referenceSymbols) {
                    if (!referenceSymbols) {
                        return undefined;
                    }
                    var referenceEntries = [];
                    for (var _i = 0; _i < referenceSymbols.length; _i++) {
                        var referenceSymbol = referenceSymbols[_i];
                        ts.addRange(referenceEntries, referenceSymbol.references);
                    }
                    return referenceEntries;
                }
                function findRenameLocations(fileName, position, findInStrings, findInComments) {
                    var referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments);
                    return convertReferences(referencedSymbols);
                }
                function getReferencesAtPosition(fileName, position) {
                    var referencedSymbols = findReferencedSymbols(fileName, position, false, false);
                    return convertReferences(referencedSymbols);
                }
                function findReferences(fileName, position) {
                    var referencedSymbols = findReferencedSymbols(fileName, position, false, false);
                    // Only include referenced symbols that have a valid definition.
                    return ts.filter(referencedSymbols, function (rs) { return !!rs.definition; });
                }
                function findReferencedSymbols(fileName, position, findInStrings, findInComments) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    var node = ts.getTouchingPropertyName(sourceFile, position);
                    if (!node) {
                        return undefined;
                    }
                    if (node.kind !== 65 /* Identifier */ &&
                        // TODO (drosen): This should be enabled in a later release - currently breaks rename.
                        //node.kind !== SyntaxKind.ThisKeyword &&
                        //node.kind !== SyntaxKind.SuperKeyword &&
                        !isLiteralNameOfPropertyDeclarationOrIndexAccess(node) &&
                        !isNameOfExternalModuleImportOrDeclaration(node)) {
                        return undefined;
                    }
                    ts.Debug.assert(node.kind === 65 /* Identifier */ || node.kind === 7 /* NumericLiteral */ || node.kind === 8 /* StringLiteral */);
                    return getReferencedSymbolsForNodes(node, program.getSourceFiles(), findInStrings, findInComments);
                }
                function getReferencedSymbolsForNodes(node, sourceFiles, findInStrings, findInComments) {
                    var typeChecker = program.getTypeChecker();
                    // Labels
                    if (isLabelName(node)) {
                        if (isJumpStatementTarget(node)) {
                            var labelDefinition = getTargetLabel(node.parent, node.text);
                            // if we have a label definition, look within its statement for references, if not, then
                            // the label is undefined and we have no results..
                            return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined;
                        }
                        else {
                            // it is a label definition and not a target, search within the parent labeledStatement
                            return getLabelReferencesInNode(node.parent, node);
                        }
                    }
                    if (node.kind === 93 /* ThisKeyword */) {
                        return getReferencesForThisKeyword(node, sourceFiles);
                    }
                    if (node.kind === 91 /* SuperKeyword */) {
                        return getReferencesForSuperKeyword(node);
                    }
                    var symbol = typeChecker.getSymbolAtLocation(node);
                    // Could not find a symbol e.g. unknown identifier
                    if (!symbol) {
                        // Can't have references to something that we have no symbol for.
                        return undefined;
                    }
                    var declarations = symbol.declarations;
                    // The symbol was an internal symbol and does not have a declaration e.g.undefined symbol
                    if (!declarations || !declarations.length) {
                        return undefined;
                    }
                    var result;
                    // Compute the meaning from the location and the symbol it references
                    var searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations);
                    // Get the text to search for, we need to normalize it as external module names will have quote
                    var declaredName = getDeclaredName(symbol, node);
                    // Try to get the smallest valid scope that we can limit our search to;
                    // otherwise we'll need to search globally (i.e. include each file).
                    var scope = getSymbolScope(symbol);
                    // Maps from a symbol ID to the ReferencedSymbol entry in 'result'.
                    var symbolToIndex = [];
                    if (scope) {
                        result = [];
                        getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
                    }
                    else {
                        var internedName = getInternedName(symbol, node, declarations);
                        for (var _i = 0; _i < sourceFiles.length; _i++) {
                            var sourceFile = sourceFiles[_i];
                            cancellationToken.throwIfCancellationRequested();
                            var nameTable = getNameTable(sourceFile);
                            if (ts.lookUp(nameTable, internedName)) {
                                result = result || [];
                                getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
                            }
                        }
                    }
                    return result;
                    function getDefinition(symbol) {
                        var info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node);
                        var name = ts.map(info.displayParts, function (p) { return p.text; }).join("");
                        var declarations = symbol.declarations;
                        if (!declarations || declarations.length === 0) {
                            return undefined;
                        }
                        return {
                            containerKind: "",
                            containerName: "",
                            name: name,
                            kind: info.symbolKind,
                            fileName: declarations[0].getSourceFile().fileName,
                            textSpan: ts.createTextSpan(declarations[0].getStart(), 0)
                        };
                    }
                    function isImportOrExportSpecifierName(location) {
                        return location.parent &&
                            (location.parent.kind === 213 /* ImportSpecifier */ || location.parent.kind === 217 /* ExportSpecifier */) &&
                            location.parent.propertyName === location;
                    }
                    function isImportOrExportSpecifierImportSymbol(symbol) {
                        return (symbol.flags & 8388608 /* Alias */) && ts.forEach(symbol.declarations, function (declaration) {
                            return declaration.kind === 213 /* ImportSpecifier */ || declaration.kind === 217 /* ExportSpecifier */;
                        });
                    }
                    function getDeclaredName(symbol, location) {
                        // Special case for function expressions, whose names are solely local to their bodies.
                        var functionExpression = ts.forEach(symbol.declarations, function (d) { return d.kind === 162 /* FunctionExpression */ ? d : undefined; });
                        // When a name gets interned into a SourceFile's 'identifiers' Map,
                        // its name is escaped and stored in the same way its symbol name/identifier
                        // name should be stored. Function expressions, however, are a special case,
                        // because despite sometimes having a name, the binder unconditionally binds them
                        // to a symbol with the name "__function".
                        var name;
                        if (functionExpression && functionExpression.name) {
                            name = functionExpression.name.text;
                        }
                        // If this is an export or import specifier it could have been renamed using the as syntax.
                        // if so we want to search for whatever under the cursor, the symbol is pointing to the alias (name)
                        // so check for the propertyName.
                        if (isImportOrExportSpecifierName(location)) {
                            return location.getText();
                        }
                        name = typeChecker.symbolToString(symbol);
                        return stripQuotes(name);
                    }
                    function getInternedName(symbol, location, declarations) {
                        // If this is an export or import specifier it could have been renamed using the as syntax.
                        // if so we want to search for whatever under the cursor, the symbol is pointing to the alias (name)
                        // so check for the propertyName.
                        if (isImportOrExportSpecifierName(location)) {
                            return location.getText();
                        }
                        // Special case for function expressions, whose names are solely local to their bodies.
                        var functionExpression = ts.forEach(declarations, function (d) { return d.kind === 162 /* FunctionExpression */ ? d : undefined; });
                        // When a name gets interned into a SourceFile's 'identifiers' Map,
                        // its name is escaped and stored in the same way its symbol name/identifier
                        // name should be stored. Function expressions, however, are a special case,
                        // because despite sometimes having a name, the binder unconditionally binds them
                        // to a symbol with the name "__function".
                        var name = functionExpression && functionExpression.name
                            ? functionExpression.name.text
                            : symbol.name;
                        return stripQuotes(name);
                    }
                    function stripQuotes(name) {
                        var length = name.length;
                        if (length >= 2 && name.charCodeAt(0) === 34 /* doubleQuote */ && name.charCodeAt(length - 1) === 34 /* doubleQuote */) {
                            return name.substring(1, length - 1);
                        }
                        ;
                        return name;
                    }
                    function getSymbolScope(symbol) {
                        // If this is private property or method, the scope is the containing class
                        if (symbol.flags & (4 /* Property */ | 8192 /* Method */)) {
                            var privateDeclaration = ts.forEach(symbol.getDeclarations(), function (d) { return (d.flags & 32 /* Private */) ? d : undefined; });
                            if (privateDeclaration) {
                                return ts.getAncestor(privateDeclaration, 201 /* ClassDeclaration */);
                            }
                        }
                        // If the symbol is an import we would like to find it if we are looking for what it imports.
                        // So consider it visibile outside its declaration scope.
                        if (symbol.flags & 8388608 /* Alias */) {
                            return undefined;
                        }
                        // if this symbol is visible from its parent container, e.g. exported, then bail out
                        // if symbol correspond to the union property - bail out
                        if (symbol.parent || (symbol.flags & 268435456 /* UnionProperty */)) {
                            return undefined;
                        }
                        var scope = undefined;
                        var declarations = symbol.getDeclarations();
                        if (declarations) {
                            for (var _i = 0; _i < declarations.length; _i++) {
                                var declaration = declarations[_i];
                                var container = getContainerNode(declaration);
                                if (!container) {
                                    return undefined;
                                }
                                if (scope && scope !== container) {
                                    // Different declarations have different containers, bail out
                                    return undefined;
                                }
                                if (container.kind === 227 /* SourceFile */ && !ts.isExternalModule(container)) {
                                    // This is a global variable and not an external module, any declaration defined
                                    // within this scope is visible outside the file
                                    return undefined;
                                }
                                // The search scope is the container node
                                scope = container;
                            }
                        }
                        return scope;
                    }
                    function getPossibleSymbolReferencePositions(sourceFile, symbolName, start, end) {
                        var positions = [];
                        /// TODO: Cache symbol existence for files to save text search
                        // Also, need to make this work for unicode escapes.
                        // Be resilient in the face of a symbol with no name or zero length name
                        if (!symbolName || !symbolName.length) {
                            return positions;
                        }
                        var text = sourceFile.text;
                        var sourceLength = text.length;
                        var symbolNameLength = symbolName.length;
                        var position = text.indexOf(symbolName, start);
                        while (position >= 0) {
                            cancellationToken.throwIfCancellationRequested();
                            // If we are past the end, stop looking
                            if (position > end)
                                break;
                            // We found a match.  Make sure it's not part of a larger word (i.e. the char 
                            // before and after it have to be a non-identifier char).
                            var endPosition = position + symbolNameLength;
                            if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), 2 /* Latest */)) &&
                                (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 2 /* Latest */))) {
                                // Found a real match.  Keep searching.  
                                positions.push(position);
                            }
                            position = text.indexOf(symbolName, position + symbolNameLength + 1);
                        }
                        return positions;
                    }
                    function getLabelReferencesInNode(container, targetLabel) {
                        var references = [];
                        var sourceFile = container.getSourceFile();
                        var labelName = targetLabel.text;
                        var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd());
                        ts.forEach(possiblePositions, function (position) {
                            cancellationToken.throwIfCancellationRequested();
                            var node = ts.getTouchingWord(sourceFile, position);
                            if (!node || node.getWidth() !== labelName.length) {
                                return;
                            }
                            // Only pick labels that are either the target label, or have a target that is the target label
                            if (node === targetLabel ||
                                (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel)) {
                                references.push(getReferenceEntryFromNode(node));
                            }
                        });
                        var definition = {
                            containerKind: "",
                            containerName: "",
                            fileName: targetLabel.getSourceFile().fileName,
                            kind: ScriptElementKind.label,
                            name: labelName,
                            textSpan: ts.createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd())
                        };
                        return [{ definition: definition, references: references }];
                    }
                    function isValidReferencePosition(node, searchSymbolName) {
                        if (node) {
                            // Compare the length so we filter out strict superstrings of the symbol we are looking for
                            switch (node.kind) {
                                case 65 /* Identifier */:
                                    return node.getWidth() === searchSymbolName.length;
                                case 8 /* StringLiteral */:
                                    if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node) ||
                                        isNameOfExternalModuleImportOrDeclaration(node)) {
                                        // For string literals we have two additional chars for the quotes
                                        return node.getWidth() === searchSymbolName.length + 2;
                                    }
                                    break;
                                case 7 /* NumericLiteral */:
                                    if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) {
                                        return node.getWidth() === searchSymbolName.length;
                                    }
                                    break;
                            }
                        }
                        return false;
                    }
                    /** Search within node "container" for references for a search value, where the search value is defined as a
                      * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
                      * searchLocation: a node where the search value
                      */
                    function getReferencesInNode(container, searchSymbol, searchText, searchLocation, searchMeaning, findInStrings, findInComments, result, symbolToIndex) {
                        var sourceFile = container.getSourceFile();
                        var tripleSlashDirectivePrefixRegex = /^\/\/\/\s*</;
                        var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, container.getStart(), container.getEnd());
                        if (possiblePositions.length) {
                            // Build the set of symbols to search for, initially it has only the current symbol
                            var searchSymbols = populateSearchSymbolSet(searchSymbol, searchLocation);
                            ts.forEach(possiblePositions, function (position) {
                                cancellationToken.throwIfCancellationRequested();
                                var referenceLocation = ts.getTouchingPropertyName(sourceFile, position);
                                if (!isValidReferencePosition(referenceLocation, searchText)) {
                                    // This wasn't the start of a token.  Check to see if it might be a 
                                    // match in a comment or string if that's what the caller is asking
                                    // for.
                                    if ((findInStrings && isInString(position)) ||
                                        (findInComments && isInComment(position))) {
                                        // In the case where we're looking inside comments/strings, we don't have
                                        // an actual definition.  So just use 'undefined' here.  Features like
                                        // 'Rename' won't care (as they ignore the definitions), and features like
                                        // 'FindReferences' will just filter out these results.
                                        result.push({
                                            definition: undefined,
                                            references: [{
                                                    fileName: sourceFile.fileName,
                                                    textSpan: ts.createTextSpan(position, searchText.length),
                                                    isWriteAccess: false
                                                }]
                                        });
                                    }
                                    return;
                                }
                                if (!(getMeaningFromLocation(referenceLocation) & searchMeaning)) {
                                    return;
                                }
                                var referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation);
                                if (referenceSymbol) {
                                    var referenceSymbolDeclaration = referenceSymbol.valueDeclaration;
                                    var shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration);
                                    var relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation);
                                    if (relatedSymbol) {
                                        var referencedSymbol = getReferencedSymbol(relatedSymbol);
                                        referencedSymbol.references.push(getReferenceEntryFromNode(referenceLocation));
                                    }
                                    else if (!(referenceSymbol.flags & 67108864 /* Transient */) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) {
                                        var referencedSymbol = getReferencedSymbol(shorthandValueSymbol);
                                        referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name));
                                    }
                                }
                            });
                        }
                        return;
                        function getReferencedSymbol(symbol) {
                            var symbolId = ts.getSymbolId(symbol);
                            var index = symbolToIndex[symbolId];
                            if (index === undefined) {
                                index = result.length;
                                symbolToIndex[symbolId] = index;
                                result.push({
                                    definition: getDefinition(symbol),
                                    references: []
                                });
                            }
                            return result[index];
                        }
                        function isInString(position) {
                            var token = ts.getTokenAtPosition(sourceFile, position);
                            return token && token.kind === 8 /* StringLiteral */ && position > token.getStart();
                        }
                        function isInComment(position) {
                            var token = ts.getTokenAtPosition(sourceFile, position);
                            if (token && position < token.getStart()) {
                                // First, we have to see if this position actually landed in a comment.
                                var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos);
                                // Then we want to make sure that it wasn't in a "///<" directive comment
                                // We don't want to unintentionally update a file name.
                                return ts.forEach(commentRanges, function (c) {
                                    if (c.pos < position && position < c.end) {
                                        var commentText = sourceFile.text.substring(c.pos, c.end);
                                        if (!tripleSlashDirectivePrefixRegex.test(commentText)) {
                                            return true;
                                        }
                                    }
                                });
                            }
                            return false;
                        }
                    }
                    function getReferencesForSuperKeyword(superKeyword) {
                        var searchSpaceNode = ts.getSuperContainer(superKeyword, false);
                        if (!searchSpaceNode) {
                            return undefined;
                        }
                        // Whether 'super' occurs in a static context within a class.
                        var staticFlag = 128 /* Static */;
                        switch (searchSpaceNode.kind) {
                            case 132 /* PropertyDeclaration */:
                            case 131 /* PropertySignature */:
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                            case 135 /* Constructor */:
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                                staticFlag &= searchSpaceNode.flags;
                                searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
                                break;
                            default:
                                return undefined;
                        }
                        var references = [];
                        var sourceFile = searchSpaceNode.getSourceFile();
                        var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd());
                        ts.forEach(possiblePositions, function (position) {
                            cancellationToken.throwIfCancellationRequested();
                            var node = ts.getTouchingWord(sourceFile, position);
                            if (!node || node.kind !== 91 /* SuperKeyword */) {
                                return;
                            }
                            var container = ts.getSuperContainer(node, false);
                            // If we have a 'super' container, we must have an enclosing class.
                            // Now make sure the owning class is the same as the search-space
                            // and has the same static qualifier as the original 'super's owner.
                            if (container && (128 /* Static */ & container.flags) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) {
                                references.push(getReferenceEntryFromNode(node));
                            }
                        });
                        var definition = getDefinition(searchSpaceNode.symbol);
                        return [{ definition: definition, references: references }];
                    }
                    function getReferencesForThisKeyword(thisOrSuperKeyword, sourceFiles) {
                        var searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, false);
                        // Whether 'this' occurs in a static context within a class.
                        var staticFlag = 128 /* Static */;
                        switch (searchSpaceNode.kind) {
                            case 134 /* MethodDeclaration */:
                            case 133 /* MethodSignature */:
                                if (ts.isObjectLiteralMethod(searchSpaceNode)) {
                                    break;
                                }
                            // fall through
                            case 132 /* PropertyDeclaration */:
                            case 131 /* PropertySignature */:
                            case 135 /* Constructor */:
                            case 136 /* GetAccessor */:
                            case 137 /* SetAccessor */:
                                staticFlag &= searchSpaceNode.flags;
                                searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
                                break;
                            case 227 /* SourceFile */:
                                if (ts.isExternalModule(searchSpaceNode)) {
                                    return undefined;
                                }
                            // Fall through
                            case 200 /* FunctionDeclaration */:
                            case 162 /* FunctionExpression */:
                                break;
                            // Computed properties in classes are not handled here because references to this are illegal,
                            // so there is no point finding references to them.
                            default:
                                return undefined;
                        }
                        var references = [];
                        var possiblePositions;
                        if (searchSpaceNode.kind === 227 /* SourceFile */) {
                            ts.forEach(sourceFiles, function (sourceFile) {
                                possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", sourceFile.getStart(), sourceFile.getEnd());
                                getThisReferencesInFile(sourceFile, sourceFile, possiblePositions, references);
                            });
                        }
                        else {
                            var sourceFile = searchSpaceNode.getSourceFile();
                            possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd());
                            getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references);
                        }
                        return [{
                                definition: {
                                    containerKind: "",
                                    containerName: "",
                                    fileName: node.getSourceFile().fileName,
                                    kind: ScriptElementKind.variableElement,
                                    name: "this",
                                    textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd())
                                },
                                references: references
                            }];
                        function getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, result) {
                            ts.forEach(possiblePositions, function (position) {
                                cancellationToken.throwIfCancellationRequested();
                                var node = ts.getTouchingWord(sourceFile, position);
                                if (!node || node.kind !== 93 /* ThisKeyword */) {
                                    return;
                                }
                                var container = ts.getThisContainer(node, false);
                                switch (searchSpaceNode.kind) {
                                    case 162 /* FunctionExpression */:
                                    case 200 /* FunctionDeclaration */:
                                        if (searchSpaceNode.symbol === container.symbol) {
                                            result.push(getReferenceEntryFromNode(node));
                                        }
                                        break;
                                    case 134 /* MethodDeclaration */:
                                    case 133 /* MethodSignature */:
                                        if (ts.isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol) {
                                            result.push(getReferenceEntryFromNode(node));
                                        }
                                        break;
                                    case 201 /* ClassDeclaration */:
                                        // Make sure the container belongs to the same class
                                        // and has the appropriate static modifier from the original container.
                                        if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (container.flags & 128 /* Static */) === staticFlag) {
                                            result.push(getReferenceEntryFromNode(node));
                                        }
                                        break;
                                    case 227 /* SourceFile */:
                                        if (container.kind === 227 /* SourceFile */ && !ts.isExternalModule(container)) {
                                            result.push(getReferenceEntryFromNode(node));
                                        }
                                        break;
                                }
                            });
                        }
                    }
                    function populateSearchSymbolSet(symbol, location) {
                        // The search set contains at least the current symbol
                        var result = [symbol];
                        // If the symbol is an alias, add what it alaises to the list
                        if (isImportOrExportSpecifierImportSymbol(symbol)) {
                            result.push(typeChecker.getAliasedSymbol(symbol));
                        }
                        // If the location is in a context sensitive location (i.e. in an object literal) try
                        // to get a contextual type for it, and add the property symbol from the contextual
                        // type to the search set
                        if (isNameOfPropertyAssignment(location)) {
                            ts.forEach(getPropertySymbolsFromContextualType(location), function (contextualSymbol) {
                                result.push.apply(result, typeChecker.getRootSymbols(contextualSymbol));
                            });
                            /* Because in short-hand property assignment, location has two meaning : property name and as value of the property
                             * When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of
                             * property name and variable declaration of the identifier.
                             * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service
                             * should show both 'name' in 'obj' and 'name' in variable declaration
                             *      let name = "Foo";
                             *      let obj = { name };
                             * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment
                             * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration
                             * will be included correctly.
                             */
                            var shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent);
                            if (shorthandValueSymbol) {
                                result.push(shorthandValueSymbol);
                            }
                        }
                        // If this is a union property, add all the symbols from all its source symbols in all unioned types.
                        // If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list
                        ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) {
                            if (rootSymbol !== symbol) {
                                result.push(rootSymbol);
                            }
                            // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
                            if (rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */)) {
                                getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result);
                            }
                        });
                        return result;
                    }
                    function getPropertySymbolsFromBaseTypes(symbol, propertyName, result) {
                        if (symbol && symbol.flags & (32 /* Class */ | 64 /* Interface */)) {
                            ts.forEach(symbol.getDeclarations(), function (declaration) {
                                if (declaration.kind === 201 /* ClassDeclaration */) {
                                    getPropertySymbolFromTypeReference(ts.getClassExtendsHeritageClauseElement(declaration));
                                    ts.forEach(ts.getClassImplementsHeritageClauseElements(declaration), getPropertySymbolFromTypeReference);
                                }
                                else if (declaration.kind === 202 /* InterfaceDeclaration */) {
                                    ts.forEach(ts.getInterfaceBaseTypeNodes(declaration), getPropertySymbolFromTypeReference);
                                }
                            });
                        }
                        return;
                        function getPropertySymbolFromTypeReference(typeReference) {
                            if (typeReference) {
                                var type = typeChecker.getTypeAtLocation(typeReference);
                                if (type) {
                                    var propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
                                    if (propertySymbol) {
                                        result.push(propertySymbol);
                                    }
                                    // Visit the typeReference as well to see if it directly or indirectly use that property
                                    getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result);
                                }
                            }
                        }
                    }
                    function getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation) {
                        if (searchSymbols.indexOf(referenceSymbol) >= 0) {
                            return referenceSymbol;
                        }
                        // If the reference symbol is an alias, check if what it is aliasing is one of the search
                        // symbols.
                        if (isImportOrExportSpecifierImportSymbol(referenceSymbol)) {
                            var aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol);
                            if (searchSymbols.indexOf(aliasedSymbol) >= 0) {
                                return aliasedSymbol;
                            }
                        }
                        // If the reference location is in an object literal, try to get the contextual type for the 
                        // object literal, lookup the property symbol in the contextual type, and use this symbol to
                        // compare to our searchSymbol
                        if (isNameOfPropertyAssignment(referenceLocation)) {
                            return ts.forEach(getPropertySymbolsFromContextualType(referenceLocation), function (contextualSymbol) {
                                return ts.forEach(typeChecker.getRootSymbols(contextualSymbol), function (s) { return searchSymbols.indexOf(s) >= 0 ? s : undefined; });
                            });
                        }
                        // Unwrap symbols to get to the root (e.g. transient symbols as a result of widening)
                        // Or a union property, use its underlying unioned symbols
                        return ts.forEach(typeChecker.getRootSymbols(referenceSymbol), function (rootSymbol) {
                            // if it is in the list, then we are done
                            if (searchSymbols.indexOf(rootSymbol) >= 0) {
                                return rootSymbol;
                            }
                            // Finally, try all properties with the same name in any type the containing type extended or implemented, and 
                            // see if any is in the list
                            if (rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */)) {
                                var result_3 = [];
                                getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result_3);
                                return ts.forEach(result_3, function (s) { return searchSymbols.indexOf(s) >= 0 ? s : undefined; });
                            }
                            return undefined;
                        });
                    }
                    function getPropertySymbolsFromContextualType(node) {
                        if (isNameOfPropertyAssignment(node)) {
                            var objectLiteral = node.parent.parent;
                            var contextualType = typeChecker.getContextualType(objectLiteral);
                            var name_25 = node.text;
                            if (contextualType) {
                                if (contextualType.flags & 16384 /* Union */) {
                                    // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types)
                                    // if not, search the constituent types for the property
                                    var unionProperty = contextualType.getProperty(name_25);
                                    if (unionProperty) {
                                        return [unionProperty];
                                    }
                                    else {
                                        var result_4 = [];
                                        ts.forEach(contextualType.types, function (t) {
                                            var symbol = t.getProperty(name_25);
                                            if (symbol) {
                                                result_4.push(symbol);
                                            }
                                        });
                                        return result_4;
                                    }
                                }
                                else {
                                    var symbol_1 = contextualType.getProperty(name_25);
                                    if (symbol_1) {
                                        return [symbol_1];
                                    }
                                }
                            }
                        }
                        return undefined;
                    }
                    /** Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations
                      * of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class
                      * then we need to widen the search to include type positions as well.
                      * On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated
                      * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module)
                      * do not intersect in any of the three spaces.
                      */
                    function getIntersectingMeaningFromDeclarations(meaning, declarations) {
                        if (declarations) {
                            var lastIterationMeaning;
                            do {
                                // The result is order-sensitive, for instance if initialMeaning === Namespace, and declarations = [class, instantiated module]
                                // we need to consider both as they initialMeaning intersects with the module in the namespace space, and the module
                                // intersects with the class in the value space.
                                // To achieve that we will keep iterating until the result stabilizes.
                                // Remember the last meaning
                                lastIterationMeaning = meaning;
                                for (var _i = 0; _i < declarations.length; _i++) {
                                    var declaration = declarations[_i];
                                    var declarationMeaning = getMeaningFromDeclaration(declaration);
                                    if (declarationMeaning & meaning) {
                                        meaning |= declarationMeaning;
                                    }
                                }
                            } while (meaning !== lastIterationMeaning);
                        }
                        return meaning;
                    }
                }
                function getReferenceEntryFromNode(node) {
                    var start = node.getStart();
                    var end = node.getEnd();
                    if (node.kind === 8 /* StringLiteral */) {
                        start += 1;
                        end -= 1;
                    }
                    return {
                        fileName: node.getSourceFile().fileName,
                        textSpan: ts.createTextSpanFromBounds(start, end),
                        isWriteAccess: isWriteAccess(node)
                    };
                }
                /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */
                function isWriteAccess(node) {
                    if (node.kind === 65 /* Identifier */ && ts.isDeclarationName(node)) {
                        return true;
                    }
                    var parent = node.parent;
                    if (parent) {
                        if (parent.kind === 168 /* PostfixUnaryExpression */ || parent.kind === 167 /* PrefixUnaryExpression */) {
                            return true;
                        }
                        else if (parent.kind === 169 /* BinaryExpression */ && parent.left === node) {
                            var operator = parent.operatorToken.kind;
                            return 53 /* FirstAssignment */ <= operator && operator <= 64 /* LastAssignment */;
                        }
                    }
                    return false;
                }
                /// NavigateTo
                function getNavigateToItems(searchValue, maxResultCount) {
                    synchronizeHostData();
                    return ts.NavigateTo.getNavigateToItems(program, cancellationToken, searchValue, maxResultCount);
                }
                function containErrors(diagnostics) {
                    return ts.forEach(diagnostics, function (diagnostic) { return diagnostic.category === ts.DiagnosticCategory.Error; });
                }
                function getEmitOutput(fileName) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    var outputFiles = [];
                    function writeFile(fileName, data, writeByteOrderMark) {
                        outputFiles.push({
                            name: fileName,
                            writeByteOrderMark: writeByteOrderMark,
                            text: data
                        });
                    }
                    var emitOutput = program.emit(sourceFile, writeFile);
                    return {
                        outputFiles: outputFiles,
                        emitSkipped: emitOutput.emitSkipped
                    };
                }
                function getMeaningFromDeclaration(node) {
                    switch (node.kind) {
                        case 129 /* Parameter */:
                        case 198 /* VariableDeclaration */:
                        case 152 /* BindingElement */:
                        case 132 /* PropertyDeclaration */:
                        case 131 /* PropertySignature */:
                        case 224 /* PropertyAssignment */:
                        case 225 /* ShorthandPropertyAssignment */:
                        case 226 /* EnumMember */:
                        case 134 /* MethodDeclaration */:
                        case 133 /* MethodSignature */:
                        case 135 /* Constructor */:
                        case 136 /* GetAccessor */:
                        case 137 /* SetAccessor */:
                        case 200 /* FunctionDeclaration */:
                        case 162 /* FunctionExpression */:
                        case 163 /* ArrowFunction */:
                        case 223 /* CatchClause */:
                            return 1 /* Value */;
                        case 128 /* TypeParameter */:
                        case 202 /* InterfaceDeclaration */:
                        case 203 /* TypeAliasDeclaration */:
                        case 145 /* TypeLiteral */:
                            return 2 /* Type */;
                        case 201 /* ClassDeclaration */:
                        case 204 /* EnumDeclaration */:
                            return 1 /* Value */ | 2 /* Type */;
                        case 205 /* ModuleDeclaration */:
                            if (node.name.kind === 8 /* StringLiteral */) {
                                return 4 /* Namespace */ | 1 /* Value */;
                            }
                            else if (ts.getModuleInstanceState(node) === 1 /* Instantiated */) {
                                return 4 /* Namespace */ | 1 /* Value */;
                            }
                            else {
                                return 4 /* Namespace */;
                            }
                        case 212 /* NamedImports */:
                        case 213 /* ImportSpecifier */:
                        case 208 /* ImportEqualsDeclaration */:
                        case 209 /* ImportDeclaration */:
                        case 214 /* ExportAssignment */:
                        case 215 /* ExportDeclaration */:
                            return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */;
                        // An external module can be a Value
                        case 227 /* SourceFile */:
                            return 4 /* Namespace */ | 1 /* Value */;
                    }
                    return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */;
                    ts.Debug.fail("Unknown declaration type");
                }
                function isTypeReference(node) {
                    if (ts.isRightSideOfQualifiedNameOrPropertyAccess(node)) {
                        node = node.parent;
                    }
                    return node.parent.kind === 141 /* TypeReference */ || node.parent.kind === 177 /* HeritageClauseElement */;
                }
                function isNamespaceReference(node) {
                    return isQualifiedNameNamespaceReference(node) || isPropertyAccessNamespaceReference(node);
                }
                function isPropertyAccessNamespaceReference(node) {
                    var root = node;
                    var isLastClause = true;
                    if (root.parent.kind === 155 /* PropertyAccessExpression */) {
                        while (root.parent && root.parent.kind === 155 /* PropertyAccessExpression */) {
                            root = root.parent;
                        }
                        isLastClause = root.name === node;
                    }
                    if (!isLastClause && root.parent.kind === 177 /* HeritageClauseElement */ && root.parent.parent.kind === 222 /* HeritageClause */) {
                        var decl = root.parent.parent.parent;
                        return (decl.kind === 201 /* ClassDeclaration */ && root.parent.parent.token === 102 /* ImplementsKeyword */) ||
                            (decl.kind === 202 /* InterfaceDeclaration */ && root.parent.parent.token === 79 /* ExtendsKeyword */);
                    }
                    return false;
                }
                function isQualifiedNameNamespaceReference(node) {
                    var root = node;
                    var isLastClause = true;
                    if (root.parent.kind === 126 /* QualifiedName */) {
                        while (root.parent && root.parent.kind === 126 /* QualifiedName */) {
                            root = root.parent;
                        }
                        isLastClause = root.right === node;
                    }
                    return root.parent.kind === 141 /* TypeReference */ && !isLastClause;
                }
                function isInRightSideOfImport(node) {
                    while (node.parent.kind === 126 /* QualifiedName */) {
                        node = node.parent;
                    }
                    return ts.isInternalModuleImportEqualsDeclaration(node.parent) && node.parent.moduleReference === node;
                }
                function getMeaningFromRightHandSideOfImportEquals(node) {
                    ts.Debug.assert(node.kind === 65 /* Identifier */);
                    //     import a = |b|; // Namespace
                    //     import a = |b.c|; // Value, type, namespace
                    //     import a = |b.c|.d; // Namespace
                    if (node.parent.kind === 126 /* QualifiedName */ &&
                        node.parent.right === node &&
                        node.parent.parent.kind === 208 /* ImportEqualsDeclaration */) {
                        return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */;
                    }
                    return 4 /* Namespace */;
                }
                function getMeaningFromLocation(node) {
                    if (node.parent.kind === 214 /* ExportAssignment */) {
                        return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */;
                    }
                    else if (isInRightSideOfImport(node)) {
                        return getMeaningFromRightHandSideOfImportEquals(node);
                    }
                    else if (ts.isDeclarationName(node)) {
                        return getMeaningFromDeclaration(node.parent);
                    }
                    else if (isTypeReference(node)) {
                        return 2 /* Type */;
                    }
                    else if (isNamespaceReference(node)) {
                        return 4 /* Namespace */;
                    }
                    else {
                        return 1 /* Value */;
                    }
                }
                // Signature help
                /**
                 * This is a semantic operation.
                 */
                function getSignatureHelpItems(fileName, position) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    return ts.SignatureHelp.getSignatureHelpItems(program, sourceFile, position, cancellationToken);
                }
                /// Syntactic features
                function getSourceFile(fileName) {
                    return syntaxTreeCache.getCurrentSourceFile(fileName);
                }
                function getNameOrDottedNameSpan(fileName, startPos, endPos) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    // Get node at the location
                    var node = ts.getTouchingPropertyName(sourceFile, startPos);
                    if (!node) {
                        return;
                    }
                    switch (node.kind) {
                        case 155 /* PropertyAccessExpression */:
                        case 126 /* QualifiedName */:
                        case 8 /* StringLiteral */:
                        case 80 /* FalseKeyword */:
                        case 95 /* TrueKeyword */:
                        case 89 /* NullKeyword */:
                        case 91 /* SuperKeyword */:
                        case 93 /* ThisKeyword */:
                        case 65 /* Identifier */:
                            break;
                        // Cant create the text span
                        default:
                            return;
                    }
                    var nodeForStartPos = node;
                    while (true) {
                        if (isRightSideOfPropertyAccess(nodeForStartPos) || isRightSideOfQualifiedName(nodeForStartPos)) {
                            // If on the span is in right side of the the property or qualified name, return the span from the qualified name pos to end of this node
                            nodeForStartPos = nodeForStartPos.parent;
                        }
                        else if (isNameOfModuleDeclaration(nodeForStartPos)) {
                            // If this is name of a module declarations, check if this is right side of dotted module name
                            // If parent of the module declaration which is parent of this node is module declaration and its body is the module declaration that this node is name of 
                            // Then this name is name from dotted module
                            if (nodeForStartPos.parent.parent.kind === 205 /* ModuleDeclaration */ &&
                                nodeForStartPos.parent.parent.body === nodeForStartPos.parent) {
                                // Use parent module declarations name for start pos
                                nodeForStartPos = nodeForStartPos.parent.parent.name;
                            }
                            else {
                                // We have to use this name for start pos
                                break;
                            }
                        }
                        else {
                            // Is not a member expression so we have found the node for start pos
                            break;
                        }
                    }
                    return ts.createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd());
                }
                function getBreakpointStatementAtPosition(fileName, position) {
                    // doesn't use compiler - no need to synchronize with host
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    return ts.BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position);
                }
                function getNavigationBarItems(fileName) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    return ts.NavigationBar.getNavigationBarItems(sourceFile);
                }
                function getSemanticClassifications(fileName, span) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    var typeChecker = program.getTypeChecker();
                    var result = [];
                    processNode(sourceFile);
                    return result;
                    function classifySymbol(symbol, meaningAtPosition) {
                        var flags = symbol.getFlags();
                        if (flags & 32 /* Class */) {
                            return ClassificationTypeNames.className;
                        }
                        else if (flags & 384 /* Enum */) {
                            return ClassificationTypeNames.enumName;
                        }
                        else if (flags & 524288 /* TypeAlias */) {
                            return ClassificationTypeNames.typeAlias;
                        }
                        else if (meaningAtPosition & 2 /* Type */) {
                            if (flags & 64 /* Interface */) {
                                return ClassificationTypeNames.interfaceName;
                            }
                            else if (flags & 262144 /* TypeParameter */) {
                                return ClassificationTypeNames.typeParameterName;
                            }
                        }
                        else if (flags & 1536 /* Module */) {
                            // Only classify a module as such if
                            //  - It appears in a namespace context.
                            //  - There exists a module declaration which actually impacts the value side.
                            if (meaningAtPosition & 4 /* Namespace */ ||
                                (meaningAtPosition & 1 /* Value */ && hasValueSideModule(symbol))) {
                                return ClassificationTypeNames.moduleName;
                            }
                        }
                        return undefined;
                        /**
                         * Returns true if there exists a module that introduces entities on the value side.
                         */
                        function hasValueSideModule(symbol) {
                            return ts.forEach(symbol.declarations, function (declaration) {
                                return declaration.kind === 205 /* ModuleDeclaration */ && ts.getModuleInstanceState(declaration) == 1 /* Instantiated */;
                            });
                        }
                    }
                    function processNode(node) {
                        // Only walk into nodes that intersect the requested span.
                        if (node && ts.textSpanIntersectsWith(span, node.getStart(), node.getWidth())) {
                            if (node.kind === 65 /* Identifier */ && node.getWidth() > 0) {
                                var symbol = typeChecker.getSymbolAtLocation(node);
                                if (symbol) {
                                    var type = classifySymbol(symbol, getMeaningFromLocation(node));
                                    if (type) {
                                        result.push({
                                            textSpan: ts.createTextSpan(node.getStart(), node.getWidth()),
                                            classificationType: type
                                        });
                                    }
                                }
                            }
                            ts.forEachChild(node, processNode);
                        }
                    }
                }
                function getSyntacticClassifications(fileName, span) {
                    // doesn't use compiler - no need to synchronize with host
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    // Make a scanner we can get trivia from.
                    var triviaScanner = ts.createScanner(2 /* Latest */, false, sourceFile.text);
                    var mergeConflictScanner = ts.createScanner(2 /* Latest */, false, sourceFile.text);
                    var result = [];
                    processElement(sourceFile);
                    return result;
                    function classifyLeadingTrivia(token) {
                        var tokenStart = ts.skipTrivia(sourceFile.text, token.pos, false);
                        if (tokenStart === token.pos) {
                            return;
                        }
                        // token has trivia.  Classify them appropriately.
                        triviaScanner.setTextPos(token.pos);
                        while (true) {
                            var start = triviaScanner.getTextPos();
                            var kind = triviaScanner.scan();
                            var end = triviaScanner.getTextPos();
                            var width = end - start;
                            if (ts.textSpanIntersectsWith(span, start, width)) {
                                if (!ts.isTrivia(kind)) {
                                    return;
                                }
                                if (ts.isComment(kind)) {
                                    // Simple comment.  Just add as is.
                                    result.push({
                                        textSpan: ts.createTextSpan(start, width),
                                        classificationType: ClassificationTypeNames.comment
                                    });
                                    continue;
                                }
                                if (kind === 6 /* ConflictMarkerTrivia */) {
                                    var text = sourceFile.text;
                                    var ch = text.charCodeAt(start);
                                    // for the <<<<<<< and >>>>>>> markers, we just add them in as comments
                                    // in the classification stream.
                                    if (ch === 60 /* lessThan */ || ch === 62 /* greaterThan */) {
                                        result.push({
                                            textSpan: ts.createTextSpan(start, width),
                                            classificationType: ClassificationTypeNames.comment
                                        });
                                        continue;
                                    }
                                    // for the ======== add a comment for the first line, and then lex all
                                    // subsequent lines up until the end of the conflict marker.
                                    ts.Debug.assert(ch === 61 /* equals */);
                                    classifyDisabledMergeCode(text, start, end);
                                }
                            }
                        }
                    }
                    function classifyDisabledMergeCode(text, start, end) {
                        // Classify the line that the ======= marker is on as a comment.  Then just lex 
                        // all further tokens and add them to the result.
                        for (var i = start; i < end; i++) {
                            if (ts.isLineBreak(text.charCodeAt(i))) {
                                break;
                            }
                        }
                        result.push({
                            textSpan: ts.createTextSpanFromBounds(start, i),
                            classificationType: ClassificationTypeNames.comment
                        });
                        mergeConflictScanner.setTextPos(i);
                        while (mergeConflictScanner.getTextPos() < end) {
                            classifyDisabledCodeToken();
                        }
                    }
                    function classifyDisabledCodeToken() {
                        var start = mergeConflictScanner.getTextPos();
                        var tokenKind = mergeConflictScanner.scan();
                        var end = mergeConflictScanner.getTextPos();
                        var type = classifyTokenType(tokenKind);
                        if (type) {
                            result.push({
                                textSpan: ts.createTextSpanFromBounds(start, end),
                                classificationType: type
                            });
                        }
                    }
                    function classifyToken(token) {
                        classifyLeadingTrivia(token);
                        if (token.getWidth() > 0) {
                            var type = classifyTokenType(token.kind, token);
                            if (type) {
                                result.push({
                                    textSpan: ts.createTextSpan(token.getStart(), token.getWidth()),
                                    classificationType: type
                                });
                            }
                        }
                    }
                    // for accurate classification, the actual token should be passed in.  however, for 
                    // cases like 'disabled merge code' classification, we just get the token kind and
                    // classify based on that instead.
                    function classifyTokenType(tokenKind, token) {
                        if (ts.isKeyword(tokenKind)) {
                            return ClassificationTypeNames.keyword;
                        }
                        // Special case < and >  If they appear in a generic context they are punctuation,
                        // not operators.
                        if (tokenKind === 24 /* LessThanToken */ || tokenKind === 25 /* GreaterThanToken */) {
                            // If the node owning the token has a type argument list or type parameter list, then
                            // we can effectively assume that a '<' and '>' belong to those lists.
                            if (token && ts.getTypeArgumentOrTypeParameterList(token.parent)) {
                                return ClassificationTypeNames.punctuation;
                            }
                        }
                        if (ts.isPunctuation(tokenKind)) {
                            if (token) {
                                if (tokenKind === 53 /* EqualsToken */) {
                                    // the '=' in a variable declaration is special cased here.
                                    if (token.parent.kind === 198 /* VariableDeclaration */ ||
                                        token.parent.kind === 132 /* PropertyDeclaration */ ||
                                        token.parent.kind === 129 /* Parameter */) {
                                        return ClassificationTypeNames.operator;
                                    }
                                }
                                if (token.parent.kind === 169 /* BinaryExpression */ ||
                                    token.parent.kind === 167 /* PrefixUnaryExpression */ ||
                                    token.parent.kind === 168 /* PostfixUnaryExpression */ ||
                                    token.parent.kind === 170 /* ConditionalExpression */) {
                                    return ClassificationTypeNames.operator;
                                }
                            }
                            return ClassificationTypeNames.punctuation;
                        }
                        else if (tokenKind === 7 /* NumericLiteral */) {
                            return ClassificationTypeNames.numericLiteral;
                        }
                        else if (tokenKind === 8 /* StringLiteral */) {
                            return ClassificationTypeNames.stringLiteral;
                        }
                        else if (tokenKind === 9 /* RegularExpressionLiteral */) {
                            // TODO: we should get another classification type for these literals.
                            return ClassificationTypeNames.stringLiteral;
                        }
                        else if (ts.isTemplateLiteralKind(tokenKind)) {
                            // TODO (drosen): we should *also* get another classification type for these literals.
                            return ClassificationTypeNames.stringLiteral;
                        }
                        else if (tokenKind === 65 /* Identifier */) {
                            if (token) {
                                switch (token.parent.kind) {
                                    case 201 /* ClassDeclaration */:
                                        if (token.parent.name === token) {
                                            return ClassificationTypeNames.className;
                                        }
                                        return;
                                    case 128 /* TypeParameter */:
                                        if (token.parent.name === token) {
                                            return ClassificationTypeNames.typeParameterName;
                                        }
                                        return;
                                    case 202 /* InterfaceDeclaration */:
                                        if (token.parent.name === token) {
                                            return ClassificationTypeNames.interfaceName;
                                        }
                                        return;
                                    case 204 /* EnumDeclaration */:
                                        if (token.parent.name === token) {
                                            return ClassificationTypeNames.enumName;
                                        }
                                        return;
                                    case 205 /* ModuleDeclaration */:
                                        if (token.parent.name === token) {
                                            return ClassificationTypeNames.moduleName;
                                        }
                                        return;
                                }
                            }
                            return ClassificationTypeNames.text;
                        }
                    }
                    function processElement(element) {
                        // Ignore nodes that don't intersect the original span to classify.
                        if (ts.textSpanIntersectsWith(span, element.getFullStart(), element.getFullWidth())) {
                            var children = element.getChildren();
                            for (var _i = 0; _i < children.length; _i++) {
                                var child = children[_i];
                                if (ts.isToken(child)) {
                                    classifyToken(child);
                                }
                                else {
                                    // Recurse into our child nodes.
                                    processElement(child);
                                }
                            }
                        }
                    }
                }
                function getOutliningSpans(fileName) {
                    // doesn't use compiler - no need to synchronize with host
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    return ts.OutliningElementsCollector.collectElements(sourceFile);
                }
                function getBraceMatchingAtPosition(fileName, position) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    var result = [];
                    var token = ts.getTouchingToken(sourceFile, position);
                    if (token.getStart(sourceFile) === position) {
                        var matchKind = getMatchingTokenKind(token);
                        // Ensure that there is a corresponding token to match ours.
                        if (matchKind) {
                            var parentElement = token.parent;
                            var childNodes = parentElement.getChildren(sourceFile);
                            for (var _i = 0; _i < childNodes.length; _i++) {
                                var current = childNodes[_i];
                                if (current.kind === matchKind) {
                                    var range1 = ts.createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile));
                                    var range2 = ts.createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile));
                                    // We want to order the braces when we return the result.
                                    if (range1.start < range2.start) {
                                        result.push(range1, range2);
                                    }
                                    else {
                                        result.push(range2, range1);
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    return result;
                    function getMatchingTokenKind(token) {
                        switch (token.kind) {
                            case 14 /* OpenBraceToken */: return 15 /* CloseBraceToken */;
                            case 16 /* OpenParenToken */: return 17 /* CloseParenToken */;
                            case 18 /* OpenBracketToken */: return 19 /* CloseBracketToken */;
                            case 24 /* LessThanToken */: return 25 /* GreaterThanToken */;
                            case 15 /* CloseBraceToken */: return 14 /* OpenBraceToken */;
                            case 17 /* CloseParenToken */: return 16 /* OpenParenToken */;
                            case 19 /* CloseBracketToken */: return 18 /* OpenBracketToken */;
                            case 25 /* GreaterThanToken */: return 24 /* LessThanToken */;
                        }
                        return undefined;
                    }
                }
                function getIndentationAtPosition(fileName, position, editorOptions) {
                    var start = new Date().getTime();
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start));
                    start = new Date().getTime();
                    var result = ts.formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions);
                    log("getIndentationAtPosition: computeIndentation  : " + (new Date().getTime() - start));
                    return result;
                }
                function getFormattingEditsForRange(fileName, start, end, options) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    return ts.formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options);
                }
                function getFormattingEditsForDocument(fileName, options) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    return ts.formatting.formatDocument(sourceFile, getRuleProvider(options), options);
                }
                function getFormattingEditsAfterKeystroke(fileName, position, key, options) {
                    var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
                    if (key === "}") {
                        return ts.formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options);
                    }
                    else if (key === ";") {
                        return ts.formatting.formatOnSemicolon(position, sourceFile, getRuleProvider(options), options);
                    }
                    else if (key === "\n") {
                        return ts.formatting.formatOnEnter(position, sourceFile, getRuleProvider(options), options);
                    }
                    return [];
                }
                function getTodoComments(fileName, descriptors) {
                    // Note: while getting todo comments seems like a syntactic operation, we actually 
                    // treat it as a semantic operation here.  This is because we expect our host to call
                    // this on every single file.  If we treat this syntactically, then that will cause
                    // us to populate and throw away the tree in our syntax tree cache for each file.  By
                    // treating this as a semantic operation, we can access any tree without throwing 
                    // anything away.
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    cancellationToken.throwIfCancellationRequested();
                    var fileContents = sourceFile.text;
                    var result = [];
                    if (descriptors.length > 0) {
                        var regExp = getTodoCommentsRegExp();
                        var matchArray;
                        while (matchArray = regExp.exec(fileContents)) {
                            cancellationToken.throwIfCancellationRequested();
                            // If we got a match, here is what the match array will look like.  Say the source text is:
                            //
                            //      "    // hack   1"
                            //
                            // The result array with the regexp:    will be:
                            //
                            //      ["// hack   1", "// ", "hack   1", undefined, "hack"]
                            //
                            // Here are the relevant capture groups:
                            //  0) The full match for the entire regexp.
                            //  1) The preamble to the message portion.
                            //  2) The message portion.
                            //  3...N) The descriptor that was matched - by index.  'undefined' for each 
                            //         descriptor that didn't match.  an actual value if it did match.
                            //
                            //  i.e. 'undefined' in position 3 above means TODO(jason) didn't match.
                            //       "hack"      in position 4 means HACK did match.
                            var firstDescriptorCaptureIndex = 3;
                            ts.Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex);
                            var preamble = matchArray[1];
                            var matchPosition = matchArray.index + preamble.length;
                            // OK, we have found a match in the file.  This is only an acceptable match if
                            // it is contained within a comment.
                            var token = ts.getTokenAtPosition(sourceFile, matchPosition);
                            if (!isInsideComment(sourceFile, token, matchPosition)) {
                                continue;
                            }
                            var descriptor = undefined;
                            for (var i = 0, n = descriptors.length; i < n; i++) {
                                if (matchArray[i + firstDescriptorCaptureIndex]) {
                                    descriptor = descriptors[i];
                                }
                            }
                            ts.Debug.assert(descriptor !== undefined);
                            // We don't want to match something like 'TODOBY', so we make sure a non 
                            // letter/digit follows the match.
                            if (isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor.text.length))) {
                                continue;
                            }
                            var message = matchArray[2];
                            result.push({
                                descriptor: descriptor,
                                message: message,
                                position: matchPosition
                            });
                        }
                    }
                    return result;
                    function escapeRegExp(str) {
                        return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
                    }
                    function getTodoCommentsRegExp() {
                        // NOTE: ?:  means 'non-capture group'.  It allows us to have groups without having to
                        // filter them out later in the final result array.
                        // TODO comments can appear in one of the following forms:
                        //
                        //  1)      // TODO     or  /////////// TODO
                        //
                        //  2)      /* TODO     or  /********** TODO
                        //
                        //  3)      /*
                        //           *   TODO
                        //           */
                        //
                        // The following three regexps are used to match the start of the text up to the TODO
                        // comment portion.
                        var singleLineCommentStart = /(?:\/\/+\s*)/.source;
                        var multiLineCommentStart = /(?:\/\*+\s*)/.source;
                        var anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source;
                        // Match any of the above three TODO comment start regexps.
                        // Note that the outermost group *is* a capture group.  We want to capture the preamble
                        // so that we can determine the starting position of the TODO comment match.
                        var preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")";
                        // Takes the descriptors and forms a regexp that matches them as if they were literals.
                        // For example, if the descriptors are "TODO(jason)" and "HACK", then this will be:
                        //
                        //      (?:(TODO\(jason\))|(HACK))
                        //
                        // Note that the outermost group is *not* a capture group, but the innermost groups
                        // *are* capture groups.  By capturing the inner literals we can determine after 
                        // matching which descriptor we are dealing with.
                        var literals = "(?:" + ts.map(descriptors, function (d) { return "(" + escapeRegExp(d.text) + ")"; }).join("|") + ")";
                        // After matching a descriptor literal, the following regexp matches the rest of the 
                        // text up to the end of the line (or */).
                        var endOfLineOrEndOfComment = /(?:$|\*\/)/.source;
                        var messageRemainder = /(?:.*?)/.source;
                        // This is the portion of the match we'll return as part of the TODO comment result. We
                        // match the literal portion up to the end of the line or end of comment.
                        var messagePortion = "(" + literals + messageRemainder + ")";
                        var regExpString = preamble + messagePortion + endOfLineOrEndOfComment;
                        // The final regexp will look like this:
                        // /((?:\/\/+\s*)|(?:\/\*+\s*)|(?:^(?:\s|\*)*))((?:(TODO\(jason\))|(HACK))(?:.*?))(?:$|\*\/)/gim
                        // The flags of the regexp are important here.
                        //  'g' is so that we are doing a global search and can find matches several times
                        //  in the input.
                        //
                        //  'i' is for case insensitivity (We do this to match C# TODO comment code).
                        //
                        //  'm' is so we can find matches in a multi-line input.
                        return new RegExp(regExpString, "gim");
                    }
                    function isLetterOrDigit(char) {
                        return (char >= 97 /* a */ && char <= 122 /* z */) ||
                            (char >= 65 /* A */ && char <= 90 /* Z */) ||
                            (char >= 48 /* _0 */ && char <= 57 /* _9 */);
                    }
                }
                function getRenameInfo(fileName, position) {
                    synchronizeHostData();
                    var sourceFile = getValidSourceFile(fileName);
                    var typeChecker = program.getTypeChecker();
                    var node = ts.getTouchingWord(sourceFile, position);
                    // Can only rename an identifier.
                    if (node && node.kind === 65 /* Identifier */) {
                        var symbol = typeChecker.getSymbolAtLocation(node);
                        // Only allow a symbol to be renamed if it actually has at least one declaration.
                        if (symbol) {
                            var declarations = symbol.getDeclarations();
                            if (declarations && declarations.length > 0) {
                                // Disallow rename for elements that are defined in the standard TypeScript library.
                                var defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings());
                                if (defaultLibFileName) {
                                    for (var _i = 0; _i < declarations.length; _i++) {
                                        var current = declarations[_i];
                                        var sourceFile_2 = current.getSourceFile();
                                        if (sourceFile_2 && getCanonicalFileName(ts.normalizePath(sourceFile_2.fileName)) === getCanonicalFileName(ts.normalizePath(defaultLibFileName))) {
                                            return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library.key));
                                        }
                                    }
                                }
                                var kind = getSymbolKind(symbol, node);
                                if (kind) {
                                    return {
                                        canRename: true,
                                        localizedErrorMessage: undefined,
                                        displayName: symbol.name,
                                        fullDisplayName: typeChecker.getFullyQualifiedName(symbol),
                                        kind: kind,
                                        kindModifiers: getSymbolModifiers(symbol),
                                        triggerSpan: ts.createTextSpan(node.getStart(), node.getWidth())
                                    };
                                }
                            }
                        }
                    }
                    return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_this_element.key));
                    function getRenameInfoError(localizedErrorMessage) {
                        return {
                            canRename: false,
                            localizedErrorMessage: localizedErrorMessage,
                            displayName: undefined,
                            fullDisplayName: undefined,
                            kind: undefined,
                            kindModifiers: undefined,
                            triggerSpan: undefined
                        };
                    }
                }
                return {
                    dispose: dispose,
                    cleanupSemanticCache: cleanupSemanticCache,
                    getSyntacticDiagnostics: getSyntacticDiagnostics,
                    getSemanticDiagnostics: getSemanticDiagnostics,
                    getCompilerOptionsDiagnostics: getCompilerOptionsDiagnostics,
                    getSyntacticClassifications: getSyntacticClassifications,
                    getSemanticClassifications: getSemanticClassifications,
                    getCompletionsAtPosition: getCompletionsAtPosition,
                    getCompletionEntryDetails: getCompletionEntryDetails,
                    getSignatureHelpItems: getSignatureHelpItems,
                    getQuickInfoAtPosition: getQuickInfoAtPosition,
                    getDefinitionAtPosition: getDefinitionAtPosition,
                    getReferencesAtPosition: getReferencesAtPosition,
                    findReferences: findReferences,
                    getOccurrencesAtPosition: getOccurrencesAtPosition,
                    getDocumentHighlights: getDocumentHighlights,
                    getNameOrDottedNameSpan: getNameOrDottedNameSpan,
                    getBreakpointStatementAtPosition: getBreakpointStatementAtPosition,
                    getNavigateToItems: getNavigateToItems,
                    getRenameInfo: getRenameInfo,
                    findRenameLocations: findRenameLocations,
                    getNavigationBarItems: getNavigationBarItems,
                    getOutliningSpans: getOutliningSpans,
                    getTodoComments: getTodoComments,
                    getBraceMatchingAtPosition: getBraceMatchingAtPosition,
                    getIndentationAtPosition: getIndentationAtPosition,
                    getFormattingEditsForRange: getFormattingEditsForRange,
                    getFormattingEditsForDocument: getFormattingEditsForDocument,
                    getFormattingEditsAfterKeystroke: getFormattingEditsAfterKeystroke,
                    getEmitOutput: getEmitOutput,
                    getSourceFile: getSourceFile,
                    getProgram: getProgram
                };
            }
            ts.createLanguageService = createLanguageService;
            /* @internal */
            function getNameTable(sourceFile) {
                if (!sourceFile.nameTable) {
                    initializeNameTable(sourceFile);
                }
                return sourceFile.nameTable;
            }
            ts.getNameTable = getNameTable;
            function initializeNameTable(sourceFile) {
                var nameTable = {};
                walk(sourceFile);
                sourceFile.nameTable = nameTable;
                function walk(node) {
                    switch (node.kind) {
                        case 65 /* Identifier */:
                            nameTable[node.text] = node.text;
                            break;
                        case 8 /* StringLiteral */:
                        case 7 /* NumericLiteral */:
                            // We want to store any numbers/strings if they were a name that could be
                            // related to a declaration.  So, if we have 'import x = require("something")'
                            // then we want 'something' to be in the name table.  Similarly, if we have
                            // "a['propname']" then we want to store "propname" in the name table.
                            if (ts.isDeclarationName(node) ||
                                node.parent.kind === 219 /* ExternalModuleReference */ ||
                                isArgumentOfElementAccessExpression(node)) {
                                nameTable[node.text] = node.text;
                            }
                            break;
                        default:
                            ts.forEachChild(node, walk);
                    }
                }
            }
            function isArgumentOfElementAccessExpression(node) {
                return node &&
                    node.parent &&
                    node.parent.kind === 156 /* ElementAccessExpression */ &&
                    node.parent.argumentExpression === node;
            }
            /// Classifier
            function createClassifier() {
                var scanner = ts.createScanner(2 /* Latest */, false);
                /// We do not have a full parser support to know when we should parse a regex or not
                /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where
                /// we have a series of divide operator. this list allows us to be more accurate by ruling out 
                /// locations where a regexp cannot exist.
                var noRegexTable = [];
                noRegexTable[65 /* Identifier */] = true;
                noRegexTable[8 /* StringLiteral */] = true;
                noRegexTable[7 /* NumericLiteral */] = true;
                noRegexTable[9 /* RegularExpressionLiteral */] = true;
                noRegexTable[93 /* ThisKeyword */] = true;
                noRegexTable[38 /* PlusPlusToken */] = true;
                noRegexTable[39 /* MinusMinusToken */] = true;
                noRegexTable[17 /* CloseParenToken */] = true;
                noRegexTable[19 /* CloseBracketToken */] = true;
                noRegexTable[15 /* CloseBraceToken */] = true;
                noRegexTable[95 /* TrueKeyword */] = true;
                noRegexTable[80 /* FalseKeyword */] = true;
                // Just a stack of TemplateHeads and OpenCurlyBraces, used to perform rudimentary (inexact)
                // classification on template strings. Because of the context free nature of templates,
                // the only precise way to classify a template portion would be by propagating the stack across
                // lines, just as we do with the end-of-line state. However, this is a burden for implementers,
                // and the behavior is entirely subsumed by the syntactic classifier anyway, so we instead
                // flatten any nesting when the template stack is non-empty and encode it in the end-of-line state.
                // Situations in which this fails are
                //  1) When template strings are nested across different lines:
                //          `hello ${ `world
                //          ` }`
                //
                //     Where on the second line, you will get the closing of a template,
                //     a closing curly, and a new template.
                //
                //  2) When substitution expressions have curly braces and the curly brace falls on the next line:
                //          `hello ${ () => {
                //          return "world" } } `
                //
                //     Where on the second line, you will get the 'return' keyword,
                //     a string literal, and a template end consisting of '} } `'.
                var templateStack = [];
                /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */
                function canFollow(keyword1, keyword2) {
                    if (ts.isAccessibilityModifier(keyword1)) {
                        if (keyword2 === 116 /* GetKeyword */ ||
                            keyword2 === 120 /* SetKeyword */ ||
                            keyword2 === 114 /* ConstructorKeyword */ ||
                            keyword2 === 109 /* StaticKeyword */) {
                            // Allow things like "public get", "public constructor" and "public static".  
                            // These are all legal.
                            return true;
                        }
                        // Any other keyword following "public" is actually an identifier an not a real
                        // keyword.
                        return false;
                    }
                    // Assume any other keyword combination is legal.  This can be refined in the future
                    // if there are more cases we want the classifier to be better at.
                    return true;
                }
                // If there is a syntactic classifier ('syntacticClassifierAbsent' is false),
                // we will be more conservative in order to avoid conflicting with the syntactic classifier.
                function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) {
                    var offset = 0;
                    var token = 0 /* Unknown */;
                    var lastNonTriviaToken = 0 /* Unknown */;
                    // Empty out the template stack for reuse.
                    while (templateStack.length > 0) {
                        templateStack.pop();
                    }
                    // If we're in a string literal, then prepend: "\
                    // (and a newline).  That way when we lex we'll think we're still in a string literal.
                    //
                    // If we're in a multiline comment, then prepend: /*
                    // (and a newline).  That way when we lex we'll think we're still in a multiline comment.
                    switch (lexState) {
                        case 3 /* InDoubleQuoteStringLiteral */:
                            text = '"\\\n' + text;
                            offset = 3;
                            break;
                        case 2 /* InSingleQuoteStringLiteral */:
                            text = "'\\\n" + text;
                            offset = 3;
                            break;
                        case 1 /* InMultiLineCommentTrivia */:
                            text = "/*\n" + text;
                            offset = 3;
                            break;
                        case 4 /* InTemplateHeadOrNoSubstitutionTemplate */:
                            text = "`\n" + text;
                            offset = 2;
                            break;
                        case 5 /* InTemplateMiddleOrTail */:
                            text = "}\n" + text;
                            offset = 2;
                        // fallthrough
                        case 6 /* InTemplateSubstitutionPosition */:
                            templateStack.push(11 /* TemplateHead */);
                            break;
                    }
                    scanner.setText(text);
                    var result = {
                        finalLexState: 0 /* Start */,
                        entries: []
                    };
                    // We can run into an unfortunate interaction between the lexical and syntactic classifier
                    // when the user is typing something generic.  Consider the case where the user types:
                    //
                    //      Foo<number
                    //
                    // From the lexical classifier's perspective, 'number' is a keyword, and so the word will
                    // be classified as such.  However, from the syntactic classifier's tree-based perspective
                    // this is simply an expression with the identifier 'number' on the RHS of the less than
                    // token.  So the classification will go back to being an identifier.  The moment the user
                    // types again, number will become a keyword, then an identifier, etc. etc.
                    //
                    // To try to avoid this problem, we avoid classifying contextual keywords as keywords 
                    // when the user is potentially typing something generic.  We just can't do a good enough
                    // job at the lexical level, and so well leave it up to the syntactic classifier to make
                    // the determination.
                    //
                    // In order to determine if the user is potentially typing something generic, we use a 
                    // weak heuristic where we track < and > tokens.  It's a weak heuristic, but should
                    // work well enough in practice.
                    var angleBracketStack = 0;
                    do {
                        token = scanner.scan();
                        if (!ts.isTrivia(token)) {
                            if ((token === 36 /* SlashToken */ || token === 57 /* SlashEqualsToken */) && !noRegexTable[lastNonTriviaToken]) {
                                if (scanner.reScanSlashToken() === 9 /* RegularExpressionLiteral */) {
                                    token = 9 /* RegularExpressionLiteral */;
                                }
                            }
                            else if (lastNonTriviaToken === 20 /* DotToken */ && isKeyword(token)) {
                                token = 65 /* Identifier */;
                            }
                            else if (isKeyword(lastNonTriviaToken) && isKeyword(token) && !canFollow(lastNonTriviaToken, token)) {
                                // We have two keywords in a row.  Only treat the second as a keyword if 
                                // it's a sequence that could legally occur in the language.  Otherwise
                                // treat it as an identifier.  This way, if someone writes "private var"
                                // we recognize that 'var' is actually an identifier here.
                                token = 65 /* Identifier */;
                            }
                            else if (lastNonTriviaToken === 65 /* Identifier */ &&
                                token === 24 /* LessThanToken */) {
                                // Could be the start of something generic.  Keep track of that by bumping 
                                // up the current count of generic contexts we may be in.
                                angleBracketStack++;
                            }
                            else if (token === 25 /* GreaterThanToken */ && angleBracketStack > 0) {
                                // If we think we're currently in something generic, then mark that that
                                // generic entity is complete.
                                angleBracketStack--;
                            }
                            else if (token === 112 /* AnyKeyword */ ||
                                token === 121 /* StringKeyword */ ||
                                token === 119 /* NumberKeyword */ ||
                                token === 113 /* BooleanKeyword */ ||
                                token === 122 /* SymbolKeyword */) {
                                if (angleBracketStack > 0 && !syntacticClassifierAbsent) {
                                    // If it looks like we're could be in something generic, don't classify this 
                                    // as a keyword.  We may just get overwritten by the syntactic classifier,
                                    // causing a noisy experience for the user.
                                    token = 65 /* Identifier */;
                                }
                            }
                            else if (token === 11 /* TemplateHead */) {
                                templateStack.push(token);
                            }
                            else if (token === 14 /* OpenBraceToken */) {
                                // If we don't have anything on the template stack,
                                // then we aren't trying to keep track of a previously scanned template head.
                                if (templateStack.length > 0) {
                                    templateStack.push(token);
                                }
                            }
                            else if (token === 15 /* CloseBraceToken */) {
                                // If we don't have anything on the template stack,
                                // then we aren't trying to keep track of a previously scanned template head.
                                if (templateStack.length > 0) {
                                    var lastTemplateStackToken = ts.lastOrUndefined(templateStack);
                                    if (lastTemplateStackToken === 11 /* TemplateHead */) {
                                        token = scanner.reScanTemplateToken();
                                        // Only pop on a TemplateTail; a TemplateMiddle indicates there is more for us.
                                        if (token === 13 /* TemplateTail */) {
                                            templateStack.pop();
                                        }
                                        else {
                                            ts.Debug.assert(token === 12 /* TemplateMiddle */, "Should have been a template middle. Was " + token);
                                        }
                                    }
                                    else {
                                        ts.Debug.assert(lastTemplateStackToken === 14 /* OpenBraceToken */, "Should have been an open brace. Was: " + token);
                                        templateStack.pop();
                                    }
                                }
                            }
                            lastNonTriviaToken = token;
                        }
                        processToken();
                    } while (token !== 1 /* EndOfFileToken */);
                    return result;
                    function processToken() {
                        var start = scanner.getTokenPos();
                        var end = scanner.getTextPos();
                        addResult(end - start, classFromKind(token));
                        if (end >= text.length) {
                            if (token === 8 /* StringLiteral */) {
                                // Check to see if we finished up on a multiline string literal.
                                var tokenText = scanner.getTokenText();
                                if (scanner.isUnterminated()) {
                                    var lastCharIndex = tokenText.length - 1;
                                    var numBackslashes = 0;
                                    while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === 92 /* backslash */) {
                                        numBackslashes++;
                                    }
                                    // If we have an odd number of backslashes, then the multiline string is unclosed
                                    if (numBackslashes & 1) {
                                        var quoteChar = tokenText.charCodeAt(0);
                                        result.finalLexState = quoteChar === 34 /* doubleQuote */
                                            ? 3 /* InDoubleQuoteStringLiteral */
                                            : 2 /* InSingleQuoteStringLiteral */;
                                    }
                                }
                            }
                            else if (token === 3 /* MultiLineCommentTrivia */) {
                                // Check to see if the multiline comment was unclosed.
                                if (scanner.isUnterminated()) {
                                    result.finalLexState = 1 /* InMultiLineCommentTrivia */;
                                }
                            }
                            else if (ts.isTemplateLiteralKind(token)) {
                                if (scanner.isUnterminated()) {
                                    if (token === 13 /* TemplateTail */) {
                                        result.finalLexState = 5 /* InTemplateMiddleOrTail */;
                                    }
                                    else if (token === 10 /* NoSubstitutionTemplateLiteral */) {
                                        result.finalLexState = 4 /* InTemplateHeadOrNoSubstitutionTemplate */;
                                    }
                                    else {
                                        ts.Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token);
                                    }
                                }
                            }
                            else if (templateStack.length > 0 && ts.lastOrUndefined(templateStack) === 11 /* TemplateHead */) {
                                result.finalLexState = 6 /* InTemplateSubstitutionPosition */;
                            }
                        }
                    }
                    function addResult(length, classification) {
                        if (length > 0) {
                            // If this is the first classification we're adding to the list, then remove any 
                            // offset we have if we were continuing a construct from the previous line.
                            if (result.entries.length === 0) {
                                length -= offset;
                            }
                            result.entries.push({ length: length, classification: classification });
                        }
                    }
                }
                function isBinaryExpressionOperatorToken(token) {
                    switch (token) {
                        case 35 /* AsteriskToken */:
                        case 36 /* SlashToken */:
                        case 37 /* PercentToken */:
                        case 33 /* PlusToken */:
                        case 34 /* MinusToken */:
                        case 40 /* LessThanLessThanToken */:
                        case 41 /* GreaterThanGreaterThanToken */:
                        case 42 /* GreaterThanGreaterThanGreaterThanToken */:
                        case 24 /* LessThanToken */:
                        case 25 /* GreaterThanToken */:
                        case 26 /* LessThanEqualsToken */:
                        case 27 /* GreaterThanEqualsToken */:
                        case 87 /* InstanceOfKeyword */:
                        case 86 /* InKeyword */:
                        case 28 /* EqualsEqualsToken */:
                        case 29 /* ExclamationEqualsToken */:
                        case 30 /* EqualsEqualsEqualsToken */:
                        case 31 /* ExclamationEqualsEqualsToken */:
                        case 43 /* AmpersandToken */:
                        case 45 /* CaretToken */:
                        case 44 /* BarToken */:
                        case 48 /* AmpersandAmpersandToken */:
                        case 49 /* BarBarToken */:
                        case 63 /* BarEqualsToken */:
                        case 62 /* AmpersandEqualsToken */:
                        case 64 /* CaretEqualsToken */:
                        case 59 /* LessThanLessThanEqualsToken */:
                        case 60 /* GreaterThanGreaterThanEqualsToken */:
                        case 61 /* GreaterThanGreaterThanGreaterThanEqualsToken */:
                        case 54 /* PlusEqualsToken */:
                        case 55 /* MinusEqualsToken */:
                        case 56 /* AsteriskEqualsToken */:
                        case 57 /* SlashEqualsToken */:
                        case 58 /* PercentEqualsToken */:
                        case 53 /* EqualsToken */:
                        case 23 /* CommaToken */:
                            return true;
                        default:
                            return false;
                    }
                }
                function isPrefixUnaryExpressionOperatorToken(token) {
                    switch (token) {
                        case 33 /* PlusToken */:
                        case 34 /* MinusToken */:
                        case 47 /* TildeToken */:
                        case 46 /* ExclamationToken */:
                        case 38 /* PlusPlusToken */:
                        case 39 /* MinusMinusToken */:
                            return true;
                        default:
                            return false;
                    }
                }
                function isKeyword(token) {
                    return token >= 66 /* FirstKeyword */ && token <= 125 /* LastKeyword */;
                }
                function classFromKind(token) {
                    if (isKeyword(token)) {
                        return TokenClass.Keyword;
                    }
                    else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) {
                        return TokenClass.Operator;
                    }
                    else if (token >= 14 /* FirstPunctuation */ && token <= 64 /* LastPunctuation */) {
                        return TokenClass.Punctuation;
                    }
                    switch (token) {
                        case 7 /* NumericLiteral */:
                            return TokenClass.NumberLiteral;
                        case 8 /* StringLiteral */:
                            return TokenClass.StringLiteral;
                        case 9 /* RegularExpressionLiteral */:
                            return TokenClass.RegExpLiteral;
                        case 6 /* ConflictMarkerTrivia */:
                        case 3 /* MultiLineCommentTrivia */:
                        case 2 /* SingleLineCommentTrivia */:
                            return TokenClass.Comment;
                        case 5 /* WhitespaceTrivia */:
                        case 4 /* NewLineTrivia */:
                            return TokenClass.Whitespace;
                        case 65 /* Identifier */:
                        default:
                            if (ts.isTemplateLiteralKind(token)) {
                                return TokenClass.StringLiteral;
                            }
                            return TokenClass.Identifier;
                    }
                }
                return { getClassificationsForLine: getClassificationsForLine };
            }
            ts.createClassifier = createClassifier;
            /**
              * Get the path of the default library file (lib.d.ts) as distributed with the typescript
              * node package.
              * The functionality is not supported if the ts module is consumed outside of a node module.
              */
            function getDefaultLibFilePath(options) {
                // Check __dirname is defined and that we are on a node.js system.
                if (typeof __dirname !== "undefined") {
                    return __dirname + ts.directorySeparator + ts.getDefaultLibFileName(options);
                }
                throw new Error("getDefaultLibFilePath is only supported when consumed as a node module. ");
            }
            ts.getDefaultLibFilePath = getDefaultLibFilePath;
            function initializeServices() {
                ts.objectAllocator = {
                    getNodeConstructor: function (kind) {
                        function Node() {
                        }
                        var proto = kind === 227 /* SourceFile */ ? new SourceFileObject() : new NodeObject();
                        proto.kind = kind;
                        proto.pos = 0;
                        proto.end = 0;
                        proto.flags = 0;
                        proto.parent = undefined;
                        Node.prototype = proto;
                        return Node;
                    },
                    getSymbolConstructor: function () { return SymbolObject; },
                    getTypeConstructor: function () { return TypeObject; },
                    getSignatureConstructor: function () { return SignatureObject; }
                };
            }
            initializeServices();
        })(ts || (ts = {}));
        // Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. 
        // See LICENSE.txt in the project root for complete license information.
        /// <reference path='services.ts' />
        /* @internal */
        var ts;
        (function (ts) {
            var BreakpointResolver;
            (function (BreakpointResolver) {
                /**
                 * Get the breakpoint span in given sourceFile
                 */
                function spanInSourceFileAtLocation(sourceFile, position) {
                    // Cannot set breakpoint in dts file
                    if (sourceFile.flags & 2048 /* DeclarationFile */) {
                        return undefined;
                    }
                    var tokenAtLocation = ts.getTokenAtPosition(sourceFile, position);
                    var lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
                    if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart()).line > lineOfPosition) {
                        // Get previous token if the token is returned starts on new line
                        // eg: let x =10; |--- cursor is here
                        //     let y = 10; 
                        // token at position will return let keyword on second line as the token but we would like to use 
                        // token on same line if trailing trivia (comments or white spaces on same line) part of the last token on that line
                        tokenAtLocation = ts.findPrecedingToken(tokenAtLocation.pos, sourceFile);
                        // Its a blank line
                        if (!tokenAtLocation || sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getEnd()).line !== lineOfPosition) {
                            return undefined;
                        }
                    }
                    // Cannot set breakpoint in ambient declarations
                    if (ts.isInAmbientContext(tokenAtLocation)) {
                        return undefined;
                    }
                    // Get the span in the node based on its syntax
                    return spanInNode(tokenAtLocation);
                    function textSpan(startNode, endNode) {
                        return ts.createTextSpanFromBounds(startNode.getStart(), (endNode || startNode).getEnd());
                    }
                    function spanInNodeIfStartsOnSameLine(node, otherwiseOnNode) {
                        if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart()).line) {
                            return spanInNode(node);
                        }
                        return spanInNode(otherwiseOnNode);
                    }
                    function spanInPreviousNode(node) {
                        return spanInNode(ts.findPrecedingToken(node.pos, sourceFile));
                    }
                    function spanInNextNode(node) {
                        return spanInNode(ts.findNextToken(node, node.parent));
                    }
                    function spanInNode(node) {
                        if (node) {
                            if (ts.isExpression(node)) {
                                if (node.parent.kind === 184 /* DoStatement */) {
                                    // Set span as if on while keyword
                                    return spanInPreviousNode(node);
                                }
                                if (node.parent.kind === 186 /* ForStatement */) {
                                    // For now lets set the span on this expression, fix it later
                                    return textSpan(node);
                                }
                                if (node.parent.kind === 169 /* BinaryExpression */ && node.parent.operatorToken.kind === 23 /* CommaToken */) {
                                    // if this is comma expression, the breakpoint is possible in this expression
                                    return textSpan(node);
                                }
                                if (node.parent.kind == 163 /* ArrowFunction */ && node.parent.body == node) {
                                    // If this is body of arrow function, it is allowed to have the breakpoint
                                    return textSpan(node);
                                }
                            }
                            switch (node.kind) {
                                case 180 /* VariableStatement */:
                                    // Span on first variable declaration
                                    return spanInVariableDeclaration(node.declarationList.declarations[0]);
                                case 198 /* VariableDeclaration */:
                                case 132 /* PropertyDeclaration */:
                                case 131 /* PropertySignature */:
                                    return spanInVariableDeclaration(node);
                                case 129 /* Parameter */:
                                    return spanInParameterDeclaration(node);
                                case 200 /* FunctionDeclaration */:
                                case 134 /* MethodDeclaration */:
                                case 133 /* MethodSignature */:
                                case 136 /* GetAccessor */:
                                case 137 /* SetAccessor */:
                                case 135 /* Constructor */:
                                case 162 /* FunctionExpression */:
                                case 163 /* ArrowFunction */:
                                    return spanInFunctionDeclaration(node);
                                case 179 /* Block */:
                                    if (ts.isFunctionBlock(node)) {
                                        return spanInFunctionBlock(node);
                                    }
                                // Fall through
                                case 206 /* ModuleBlock */:
                                    return spanInBlock(node);
                                case 223 /* CatchClause */:
                                    return spanInBlock(node.block);
                                case 182 /* ExpressionStatement */:
                                    // span on the expression
                                    return textSpan(node.expression);
                                case 191 /* ReturnStatement */:
                                    // span on return keyword and expression if present
                                    return textSpan(node.getChildAt(0), node.expression);
                                case 185 /* WhileStatement */:
                                    // Span on while(...)
                                    return textSpan(node, ts.findNextToken(node.expression, node));
                                case 184 /* DoStatement */:
                                    // span in statement of the do statement
                                    return spanInNode(node.statement);
                                case 197 /* DebuggerStatement */:
                                    // span on debugger keyword
                                    return textSpan(node.getChildAt(0));
                                case 183 /* IfStatement */:
                                    // set on if(..) span
                                    return textSpan(node, ts.findNextToken(node.expression, node));
                                case 194 /* LabeledStatement */:
                                    // span in statement
                                    return spanInNode(node.statement);
                                case 190 /* BreakStatement */:
                                case 189 /* ContinueStatement */:
                                    // On break or continue keyword and label if present
                                    return textSpan(node.getChildAt(0), node.label);
                                case 186 /* ForStatement */:
                                    return spanInForStatement(node);
                                case 187 /* ForInStatement */:
                                case 188 /* ForOfStatement */:
                                    // span on for (a in ...)
                                    return textSpan(node, ts.findNextToken(node.expression, node));
                                case 193 /* SwitchStatement */:
                                    // span on switch(...)
                                    return textSpan(node, ts.findNextToken(node.expression, node));
                                case 220 /* CaseClause */:
                                case 221 /* DefaultClause */:
                                    // span in first statement of the clause
                                    return spanInNode(node.statements[0]);
                                case 196 /* TryStatement */:
                                    // span in try block
                                    return spanInBlock(node.tryBlock);
                                case 195 /* ThrowStatement */:
                                    // span in throw ...
                                    return textSpan(node, node.expression);
                                case 214 /* ExportAssignment */:
                                    // span on export = id
                                    return textSpan(node, node.expression);
                                case 208 /* ImportEqualsDeclaration */:
                                    // import statement without including semicolon
                                    return textSpan(node, node.moduleReference);
                                case 209 /* ImportDeclaration */:
                                    // import statement without including semicolon
                                    return textSpan(node, node.moduleSpecifier);
                                case 215 /* ExportDeclaration */:
                                    // import statement without including semicolon
                                    return textSpan(node, node.moduleSpecifier);
                                case 205 /* ModuleDeclaration */:
                                    // span on complete module if it is instantiated
                                    if (ts.getModuleInstanceState(node) !== 1 /* Instantiated */) {
                                        return undefined;
                                    }
                                case 201 /* ClassDeclaration */:
                                case 204 /* EnumDeclaration */:
                                case 226 /* EnumMember */:
                                case 157 /* CallExpression */:
                                case 158 /* NewExpression */:
                                    // span on complete node
                                    return textSpan(node);
                                case 192 /* WithStatement */:
                                    // span in statement
                                    return spanInNode(node.statement);
                                // No breakpoint in interface, type alias
                                case 202 /* InterfaceDeclaration */:
                                case 203 /* TypeAliasDeclaration */:
                                    return undefined;
                                // Tokens:
                                case 22 /* SemicolonToken */:
                                case 1 /* EndOfFileToken */:
                                    return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile));
                                case 23 /* CommaToken */:
                                    return spanInPreviousNode(node);
                                case 14 /* OpenBraceToken */:
                                    return spanInOpenBraceToken(node);
                                case 15 /* CloseBraceToken */:
                                    return spanInCloseBraceToken(node);
                                case 16 /* OpenParenToken */:
                                    return spanInOpenParenToken(node);
                                case 17 /* CloseParenToken */:
                                    return spanInCloseParenToken(node);
                                case 51 /* ColonToken */:
                                    return spanInColonToken(node);
                                case 25 /* GreaterThanToken */:
                                case 24 /* LessThanToken */:
                                    return spanInGreaterThanOrLessThanToken(node);
                                // Keywords:
                                case 100 /* WhileKeyword */:
                                    return spanInWhileKeyword(node);
                                case 76 /* ElseKeyword */:
                                case 68 /* CatchKeyword */:
                                case 81 /* FinallyKeyword */:
                                    return spanInNextNode(node);
                                default:
                                    // If this is name of property assignment, set breakpoint in the initializer
                                    if (node.parent.kind === 224 /* PropertyAssignment */ && node.parent.name === node) {
                                        return spanInNode(node.parent.initializer);
                                    }
                                    // Breakpoint in type assertion goes to its operand
                                    if (node.parent.kind === 160 /* TypeAssertionExpression */ && node.parent.type === node) {
                                        return spanInNode(node.parent.expression);
                                    }
                                    // return type of function go to previous token
                                    if (ts.isFunctionLike(node.parent) && node.parent.type === node) {
                                        return spanInPreviousNode(node);
                                    }
                                    // Default go to parent to set the breakpoint
                                    return spanInNode(node.parent);
                            }
                        }
                        function spanInVariableDeclaration(variableDeclaration) {
                            // If declaration of for in statement, just set the span in parent
                            if (variableDeclaration.parent.parent.kind === 187 /* ForInStatement */ ||
                                variableDeclaration.parent.parent.kind === 188 /* ForOfStatement */) {
                                return spanInNode(variableDeclaration.parent.parent);
                            }
                            var isParentVariableStatement = variableDeclaration.parent.parent.kind === 180 /* VariableStatement */;
                            var isDeclarationOfForStatement = variableDeclaration.parent.parent.kind === 186 /* ForStatement */ && ts.contains(variableDeclaration.parent.parent.initializer.declarations, variableDeclaration);
                            var declarations = isParentVariableStatement
                                ? variableDeclaration.parent.parent.declarationList.declarations
                                : isDeclarationOfForStatement
                                    ? variableDeclaration.parent.parent.initializer.declarations
                                    : undefined;
                            // Breakpoint is possible in variableDeclaration only if there is initialization
                            if (variableDeclaration.initializer || (variableDeclaration.flags & 1 /* Export */)) {
                                if (declarations && declarations[0] === variableDeclaration) {
                                    if (isParentVariableStatement) {
                                        // First declaration - include let keyword
                                        return textSpan(variableDeclaration.parent, variableDeclaration);
                                    }
                                    else {
                                        ts.Debug.assert(isDeclarationOfForStatement);
                                        // Include let keyword from for statement declarations in the span
                                        return textSpan(ts.findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration);
                                    }
                                }
                                else {
                                    // Span only on this declaration
                                    return textSpan(variableDeclaration);
                                }
                            }
                            else if (declarations && declarations[0] !== variableDeclaration) {
                                // If we cant set breakpoint on this declaration, set it on previous one
                                var indexOfCurrentDeclaration = ts.indexOf(declarations, variableDeclaration);
                                return spanInVariableDeclaration(declarations[indexOfCurrentDeclaration - 1]);
                            }
                        }
                        function canHaveSpanInParameterDeclaration(parameter) {
                            // Breakpoint is possible on parameter only if it has initializer, is a rest parameter, or has public or private modifier
                            return !!parameter.initializer || parameter.dotDotDotToken !== undefined ||
                                !!(parameter.flags & 16 /* Public */) || !!(parameter.flags & 32 /* Private */);
                        }
                        function spanInParameterDeclaration(parameter) {
                            if (canHaveSpanInParameterDeclaration(parameter)) {
                                return textSpan(parameter);
                            }
                            else {
                                var functionDeclaration = parameter.parent;
                                var indexOfParameter = ts.indexOf(functionDeclaration.parameters, parameter);
                                if (indexOfParameter) {
                                    // Not a first parameter, go to previous parameter
                                    return spanInParameterDeclaration(functionDeclaration.parameters[indexOfParameter - 1]);
                                }
                                else {
                                    // Set breakpoint in the function declaration body
                                    return spanInNode(functionDeclaration.body);
                                }
                            }
                        }
                        function canFunctionHaveSpanInWholeDeclaration(functionDeclaration) {
                            return !!(functionDeclaration.flags & 1 /* Export */) ||
                                (functionDeclaration.parent.kind === 201 /* ClassDeclaration */ && functionDeclaration.kind !== 135 /* Constructor */);
                        }
                        function spanInFunctionDeclaration(functionDeclaration) {
                            // No breakpoints in the function signature
                            if (!functionDeclaration.body) {
                                return undefined;
                            }
                            if (canFunctionHaveSpanInWholeDeclaration(functionDeclaration)) {
                                // Set the span on whole function declaration
                                return textSpan(functionDeclaration);
                            }
                            // Set span in function body
                            return spanInNode(functionDeclaration.body);
                        }
                        function spanInFunctionBlock(block) {
                            var nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken();
                            if (canFunctionHaveSpanInWholeDeclaration(block.parent)) {
                                return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock);
                            }
                            return spanInNode(nodeForSpanInBlock);
                        }
                        function spanInBlock(block) {
                            switch (block.parent.kind) {
                                case 205 /* ModuleDeclaration */:
                                    if (ts.getModuleInstanceState(block.parent) !== 1 /* Instantiated */) {
                                        return undefined;
                                    }
                                // Set on parent if on same line otherwise on first statement
                                case 185 /* WhileStatement */:
                                case 183 /* IfStatement */:
                                case 187 /* ForInStatement */:
                                case 188 /* ForOfStatement */:
                                    return spanInNodeIfStartsOnSameLine(block.parent, block.statements[0]);
                                // Set span on previous token if it starts on same line otherwise on the first statement of the block
                                case 186 /* ForStatement */:
                                    return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(block.pos, sourceFile, block.parent), block.statements[0]);
                            }
                            // Default action is to set on first statement
                            return spanInNode(block.statements[0]);
                        }
                        function spanInForStatement(forStatement) {
                            if (forStatement.initializer) {
                                if (forStatement.initializer.kind === 199 /* VariableDeclarationList */) {
                                    var variableDeclarationList = forStatement.initializer;
                                    if (variableDeclarationList.declarations.length > 0) {
                                        return spanInNode(variableDeclarationList.declarations[0]);
                                    }
                                }
                                else {
                                    return spanInNode(forStatement.initializer);
                                }
                            }
                            if (forStatement.condition) {
                                return textSpan(forStatement.condition);
                            }
                            if (forStatement.incrementor) {
                                return textSpan(forStatement.incrementor);
                            }
                        }
                        // Tokens:
                        function spanInOpenBraceToken(node) {
                            switch (node.parent.kind) {
                                case 204 /* EnumDeclaration */:
                                    var enumDeclaration = node.parent;
                                    return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), enumDeclaration.members.length ? enumDeclaration.members[0] : enumDeclaration.getLastToken(sourceFile));
                                case 201 /* ClassDeclaration */:
                                    var classDeclaration = node.parent;
                                    return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), classDeclaration.members.length ? classDeclaration.members[0] : classDeclaration.getLastToken(sourceFile));
                                case 207 /* CaseBlock */:
                                    return spanInNodeIfStartsOnSameLine(node.parent.parent, node.parent.clauses[0]);
                            }
                            // Default to parent node
                            return spanInNode(node.parent);
                        }
                        function spanInCloseBraceToken(node) {
                            switch (node.parent.kind) {
                                case 206 /* ModuleBlock */:
                                    // If this is not instantiated module block no bp span
                                    if (ts.getModuleInstanceState(node.parent.parent) !== 1 /* Instantiated */) {
                                        return undefined;
                                    }
                                case 204 /* EnumDeclaration */:
                                case 201 /* ClassDeclaration */:
                                    // Span on close brace token
                                    return textSpan(node);
                                case 179 /* Block */:
                                    if (ts.isFunctionBlock(node.parent)) {
                                        // Span on close brace token
                                        return textSpan(node);
                                    }
                                // fall through.
                                case 223 /* CatchClause */:
                                    return spanInNode(node.parent.statements[node.parent.statements.length - 1]);
                                    ;
                                case 207 /* CaseBlock */:
                                    // breakpoint in last statement of the last clause
                                    var caseBlock = node.parent;
                                    var lastClause = caseBlock.clauses[caseBlock.clauses.length - 1];
                                    if (lastClause) {
                                        return spanInNode(lastClause.statements[lastClause.statements.length - 1]);
                                    }
                                    return undefined;
                                // Default to parent node
                                default:
                                    return spanInNode(node.parent);
                            }
                        }
                        function spanInOpenParenToken(node) {
                            if (node.parent.kind === 184 /* DoStatement */) {
                                // Go to while keyword and do action instead
                                return spanInPreviousNode(node);
                            }
                            // Default to parent node
                            return spanInNode(node.parent);
                        }
                        function spanInCloseParenToken(node) {
                            // Is this close paren token of parameter list, set span in previous token
                            switch (node.parent.kind) {
                                case 162 /* FunctionExpression */:
                                case 200 /* FunctionDeclaration */:
                                case 163 /* ArrowFunction */:
                                case 134 /* MethodDeclaration */:
                                case 133 /* MethodSignature */:
                                case 136 /* GetAccessor */:
                                case 137 /* SetAccessor */:
                                case 135 /* Constructor */:
                                case 185 /* WhileStatement */:
                                case 184 /* DoStatement */:
                                case 186 /* ForStatement */:
                                    return spanInPreviousNode(node);
                                // Default to parent node
                                default:
                                    return spanInNode(node.parent);
                            }
                            // Default to parent node
                            return spanInNode(node.parent);
                        }
                        function spanInColonToken(node) {
                            // Is this : specifying return annotation of the function declaration
                            if (ts.isFunctionLike(node.parent) || node.parent.kind === 224 /* PropertyAssignment */) {
                                return spanInPreviousNode(node);
                            }
                            return spanInNode(node.parent);
                        }
                        function spanInGreaterThanOrLessThanToken(node) {
                            if (node.parent.kind === 160 /* TypeAssertionExpression */) {
                                return spanInNode(node.parent.expression);
                            }
                            return spanInNode(node.parent);
                        }
                        function spanInWhileKeyword(node) {
                            if (node.parent.kind === 184 /* DoStatement */) {
                                // Set span on while expression
                                return textSpan(node, ts.findNextToken(node.parent.expression, node.parent));
                            }
                            // Default to parent node
                            return spanInNode(node.parent);
                        }
                    }
                }
                BreakpointResolver.spanInSourceFileAtLocation = spanInSourceFileAtLocation;
            })(BreakpointResolver = ts.BreakpointResolver || (ts.BreakpointResolver = {}));
        })(ts || (ts = {}));
        //
        // Copyright (c) Microsoft Corporation.  All rights reserved.
        // 
        // Licensed under the Apache License, Version 2.0 (the "License");
        // you may not use this file except in compliance with the License.
        // You may obtain a copy of the License at
        //   http://www.apache.org/licenses/LICENSE-2.0
        //
        // Unless required by applicable law or agreed to in writing, software
        // distributed under the License is distributed on an "AS IS" BASIS,
        // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        // See the License for the specific language governing permissions and
        // limitations under the License.
        //
        /// <reference path='services.ts' />
        /* @internal */
        var debugObjectHost = this;
        /* @internal */
        var ts;
        (function (ts) {
            function logInternalError(logger, err) {
                logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message);
            }
            var ScriptSnapshotShimAdapter = (function () {
                function ScriptSnapshotShimAdapter(scriptSnapshotShim) {
                    this.scriptSnapshotShim = scriptSnapshotShim;
                    this.lineStartPositions = null;
                }
                ScriptSnapshotShimAdapter.prototype.getText = function (start, end) {
                    return this.scriptSnapshotShim.getText(start, end);
                };
                ScriptSnapshotShimAdapter.prototype.getLength = function () {
                    return this.scriptSnapshotShim.getLength();
                };
                ScriptSnapshotShimAdapter.prototype.getChangeRange = function (oldSnapshot) {
                    var oldSnapshotShim = oldSnapshot;
                    var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim);
                    if (encoded == null) {
                        return null;
                    }
                    var decoded = JSON.parse(encoded);
                    return ts.createTextChangeRange(ts.createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength);
                };
                return ScriptSnapshotShimAdapter;
            })();
            var LanguageServiceShimHostAdapter = (function () {
                function LanguageServiceShimHostAdapter(shimHost) {
                    this.shimHost = shimHost;
                }
                LanguageServiceShimHostAdapter.prototype.log = function (s) {
                    this.shimHost.log(s);
                };
                LanguageServiceShimHostAdapter.prototype.trace = function (s) {
                    this.shimHost.trace(s);
                };
                LanguageServiceShimHostAdapter.prototype.error = function (s) {
                    this.shimHost.error(s);
                };
                LanguageServiceShimHostAdapter.prototype.getCompilationSettings = function () {
                    var settingsJson = this.shimHost.getCompilationSettings();
                    if (settingsJson == null || settingsJson == "") {
                        throw Error("LanguageServiceShimHostAdapter.getCompilationSettings: empty compilationSettings");
                        return null;
                    }
                    return JSON.parse(settingsJson);
                };
                LanguageServiceShimHostAdapter.prototype.getScriptFileNames = function () {
                    var encoded = this.shimHost.getScriptFileNames();
                    return this.files = JSON.parse(encoded);
                };
                LanguageServiceShimHostAdapter.prototype.getScriptSnapshot = function (fileName) {
                    // Shim the API changes for 1.5 release. This should be removed once
                    // TypeScript 1.5 has shipped.
                    if (this.files && this.files.indexOf(fileName) < 0) {
                        return undefined;
                    }
                    var scriptSnapshot = this.shimHost.getScriptSnapshot(fileName);
                    return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot);
                };
                LanguageServiceShimHostAdapter.prototype.getScriptVersion = function (fileName) {
                    return this.shimHost.getScriptVersion(fileName);
                };
                LanguageServiceShimHostAdapter.prototype.getLocalizedDiagnosticMessages = function () {
                    var diagnosticMessagesJson = this.shimHost.getLocalizedDiagnosticMessages();
                    if (diagnosticMessagesJson == null || diagnosticMessagesJson == "") {
                        return null;
                    }
                    try {
                        return JSON.parse(diagnosticMessagesJson);
                    }
                    catch (e) {
                        this.log(e.description || "diagnosticMessages.generated.json has invalid JSON format");
                        return null;
                    }
                };
                LanguageServiceShimHostAdapter.prototype.getCancellationToken = function () {
                    return this.shimHost.getCancellationToken();
                };
                LanguageServiceShimHostAdapter.prototype.getCurrentDirectory = function () {
                    return this.shimHost.getCurrentDirectory();
                };
                LanguageServiceShimHostAdapter.prototype.getDefaultLibFileName = function (options) {
                    // Wrap the API changes for 1.5 release. This try/catch
                    // should be removed once TypeScript 1.5 has shipped.
                    try {
                        return this.shimHost.getDefaultLibFileName(JSON.stringify(options));
                    }
                    catch (e) {
                        return "";
                    }
                };
                return LanguageServiceShimHostAdapter;
            })();
            ts.LanguageServiceShimHostAdapter = LanguageServiceShimHostAdapter;
            function simpleForwardCall(logger, actionDescription, action) {
                logger.log(actionDescription);
                var start = Date.now();
                var result = action();
                var end = Date.now();
                logger.log(actionDescription + " completed in " + (end - start) + " msec");
                if (typeof (result) === "string") {
                    var str = result;
                    if (str.length > 128) {
                        str = str.substring(0, 128) + "...";
                    }
                    logger.log("  result.length=" + str.length + ", result='" + JSON.stringify(str) + "'");
                }
                return result;
            }
            function forwardJSONCall(logger, actionDescription, action) {
                try {
                    var result = simpleForwardCall(logger, actionDescription, action);
                    return JSON.stringify({ result: result });
                }
                catch (err) {
                    if (err instanceof ts.OperationCanceledException) {
                        return JSON.stringify({ canceled: true });
                    }
                    logInternalError(logger, err);
                    err.description = actionDescription;
                    return JSON.stringify({ error: err });
                }
            }
            var ShimBase = (function () {
                function ShimBase(factory) {
                    this.factory = factory;
                    factory.registerShim(this);
                }
                ShimBase.prototype.dispose = function (dummy) {
                    this.factory.unregisterShim(this);
                };
                return ShimBase;
            })();
            function realizeDiagnostics(diagnostics, newLine) {
                return diagnostics.map(function (d) { return realizeDiagnostic(d, newLine); });
            }
            ts.realizeDiagnostics = realizeDiagnostics;
            function realizeDiagnostic(diagnostic, newLine) {
                return {
                    message: ts.flattenDiagnosticMessageText(diagnostic.messageText, newLine),
                    start: diagnostic.start,
                    length: diagnostic.length,
                    /// TODO: no need for the tolowerCase call
                    category: ts.DiagnosticCategory[diagnostic.category].toLowerCase(),
                    code: diagnostic.code
                };
            }
            var LanguageServiceShimObject = (function (_super) {
                __extends(LanguageServiceShimObject, _super);
                function LanguageServiceShimObject(factory, host, languageService) {
                    _super.call(this, factory);
                    this.host = host;
                    this.languageService = languageService;
                    this.logger = this.host;
                }
                LanguageServiceShimObject.prototype.forwardJSONCall = function (actionDescription, action) {
                    return forwardJSONCall(this.logger, actionDescription, action);
                };
                /// DISPOSE
                /**
                 * Ensure (almost) deterministic release of internal Javascript resources when
                 * some external native objects holds onto us (e.g. Com/Interop).
                 */
                LanguageServiceShimObject.prototype.dispose = function (dummy) {
                    this.logger.log("dispose()");
                    this.languageService.dispose();
                    this.languageService = null;
                    // force a GC
                    if (debugObjectHost && debugObjectHost.CollectGarbage) {
                        debugObjectHost.CollectGarbage();
                        this.logger.log("CollectGarbage()");
                    }
                    this.logger = null;
                    _super.prototype.dispose.call(this, dummy);
                };
                /// REFRESH
                /**
                 * Update the list of scripts known to the compiler
                 */
                LanguageServiceShimObject.prototype.refresh = function (throwOnError) {
                    this.forwardJSONCall("refresh(" + throwOnError + ")", function () {
                        return null;
                    });
                };
                LanguageServiceShimObject.prototype.cleanupSemanticCache = function () {
                    var _this = this;
                    this.forwardJSONCall("cleanupSemanticCache()", function () {
                        _this.languageService.cleanupSemanticCache();
                        return null;
                    });
                };
                LanguageServiceShimObject.prototype.realizeDiagnostics = function (diagnostics) {
                    var newLine = this.getNewLine();
                    return ts.realizeDiagnostics(diagnostics, newLine);
                };
                LanguageServiceShimObject.prototype.getSyntacticClassifications = function (fileName, start, length) {
                    var _this = this;
                    return this.forwardJSONCall("getSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")", function () {
                        var classifications = _this.languageService.getSyntacticClassifications(fileName, ts.createTextSpan(start, length));
                        return classifications;
                    });
                };
                LanguageServiceShimObject.prototype.getSemanticClassifications = function (fileName, start, length) {
                    var _this = this;
                    return this.forwardJSONCall("getSemanticClassifications('" + fileName + "', " + start + ", " + length + ")", function () {
                        var classifications = _this.languageService.getSemanticClassifications(fileName, ts.createTextSpan(start, length));
                        return classifications;
                    });
                };
                LanguageServiceShimObject.prototype.getNewLine = function () {
                    return this.host.getNewLine ? this.host.getNewLine() : "\r\n";
                };
                LanguageServiceShimObject.prototype.getSyntacticDiagnostics = function (fileName) {
                    var _this = this;
                    return this.forwardJSONCall("getSyntacticDiagnostics('" + fileName + "')", function () {
                        var diagnostics = _this.languageService.getSyntacticDiagnostics(fileName);
                        return _this.realizeDiagnostics(diagnostics);
                    });
                };
                LanguageServiceShimObject.prototype.getSemanticDiagnostics = function (fileName) {
                    var _this = this;
                    return this.forwardJSONCall("getSemanticDiagnostics('" + fileName + "')", function () {
                        var diagnostics = _this.languageService.getSemanticDiagnostics(fileName);
                        return _this.realizeDiagnostics(diagnostics);
                    });
                };
                LanguageServiceShimObject.prototype.getCompilerOptionsDiagnostics = function () {
                    var _this = this;
                    return this.forwardJSONCall("getCompilerOptionsDiagnostics()", function () {
                        var diagnostics = _this.languageService.getCompilerOptionsDiagnostics();
                        return _this.realizeDiagnostics(diagnostics);
                    });
                };
                /// QUICKINFO
                /**
                 * Computes a string representation of the type at the requested position
                 * in the active file.
                 */
                LanguageServiceShimObject.prototype.getQuickInfoAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getQuickInfoAtPosition('" + fileName + "', " + position + ")", function () {
                        var quickInfo = _this.languageService.getQuickInfoAtPosition(fileName, position);
                        return quickInfo;
                    });
                };
                /// NAMEORDOTTEDNAMESPAN
                /**
                 * Computes span information of the name or dotted name at the requested position
                 * in the active file.
                 */
                LanguageServiceShimObject.prototype.getNameOrDottedNameSpan = function (fileName, startPos, endPos) {
                    var _this = this;
                    return this.forwardJSONCall("getNameOrDottedNameSpan('" + fileName + "', " + startPos + ", " + endPos + ")", function () {
                        var spanInfo = _this.languageService.getNameOrDottedNameSpan(fileName, startPos, endPos);
                        return spanInfo;
                    });
                };
                /**
                 * STATEMENTSPAN
                 * Computes span information of statement at the requested position in the active file.
                 */
                LanguageServiceShimObject.prototype.getBreakpointStatementAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getBreakpointStatementAtPosition('" + fileName + "', " + position + ")", function () {
                        var spanInfo = _this.languageService.getBreakpointStatementAtPosition(fileName, position);
                        return spanInfo;
                    });
                };
                /// SIGNATUREHELP
                LanguageServiceShimObject.prototype.getSignatureHelpItems = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getSignatureHelpItems('" + fileName + "', " + position + ")", function () {
                        var signatureInfo = _this.languageService.getSignatureHelpItems(fileName, position);
                        return signatureInfo;
                    });
                };
                /// GOTO DEFINITION
                /**
                 * Computes the definition location and file for the symbol
                 * at the requested position.
                 */
                LanguageServiceShimObject.prototype.getDefinitionAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getDefinitionAtPosition('" + fileName + "', " + position + ")", function () {
                        return _this.languageService.getDefinitionAtPosition(fileName, position);
                    });
                };
                LanguageServiceShimObject.prototype.getRenameInfo = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getRenameInfo('" + fileName + "', " + position + ")", function () {
                        return _this.languageService.getRenameInfo(fileName, position);
                    });
                };
                LanguageServiceShimObject.prototype.findRenameLocations = function (fileName, position, findInStrings, findInComments) {
                    var _this = this;
                    return this.forwardJSONCall("findRenameLocations('" + fileName + "', " + position + ", " + findInStrings + ", " + findInComments + ")", function () {
                        return _this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments);
                    });
                };
                /// GET BRACE MATCHING
                LanguageServiceShimObject.prototype.getBraceMatchingAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getBraceMatchingAtPosition('" + fileName + "', " + position + ")", function () {
                        var textRanges = _this.languageService.getBraceMatchingAtPosition(fileName, position);
                        return textRanges;
                    });
                };
                /// GET SMART INDENT
                LanguageServiceShimObject.prototype.getIndentationAtPosition = function (fileName, position, options /*Services.EditorOptions*/) {
                    var _this = this;
                    return this.forwardJSONCall("getIndentationAtPosition('" + fileName + "', " + position + ")", function () {
                        var localOptions = JSON.parse(options);
                        return _this.languageService.getIndentationAtPosition(fileName, position, localOptions);
                    });
                };
                /// GET REFERENCES
                LanguageServiceShimObject.prototype.getReferencesAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getReferencesAtPosition('" + fileName + "', " + position + ")", function () {
                        return _this.languageService.getReferencesAtPosition(fileName, position);
                    });
                };
                LanguageServiceShimObject.prototype.findReferences = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("findReferences('" + fileName + "', " + position + ")", function () {
                        return _this.languageService.findReferences(fileName, position);
                    });
                };
                LanguageServiceShimObject.prototype.getOccurrencesAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getOccurrencesAtPosition('" + fileName + "', " + position + ")", function () {
                        return _this.languageService.getOccurrencesAtPosition(fileName, position);
                    });
                };
                LanguageServiceShimObject.prototype.getDocumentHighlights = function (fileName, position, filesToSearch) {
                    var _this = this;
                    return this.forwardJSONCall("getDocumentHighlights('" + fileName + "', " + position + ")", function () {
                        return _this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch));
                    });
                };
                /// COMPLETION LISTS
                /**
                 * Get a string based representation of the completions
                 * to provide at the given source position and providing a member completion
                 * list if requested.
                 */
                LanguageServiceShimObject.prototype.getCompletionsAtPosition = function (fileName, position) {
                    var _this = this;
                    return this.forwardJSONCall("getCompletionsAtPosition('" + fileName + "', " + position + ")", function () {
                        var completion = _this.languageService.getCompletionsAtPosition(fileName, position);
                        return completion;
                    });
                };
                /** Get a string based representation of a completion list entry details */
                LanguageServiceShimObject.prototype.getCompletionEntryDetails = function (fileName, position, entryName) {
                    var _this = this;
                    return this.forwardJSONCall("getCompletionEntryDetails('" + fileName + "', " + position + ", " + entryName + ")", function () {
                        var details = _this.languageService.getCompletionEntryDetails(fileName, position, entryName);
                        return details;
                    });
                };
                LanguageServiceShimObject.prototype.getFormattingEditsForRange = function (fileName, start, end, options /*Services.FormatCodeOptions*/) {
                    var _this = this;
                    return this.forwardJSONCall("getFormattingEditsForRange('" + fileName + "', " + start + ", " + end + ")", function () {
                        var localOptions = JSON.parse(options);
                        var edits = _this.languageService.getFormattingEditsForRange(fileName, start, end, localOptions);
                        return edits;
                    });
                };
                LanguageServiceShimObject.prototype.getFormattingEditsForDocument = function (fileName, options /*Services.FormatCodeOptions*/) {
                    var _this = this;
                    return this.forwardJSONCall("getFormattingEditsForDocument('" + fileName + "')", function () {
                        var localOptions = JSON.parse(options);
                        var edits = _this.languageService.getFormattingEditsForDocument(fileName, localOptions);
                        return edits;
                    });
                };
                LanguageServiceShimObject.prototype.getFormattingEditsAfterKeystroke = function (fileName, position, key, options /*Services.FormatCodeOptions*/) {
                    var _this = this;
                    return this.forwardJSONCall("getFormattingEditsAfterKeystroke('" + fileName + "', " + position + ", '" + key + "')", function () {
                        var localOptions = JSON.parse(options);
                        var edits = _this.languageService.getFormattingEditsAfterKeystroke(fileName, position, key, localOptions);
                        return edits;
                    });
                };
                /// NAVIGATE TO
                /** Return a list of symbols that are interesting to navigate to */
                LanguageServiceShimObject.prototype.getNavigateToItems = function (searchValue, maxResultCount) {
                    var _this = this;
                    return this.forwardJSONCall("getNavigateToItems('" + searchValue + "', " + maxResultCount + ")", function () {
                        var items = _this.languageService.getNavigateToItems(searchValue, maxResultCount);
                        return items;
                    });
                };
                LanguageServiceShimObject.prototype.getNavigationBarItems = function (fileName) {
                    var _this = this;
                    return this.forwardJSONCall("getNavigationBarItems('" + fileName + "')", function () {
                        var items = _this.languageService.getNavigationBarItems(fileName);
                        return items;
                    });
                };
                LanguageServiceShimObject.prototype.getOutliningSpans = function (fileName) {
                    var _this = this;
                    return this.forwardJSONCall("getOutliningSpans('" + fileName + "')", function () {
                        var items = _this.languageService.getOutliningSpans(fileName);
                        return items;
                    });
                };
                LanguageServiceShimObject.prototype.getTodoComments = function (fileName, descriptors) {
                    var _this = this;
                    return this.forwardJSONCall("getTodoComments('" + fileName + "')", function () {
                        var items = _this.languageService.getTodoComments(fileName, JSON.parse(descriptors));
                        return items;
                    });
                };
                /// Emit
                LanguageServiceShimObject.prototype.getEmitOutput = function (fileName) {
                    var _this = this;
                    return this.forwardJSONCall("getEmitOutput('" + fileName + "')", function () {
                        var output = _this.languageService.getEmitOutput(fileName);
                        // Shim the API changes for 1.5 release. This should be removed once
                        // TypeScript 1.5 has shipped.
                        output.emitOutputStatus = output.emitSkipped ? 1 : 0;
                        return output;
                    });
                };
                return LanguageServiceShimObject;
            })(ShimBase);
            var ClassifierShimObject = (function (_super) {
                __extends(ClassifierShimObject, _super);
                function ClassifierShimObject(factory) {
                    _super.call(this, factory);
                    this.classifier = ts.createClassifier();
                }
                /// COLORIZATION
                ClassifierShimObject.prototype.getClassificationsForLine = function (text, lexState, classifyKeywordsInGenerics) {
                    var classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics);
                    var items = classification.entries;
                    var result = "";
                    for (var i = 0; i < items.length; i++) {
                        result += items[i].length + "\n";
                        result += items[i].classification + "\n";
                    }
                    result += classification.finalLexState;
                    return result;
                };
                return ClassifierShimObject;
            })(ShimBase);
            var CoreServicesShimObject = (function (_super) {
                __extends(CoreServicesShimObject, _super);
                function CoreServicesShimObject(factory, logger) {
                    _super.call(this, factory);
                    this.logger = logger;
                }
                CoreServicesShimObject.prototype.forwardJSONCall = function (actionDescription, action) {
                    return forwardJSONCall(this.logger, actionDescription, action);
                };
                CoreServicesShimObject.prototype.getPreProcessedFileInfo = function (fileName, sourceTextSnapshot) {
                    return this.forwardJSONCall("getPreProcessedFileInfo('" + fileName + "')", function () {
                        var result = ts.preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()));
                        var convertResult = {
                            referencedFiles: [],
                            importedFiles: [],
                            isLibFile: result.isLibFile
                        };
                        ts.forEach(result.referencedFiles, function (refFile) {
                            convertResult.referencedFiles.push({
                                path: ts.normalizePath(refFile.fileName),
                                position: refFile.pos,
                                length: refFile.end - refFile.pos
                            });
                        });
                        ts.forEach(result.importedFiles, function (importedFile) {
                            convertResult.importedFiles.push({
                                path: ts.normalizeSlashes(importedFile.fileName),
                                position: importedFile.pos,
                                length: importedFile.end - importedFile.pos
                            });
                        });
                        return convertResult;
                    });
                };
                CoreServicesShimObject.prototype.getDefaultCompilationSettings = function () {
                    return this.forwardJSONCall("getDefaultCompilationSettings()", function () {
                        return ts.getDefaultCompilerOptions();
                    });
                };
                return CoreServicesShimObject;
            })(ShimBase);
            var TypeScriptServicesFactory = (function () {
                function TypeScriptServicesFactory() {
                    this._shims = [];
                    this.documentRegistry = ts.createDocumentRegistry();
                }
                /*
                 * Returns script API version.
                 */
                TypeScriptServicesFactory.prototype.getServicesVersion = function () {
                    return ts.servicesVersion;
                };
                TypeScriptServicesFactory.prototype.createLanguageServiceShim = function (host) {
                    try {
                        var hostAdapter = new LanguageServiceShimHostAdapter(host);
                        var languageService = ts.createLanguageService(hostAdapter, this.documentRegistry);
                        return new LanguageServiceShimObject(this, host, languageService);
                    }
                    catch (err) {
                        logInternalError(host, err);
                        throw err;
                    }
                };
                TypeScriptServicesFactory.prototype.createClassifierShim = function (logger) {
                    try {
                        return new ClassifierShimObject(this);
                    }
                    catch (err) {
                        logInternalError(logger, err);
                        throw err;
                    }
                };
                TypeScriptServicesFactory.prototype.createCoreServicesShim = function (logger) {
                    try {
                        return new CoreServicesShimObject(this, logger);
                    }
                    catch (err) {
                        logInternalError(logger, err);
                        throw err;
                    }
                };
                TypeScriptServicesFactory.prototype.close = function () {
                    // Forget all the registered shims
                    this._shims = [];
                    this.documentRegistry = ts.createDocumentRegistry();
                };
                TypeScriptServicesFactory.prototype.registerShim = function (shim) {
                    this._shims.push(shim);
                };
                TypeScriptServicesFactory.prototype.unregisterShim = function (shim) {
                    for (var i = 0, n = this._shims.length; i < n; i++) {
                        if (this._shims[i] === shim) {
                            delete this._shims[i];
                            return;
                        }
                    }
                    throw new Error("Invalid operation");
                };
                return TypeScriptServicesFactory;
            })();
            ts.TypeScriptServicesFactory = TypeScriptServicesFactory;
            if (typeof module !== "undefined" && module.exports) {
                module.exports = ts;
            }
        })(ts || (ts = {}));
        /// TODO: this is used by VS, clean this up on both sides of the interface
        /* @internal */
        var TypeScript;
        (function (TypeScript) {
            var Services;
            (function (Services) {
                Services.TypeScriptServicesFactory = ts.TypeScriptServicesFactory;
            })(Services = TypeScript.Services || (TypeScript.Services = {}));
        })(TypeScript || (TypeScript = {}));
        /* @internal */
        var toolsVersion = "1.4";
        
    • uglify2
      • ast.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        function DEFNODE(type, props, methods, base) {
            if (arguments.length < 4) base = AST_Node;
            if (!props) props = [];
            else props = props.split(/\s+/);
            var self_props = props;
            if (base && base.PROPS)
                props = props.concat(base.PROPS);
            var code = "return function AST_" + type + "(props){ if (props) { ";
            for (var i = props.length; --i >= 0;) {
                code += "this." + props[i] + " = props." + props[i] + ";";
            }
            var proto = base && new base;
            if (proto && proto.initialize || (methods && methods.initialize))
                code += "this.initialize();";
            code += "}}";
            var ctor = new Function(code)();
            if (proto) {
                ctor.prototype = proto;
                ctor.BASE = base;
            }
            if (base) base.SUBCLASSES.push(ctor);
            ctor.prototype.CTOR = ctor;
            ctor.PROPS = props || null;
            ctor.SELF_PROPS = self_props;
            ctor.SUBCLASSES = [];
            if (type) {
                ctor.prototype.TYPE = ctor.TYPE = type;
            }
            if (methods) for (i in methods) if (methods.hasOwnProperty(i)) {
                if (/^\$/.test(i)) {
                    ctor[i.substr(1)] = methods[i];
                } else {
                    ctor.prototype[i] = methods[i];
                }
            }
            ctor.DEFMETHOD = function(name, method) {
                this.prototype[name] = method;
            };
            return ctor;
        };
        
        var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file", {
        }, null);
        
        var AST_Node = DEFNODE("Node", "start end", {
            clone: function() {
                return new this.CTOR(this);
            },
            $documentation: "Base class of all AST nodes",
            $propdoc: {
                start: "[AST_Token] The first token of this node",
                end: "[AST_Token] The last token of this node"
            },
            _walk: function(visitor) {
                return visitor._visit(this);
            },
            walk: function(visitor) {
                return this._walk(visitor); // not sure the indirection will be any help
            }
        }, null);
        
        AST_Node.warn_function = null;
        AST_Node.warn = function(txt, props) {
            if (AST_Node.warn_function)
                AST_Node.warn_function(string_template(txt, props));
        };
        
        /* -----[ statements ]----- */
        
        var AST_Statement = DEFNODE("Statement", null, {
            $documentation: "Base class of all statements",
        });
        
        var AST_Debugger = DEFNODE("Debugger", null, {
            $documentation: "Represents a debugger statement",
        }, AST_Statement);
        
        var AST_Directive = DEFNODE("Directive", "value scope quote", {
            $documentation: "Represents a directive, like \"use strict\";",
            $propdoc: {
                value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
                scope: "[AST_Scope/S] The scope that this directive affects",
                quote: "[string] the original quote character"
            },
        }, AST_Statement);
        
        var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
            $documentation: "A statement consisting of an expression, i.e. a = 1 + 2",
            $propdoc: {
                body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.body._walk(visitor);
                });
            }
        }, AST_Statement);
        
        function walk_body(node, visitor) {
            if (node.body instanceof AST_Statement) {
                node.body._walk(visitor);
            }
            else node.body.forEach(function(stat){
                stat._walk(visitor);
            });
        };
        
        var AST_Block = DEFNODE("Block", "body", {
            $documentation: "A body of statements (usually bracketed)",
            $propdoc: {
                body: "[AST_Statement*] an array of statements"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    walk_body(this, visitor);
                });
            }
        }, AST_Statement);
        
        var AST_BlockStatement = DEFNODE("BlockStatement", null, {
            $documentation: "A block statement",
        }, AST_Block);
        
        var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
            $documentation: "The empty statement (empty block or simply a semicolon)",
            _walk: function(visitor) {
                return visitor._visit(this);
            }
        }, AST_Statement);
        
        var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", {
            $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
            $propdoc: {
                body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.body._walk(visitor);
                });
            }
        }, AST_Statement);
        
        var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
            $documentation: "Statement with a label",
            $propdoc: {
                label: "[AST_Label] a label definition"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.label._walk(visitor);
                    this.body._walk(visitor);
                });
            }
        }, AST_StatementWithBody);
        
        var AST_IterationStatement = DEFNODE("IterationStatement", null, {
            $documentation: "Internal class.  All loops inherit from it."
        }, AST_StatementWithBody);
        
        var AST_DWLoop = DEFNODE("DWLoop", "condition", {
            $documentation: "Base class for do/while statements",
            $propdoc: {
                condition: "[AST_Node] the loop condition.  Should not be instanceof AST_Statement"
            }
        }, AST_IterationStatement);
        
        var AST_Do = DEFNODE("Do", null, {
            $documentation: "A `do` statement",
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.body._walk(visitor);
                    this.condition._walk(visitor);
                });
            }
        }, AST_DWLoop);
        
        var AST_While = DEFNODE("While", null, {
            $documentation: "A `while` statement",
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.condition._walk(visitor);
                    this.body._walk(visitor);
                });
            }
        }, AST_DWLoop);
        
        var AST_For = DEFNODE("For", "init condition step", {
            $documentation: "A `for` statement",
            $propdoc: {
                init: "[AST_Node?] the `for` initialization code, or null if empty",
                condition: "[AST_Node?] the `for` termination clause, or null if empty",
                step: "[AST_Node?] the `for` update clause, or null if empty"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    if (this.init) this.init._walk(visitor);
                    if (this.condition) this.condition._walk(visitor);
                    if (this.step) this.step._walk(visitor);
                    this.body._walk(visitor);
                });
            }
        }, AST_IterationStatement);
        
        var AST_ForIn = DEFNODE("ForIn", "init name object", {
            $documentation: "A `for ... in` statement",
            $propdoc: {
                init: "[AST_Node] the `for/in` initialization code",
                name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
                object: "[AST_Node] the object that we're looping through"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.init._walk(visitor);
                    this.object._walk(visitor);
                    this.body._walk(visitor);
                });
            }
        }, AST_IterationStatement);
        
        var AST_With = DEFNODE("With", "expression", {
            $documentation: "A `with` statement",
            $propdoc: {
                expression: "[AST_Node] the `with` expression"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                    this.body._walk(visitor);
                });
            }
        }, AST_StatementWithBody);
        
        /* -----[ scope and functions ]----- */
        
        var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
            $documentation: "Base class for all statements introducing a lexical scope",
            $propdoc: {
                directives: "[string*/S] an array of directives declared in this scope",
                variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
                functions: "[Object/S] like `variables`, but only lists function declarations",
                uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
                uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
                parent_scope: "[AST_Scope?/S] link to the parent scope",
                enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
                cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
            },
        }, AST_Block);
        
        var AST_Toplevel = DEFNODE("Toplevel", "globals", {
            $documentation: "The toplevel scope",
            $propdoc: {
                globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
            },
            wrap_enclose: function(arg_parameter_pairs) {
                var self = this;
                var args = [];
                var parameters = [];
        
                arg_parameter_pairs.forEach(function(pair) {
                    var splitAt = pair.lastIndexOf(":");
        
                    args.push(pair.substr(0, splitAt));
                    parameters.push(pair.substr(splitAt + 1));
                });
        
                var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";
                wrapped_tl = parse(wrapped_tl);
                wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
                    if (node instanceof AST_Directive && node.value == "$ORIG") {
                        return MAP.splice(self.body);
                    }
                }));
                return wrapped_tl;
            },
            wrap_commonjs: function(name, export_all) {
                var self = this;
                var to_export = [];
                if (export_all) {
                    self.figure_out_scope();
                    self.walk(new TreeWalker(function(node){
                        if (node instanceof AST_SymbolDeclaration && node.definition().global) {
                            if (!find_if(function(n){ return n.name == node.name }, to_export))
                                to_export.push(node);
                        }
                    }));
                }
                var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))";
                wrapped_tl = parse(wrapped_tl);
                wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
                    if (node instanceof AST_SimpleStatement) {
                        node = node.body;
                        if (node instanceof AST_String) switch (node.getValue()) {
                          case "$ORIG":
                            return MAP.splice(self.body);
                          case "$EXPORTS":
                            var body = [];
                            to_export.forEach(function(sym){
                                body.push(new AST_SimpleStatement({
                                    body: new AST_Assign({
                                        left: new AST_Sub({
                                            expression: new AST_SymbolRef({ name: "exports" }),
                                            property: new AST_String({ value: sym.name }),
                                        }),
                                        operator: "=",
                                        right: new AST_SymbolRef(sym),
                                    }),
                                }));
                            });
                            return MAP.splice(body);
                        }
                    }
                }));
                return wrapped_tl;
            }
        }, AST_Scope);
        
        var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
            $documentation: "Base class for functions",
            $propdoc: {
                name: "[AST_SymbolDeclaration?] the name of this function",
                argnames: "[AST_SymbolFunarg*] array of function arguments",
                uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    if (this.name) this.name._walk(visitor);
                    this.argnames.forEach(function(arg){
                        arg._walk(visitor);
                    });
                    walk_body(this, visitor);
                });
            }
        }, AST_Scope);
        
        var AST_Accessor = DEFNODE("Accessor", null, {
            $documentation: "A setter/getter function.  The `name` property is always null."
        }, AST_Lambda);
        
        var AST_Function = DEFNODE("Function", null, {
            $documentation: "A function expression"
        }, AST_Lambda);
        
        var AST_Defun = DEFNODE("Defun", null, {
            $documentation: "A function definition"
        }, AST_Lambda);
        
        /* -----[ JUMPS ]----- */
        
        var AST_Jump = DEFNODE("Jump", null, {
            $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"
        }, AST_Statement);
        
        var AST_Exit = DEFNODE("Exit", "value", {
            $documentation: "Base class for “exits” (`return` and `throw`)",
            $propdoc: {
                value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
            },
            _walk: function(visitor) {
                return visitor._visit(this, this.value && function(){
                    this.value._walk(visitor);
                });
            }
        }, AST_Jump);
        
        var AST_Return = DEFNODE("Return", null, {
            $documentation: "A `return` statement"
        }, AST_Exit);
        
        var AST_Throw = DEFNODE("Throw", null, {
            $documentation: "A `throw` statement"
        }, AST_Exit);
        
        var AST_LoopControl = DEFNODE("LoopControl", "label", {
            $documentation: "Base class for loop control statements (`break` and `continue`)",
            $propdoc: {
                label: "[AST_LabelRef?] the label, or null if none",
            },
            _walk: function(visitor) {
                return visitor._visit(this, this.label && function(){
                    this.label._walk(visitor);
                });
            }
        }, AST_Jump);
        
        var AST_Break = DEFNODE("Break", null, {
            $documentation: "A `break` statement"
        }, AST_LoopControl);
        
        var AST_Continue = DEFNODE("Continue", null, {
            $documentation: "A `continue` statement"
        }, AST_LoopControl);
        
        /* -----[ IF ]----- */
        
        var AST_If = DEFNODE("If", "condition alternative", {
            $documentation: "A `if` statement",
            $propdoc: {
                condition: "[AST_Node] the `if` condition",
                alternative: "[AST_Statement?] the `else` part, or null if not present"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.condition._walk(visitor);
                    this.body._walk(visitor);
                    if (this.alternative) this.alternative._walk(visitor);
                });
            }
        }, AST_StatementWithBody);
        
        /* -----[ SWITCH ]----- */
        
        var AST_Switch = DEFNODE("Switch", "expression", {
            $documentation: "A `switch` statement",
            $propdoc: {
                expression: "[AST_Node] the `switch` “discriminant”"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                    walk_body(this, visitor);
                });
            }
        }, AST_Block);
        
        var AST_SwitchBranch = DEFNODE("SwitchBranch", null, {
            $documentation: "Base class for `switch` branches",
        }, AST_Block);
        
        var AST_Default = DEFNODE("Default", null, {
            $documentation: "A `default` switch branch",
        }, AST_SwitchBranch);
        
        var AST_Case = DEFNODE("Case", "expression", {
            $documentation: "A `case` switch branch",
            $propdoc: {
                expression: "[AST_Node] the `case` expression"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                    walk_body(this, visitor);
                });
            }
        }, AST_SwitchBranch);
        
        /* -----[ EXCEPTIONS ]----- */
        
        var AST_Try = DEFNODE("Try", "bcatch bfinally", {
            $documentation: "A `try` statement",
            $propdoc: {
                bcatch: "[AST_Catch?] the catch block, or null if not present",
                bfinally: "[AST_Finally?] the finally block, or null if not present"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    walk_body(this, visitor);
                    if (this.bcatch) this.bcatch._walk(visitor);
                    if (this.bfinally) this.bfinally._walk(visitor);
                });
            }
        }, AST_Block);
        
        var AST_Catch = DEFNODE("Catch", "argname", {
            $documentation: "A `catch` node; only makes sense as part of a `try` statement",
            $propdoc: {
                argname: "[AST_SymbolCatch] symbol for the exception"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.argname._walk(visitor);
                    walk_body(this, visitor);
                });
            }
        }, AST_Block);
        
        var AST_Finally = DEFNODE("Finally", null, {
            $documentation: "A `finally` node; only makes sense as part of a `try` statement"
        }, AST_Block);
        
        /* -----[ VAR/CONST ]----- */
        
        var AST_Definitions = DEFNODE("Definitions", "definitions", {
            $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
            $propdoc: {
                definitions: "[AST_VarDef*] array of variable definitions"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.definitions.forEach(function(def){
                        def._walk(visitor);
                    });
                });
            }
        }, AST_Statement);
        
        var AST_Var = DEFNODE("Var", null, {
            $documentation: "A `var` statement"
        }, AST_Definitions);
        
        var AST_Const = DEFNODE("Const", null, {
            $documentation: "A `const` statement"
        }, AST_Definitions);
        
        var AST_VarDef = DEFNODE("VarDef", "name value", {
            $documentation: "A variable declaration; only appears in a AST_Definitions node",
            $propdoc: {
                name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
                value: "[AST_Node?] initializer, or null of there's no initializer"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.name._walk(visitor);
                    if (this.value) this.value._walk(visitor);
                });
            }
        });
        
        /* -----[ OTHER ]----- */
        
        var AST_Call = DEFNODE("Call", "expression args", {
            $documentation: "A function call expression",
            $propdoc: {
                expression: "[AST_Node] expression to invoke as function",
                args: "[AST_Node*] array of arguments"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                    this.args.forEach(function(arg){
                        arg._walk(visitor);
                    });
                });
            }
        });
        
        var AST_New = DEFNODE("New", null, {
            $documentation: "An object instantiation.  Derives from a function call since it has exactly the same properties"
        }, AST_Call);
        
        var AST_Seq = DEFNODE("Seq", "car cdr", {
            $documentation: "A sequence expression (two comma-separated expressions)",
            $propdoc: {
                car: "[AST_Node] first element in sequence",
                cdr: "[AST_Node] second element in sequence"
            },
            $cons: function(x, y) {
                var seq = new AST_Seq(x);
                seq.car = x;
                seq.cdr = y;
                return seq;
            },
            $from_array: function(array) {
                if (array.length == 0) return null;
                if (array.length == 1) return array[0].clone();
                var list = null;
                for (var i = array.length; --i >= 0;) {
                    list = AST_Seq.cons(array[i], list);
                }
                var p = list;
                while (p) {
                    if (p.cdr && !p.cdr.cdr) {
                        p.cdr = p.cdr.car;
                        break;
                    }
                    p = p.cdr;
                }
                return list;
            },
            to_array: function() {
                var p = this, a = [];
                while (p) {
                    a.push(p.car);
                    if (p.cdr && !(p.cdr instanceof AST_Seq)) {
                        a.push(p.cdr);
                        break;
                    }
                    p = p.cdr;
                }
                return a;
            },
            add: function(node) {
                var p = this;
                while (p) {
                    if (!(p.cdr instanceof AST_Seq)) {
                        var cell = AST_Seq.cons(p.cdr, node);
                        return p.cdr = cell;
                    }
                    p = p.cdr;
                }
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.car._walk(visitor);
                    if (this.cdr) this.cdr._walk(visitor);
                });
            }
        });
        
        var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
            $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",
            $propdoc: {
                expression: "[AST_Node] the “container” expression",
                property: "[AST_Node|string] the property to access.  For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node"
            }
        });
        
        var AST_Dot = DEFNODE("Dot", null, {
            $documentation: "A dotted property access expression",
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                });
            }
        }, AST_PropAccess);
        
        var AST_Sub = DEFNODE("Sub", null, {
            $documentation: "Index-style property access, i.e. `a[\"foo\"]`",
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                    this.property._walk(visitor);
                });
            }
        }, AST_PropAccess);
        
        var AST_Unary = DEFNODE("Unary", "operator expression", {
            $documentation: "Base class for unary expressions",
            $propdoc: {
                operator: "[string] the operator",
                expression: "[AST_Node] expression that this unary operator applies to"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.expression._walk(visitor);
                });
            }
        });
        
        var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, {
            $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"
        }, AST_Unary);
        
        var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
            $documentation: "Unary postfix expression, i.e. `i++`"
        }, AST_Unary);
        
        var AST_Binary = DEFNODE("Binary", "left operator right", {
            $documentation: "Binary expression, i.e. `a + b`",
            $propdoc: {
                left: "[AST_Node] left-hand side expression",
                operator: "[string] the operator",
                right: "[AST_Node] right-hand side expression"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.left._walk(visitor);
                    this.right._walk(visitor);
                });
            }
        });
        
        var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", {
            $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",
            $propdoc: {
                condition: "[AST_Node]",
                consequent: "[AST_Node]",
                alternative: "[AST_Node]"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.condition._walk(visitor);
                    this.consequent._walk(visitor);
                    this.alternative._walk(visitor);
                });
            }
        });
        
        var AST_Assign = DEFNODE("Assign", null, {
            $documentation: "An assignment expression — `a = b + 5`",
        }, AST_Binary);
        
        /* -----[ LITERALS ]----- */
        
        var AST_Array = DEFNODE("Array", "elements", {
            $documentation: "An array literal",
            $propdoc: {
                elements: "[AST_Node*] array of elements"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.elements.forEach(function(el){
                        el._walk(visitor);
                    });
                });
            }
        });
        
        var AST_Object = DEFNODE("Object", "properties", {
            $documentation: "An object literal",
            $propdoc: {
                properties: "[AST_ObjectProperty*] array of properties"
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.properties.forEach(function(prop){
                        prop._walk(visitor);
                    });
                });
            }
        });
        
        var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
            $documentation: "Base class for literal object properties",
            $propdoc: {
                key: "[string] the property name converted to a string for ObjectKeyVal.  For setters and getters this is an arbitrary AST_Node.",
                value: "[AST_Node] property value.  For setters and getters this is an AST_Function."
            },
            _walk: function(visitor) {
                return visitor._visit(this, function(){
                    this.value._walk(visitor);
                });
            }
        });
        
        var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", {
            $documentation: "A key: value object property",
            $propdoc: {
                quote: "[string] the original quote character"
            }
        }, AST_ObjectProperty);
        
        var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
            $documentation: "An object setter property",
        }, AST_ObjectProperty);
        
        var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
            $documentation: "An object getter property",
        }, AST_ObjectProperty);
        
        var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
            $propdoc: {
                name: "[string] name of this symbol",
                scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
                thedef: "[SymbolDef/S] the definition of this symbol"
            },
            $documentation: "Base class for all symbols",
        });
        
        var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
            $documentation: "The name of a property accessor (setter/getter function)"
        }, AST_Symbol);
        
        var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
            $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
            $propdoc: {
                init: "[AST_Node*/S] array of initializers for this declaration."
            }
        }, AST_Symbol);
        
        var AST_SymbolVar = DEFNODE("SymbolVar", null, {
            $documentation: "Symbol defining a variable",
        }, AST_SymbolDeclaration);
        
        var AST_SymbolConst = DEFNODE("SymbolConst", null, {
            $documentation: "A constant declaration"
        }, AST_SymbolDeclaration);
        
        var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
            $documentation: "Symbol naming a function argument",
        }, AST_SymbolVar);
        
        var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {
            $documentation: "Symbol defining a function",
        }, AST_SymbolDeclaration);
        
        var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
            $documentation: "Symbol naming a function expression",
        }, AST_SymbolDeclaration);
        
        var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
            $documentation: "Symbol naming the exception in catch",
        }, AST_SymbolDeclaration);
        
        var AST_Label = DEFNODE("Label", "references", {
            $documentation: "Symbol naming a label (declaration)",
            $propdoc: {
                references: "[AST_LoopControl*] a list of nodes referring to this label"
            },
            initialize: function() {
                this.references = [];
                this.thedef = this;
            }
        }, AST_Symbol);
        
        var AST_SymbolRef = DEFNODE("SymbolRef", null, {
            $documentation: "Reference to some symbol (not definition/declaration)",
        }, AST_Symbol);
        
        var AST_LabelRef = DEFNODE("LabelRef", null, {
            $documentation: "Reference to a label symbol",
        }, AST_Symbol);
        
        var AST_This = DEFNODE("This", null, {
            $documentation: "The `this` symbol",
        }, AST_Symbol);
        
        var AST_Constant = DEFNODE("Constant", null, {
            $documentation: "Base class for all constants",
            getValue: function() {
                return this.value;
            }
        });
        
        var AST_String = DEFNODE("String", "value quote", {
            $documentation: "A string literal",
            $propdoc: {
                value: "[string] the contents of this string",
                quote: "[string] the original quote character"
            }
        }, AST_Constant);
        
        var AST_Number = DEFNODE("Number", "value", {
            $documentation: "A number literal",
            $propdoc: {
                value: "[number] the numeric value"
            }
        }, AST_Constant);
        
        var AST_RegExp = DEFNODE("RegExp", "value", {
            $documentation: "A regexp literal",
            $propdoc: {
                value: "[RegExp] the actual regexp"
            }
        }, AST_Constant);
        
        var AST_Atom = DEFNODE("Atom", null, {
            $documentation: "Base class for atoms",
        }, AST_Constant);
        
        var AST_Null = DEFNODE("Null", null, {
            $documentation: "The `null` atom",
            value: null
        }, AST_Atom);
        
        var AST_NaN = DEFNODE("NaN", null, {
            $documentation: "The impossible value",
            value: 0/0
        }, AST_Atom);
        
        var AST_Undefined = DEFNODE("Undefined", null, {
            $documentation: "The `undefined` value",
            value: (function(){}())
        }, AST_Atom);
        
        var AST_Hole = DEFNODE("Hole", null, {
            $documentation: "A hole in an array",
            value: (function(){}())
        }, AST_Atom);
        
        var AST_Infinity = DEFNODE("Infinity", null, {
            $documentation: "The `Infinity` value",
            value: 1/0
        }, AST_Atom);
        
        var AST_Boolean = DEFNODE("Boolean", null, {
            $documentation: "Base class for booleans",
        }, AST_Atom);
        
        var AST_False = DEFNODE("False", null, {
            $documentation: "The `false` atom",
            value: false
        }, AST_Boolean);
        
        var AST_True = DEFNODE("True", null, {
            $documentation: "The `true` atom",
            value: true
        }, AST_Boolean);
        
        /* -----[ TreeWalker ]----- */
        
        function TreeWalker(callback) {
            this.visit = callback;
            this.stack = [];
        };
        TreeWalker.prototype = {
            _visit: function(node, descend) {
                this.stack.push(node);
                var ret = this.visit(node, descend ? function(){
                    descend.call(node);
                } : noop);
                if (!ret && descend) {
                    descend.call(node);
                }
                this.stack.pop();
                return ret;
            },
            parent: function(n) {
                return this.stack[this.stack.length - 2 - (n || 0)];
            },
            push: function (node) {
                this.stack.push(node);
            },
            pop: function() {
                return this.stack.pop();
            },
            self: function() {
                return this.stack[this.stack.length - 1];
            },
            find_parent: function(type) {
                var stack = this.stack;
                for (var i = stack.length; --i >= 0;) {
                    var x = stack[i];
                    if (x instanceof type) return x;
                }
            },
            has_directive: function(type) {
                return this.find_parent(AST_Scope).has_directive(type);
            },
            in_boolean_context: function() {
                var stack = this.stack;
                var i = stack.length, self = stack[--i];
                while (i > 0) {
                    var p = stack[--i];
                    if ((p instanceof AST_If           && p.condition === self) ||
                        (p instanceof AST_Conditional  && p.condition === self) ||
                        (p instanceof AST_DWLoop       && p.condition === self) ||
                        (p instanceof AST_For          && p.condition === self) ||
                        (p instanceof AST_UnaryPrefix  && p.operator == "!" && p.expression === self))
                    {
                        return true;
                    }
                    if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")))
                        return false;
                    self = p;
                }
            },
            loopcontrol_target: function(label) {
                var stack = this.stack;
                if (label) for (var i = stack.length; --i >= 0;) {
                    var x = stack[i];
                    if (x instanceof AST_LabeledStatement && x.label.name == label.name) {
                        return x.body;
                    }
                } else for (var i = stack.length; --i >= 0;) {
                    var x = stack[i];
                    if (x instanceof AST_Switch || x instanceof AST_IterationStatement)
                        return x;
                }
            }
        };
        
      • compress.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        function Compressor(options, false_by_default) {
            if (!(this instanceof Compressor))
                return new Compressor(options, false_by_default);
            TreeTransformer.call(this, this.before, this.after);
            this.options = defaults(options, {
                sequences     : !false_by_default,
                properties    : !false_by_default,
                dead_code     : !false_by_default,
                drop_debugger : !false_by_default,
                unsafe        : false,
                unsafe_comps  : false,
                conditionals  : !false_by_default,
                comparisons   : !false_by_default,
                evaluate      : !false_by_default,
                booleans      : !false_by_default,
                loops         : !false_by_default,
                unused        : !false_by_default,
                hoist_funs    : !false_by_default,
                keep_fargs    : false,
                keep_fnames   : false,
                hoist_vars    : false,
                if_return     : !false_by_default,
                join_vars     : !false_by_default,
                cascade       : !false_by_default,
                side_effects  : !false_by_default,
                pure_getters  : false,
                pure_funcs    : null,
                negate_iife   : !false_by_default,
                screw_ie8     : false,
                drop_console  : false,
                angular       : false,
        
                warnings      : true,
                global_defs   : {}
            }, true);
        };
        
        Compressor.prototype = new TreeTransformer;
        merge(Compressor.prototype, {
            option: function(key) { return this.options[key] },
            warn: function() {
                if (this.options.warnings)
                    AST_Node.warn.apply(AST_Node, arguments);
            },
            before: function(node, descend, in_list) {
                if (node._squeezed) return node;
                var was_scope = false;
                if (node instanceof AST_Scope) {
                    node = node.hoist_declarations(this);
                    was_scope = true;
                }
                descend(node, this);
                node = node.optimize(this);
                if (was_scope && node instanceof AST_Scope) {
                    node.drop_unused(this);
                    descend(node, this);
                }
                node._squeezed = true;
                return node;
            }
        });
        
        (function(){
        
            function OPT(node, optimizer) {
                node.DEFMETHOD("optimize", function(compressor){
                    var self = this;
                    if (self._optimized) return self;
                    var opt = optimizer(self, compressor);
                    opt._optimized = true;
                    if (opt === self) return opt;
                    return opt.transform(compressor);
                });
            };
        
            OPT(AST_Node, function(self, compressor){
                return self;
            });
        
            AST_Node.DEFMETHOD("equivalent_to", function(node){
                // XXX: this is a rather expensive way to test two node's equivalence:
                return this.print_to_string() == node.print_to_string();
            });
        
            function make_node(ctor, orig, props) {
                if (!props) props = {};
                if (orig) {
                    if (!props.start) props.start = orig.start;
                    if (!props.end) props.end = orig.end;
                }
                return new ctor(props);
            };
        
            function make_node_from_constant(compressor, val, orig) {
                // XXX: WIP.
                // if (val instanceof AST_Node) return val.transform(new TreeTransformer(null, function(node){
                //     if (node instanceof AST_SymbolRef) {
                //         var scope = compressor.find_parent(AST_Scope);
                //         var def = scope.find_variable(node);
                //         node.thedef = def;
                //         return node;
                //     }
                // })).transform(compressor);
        
                if (val instanceof AST_Node) return val.transform(compressor);
                switch (typeof val) {
                  case "string":
                    return make_node(AST_String, orig, {
                        value: val
                    }).optimize(compressor);
                  case "number":
                    return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, {
                        value: val
                    }).optimize(compressor);
                  case "boolean":
                    return make_node(val ? AST_True : AST_False, orig).optimize(compressor);
                  case "undefined":
                    return make_node(AST_Undefined, orig).optimize(compressor);
                  default:
                    if (val === null) {
                        return make_node(AST_Null, orig, { value: null }).optimize(compressor);
                    }
                    if (val instanceof RegExp) {
                        return make_node(AST_RegExp, orig, { value: val }).optimize(compressor);
                    }
                    throw new Error(string_template("Can't handle constant of type: {type}", {
                        type: typeof val
                    }));
                }
            };
        
            function as_statement_array(thing) {
                if (thing === null) return [];
                if (thing instanceof AST_BlockStatement) return thing.body;
                if (thing instanceof AST_EmptyStatement) return [];
                if (thing instanceof AST_Statement) return [ thing ];
                throw new Error("Can't convert thing to statement array");
            };
        
            function is_empty(thing) {
                if (thing === null) return true;
                if (thing instanceof AST_EmptyStatement) return true;
                if (thing instanceof AST_BlockStatement) return thing.body.length == 0;
                return false;
            };
        
            function loop_body(x) {
                if (x instanceof AST_Switch) return x;
                if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
                    return (x.body instanceof AST_BlockStatement ? x.body : x);
                }
                return x;
            };
        
            function tighten_body(statements, compressor) {
                var CHANGED;
                do {
                    CHANGED = false;
                    if (compressor.option("angular")) {
                        statements = process_for_angular(statements);
                    }
                    statements = eliminate_spurious_blocks(statements);
                    if (compressor.option("dead_code")) {
                        statements = eliminate_dead_code(statements, compressor);
                    }
                    if (compressor.option("if_return")) {
                        statements = handle_if_return(statements, compressor);
                    }
                    if (compressor.option("sequences")) {
                        statements = sequencesize(statements, compressor);
                    }
                    if (compressor.option("join_vars")) {
                        statements = join_consecutive_vars(statements, compressor);
                    }
                } while (CHANGED);
        
                if (compressor.option("negate_iife")) {
                    negate_iifes(statements, compressor);
                }
        
                return statements;
        
                function process_for_angular(statements) {
                    function has_inject(comment) {
                        return /@ngInject/.test(comment.value);
                    }
                    function make_arguments_names_list(func) {
                        return func.argnames.map(function(sym){
                            return make_node(AST_String, sym, { value: sym.name });
                        });
                    }
                    function make_array(orig, elements) {
                        return make_node(AST_Array, orig, { elements: elements });
                    }
                    function make_injector(func, name) {
                        return make_node(AST_SimpleStatement, func, {
                            body: make_node(AST_Assign, func, {
                                operator: "=",
                                left: make_node(AST_Dot, name, {
                                    expression: make_node(AST_SymbolRef, name, name),
                                    property: "$inject"
                                }),
                                right: make_array(func, make_arguments_names_list(func))
                            })
                        });
                    }
                    function check_expression(body) {
                        if (body && body.args) {
                            // if this is a function call check all of arguments passed
                            body.args.forEach(function(argument, index, array) {
                                var comments = argument.start.comments_before;
                                // if the argument is function preceded by @ngInject
                                if (argument instanceof AST_Lambda && comments.length && has_inject(comments[0])) {
                                    // replace the function with an array of names of its parameters and function at the end
                                    array[index] = make_array(argument, make_arguments_names_list(argument).concat(argument));
                                }
                            });
                            // if this is chained call check previous one recursively
                            if (body.expression && body.expression.expression) {
                                check_expression(body.expression.expression);
                            }
                        }
                    }
                    return statements.reduce(function(a, stat){
                        a.push(stat);
        
                        if (stat.body && stat.body.args) {
                            check_expression(stat.body);
                        } else {
                            var token = stat.start;
                            var comments = token.comments_before;
                            if (comments && comments.length > 0) {
                                var last = comments.pop();
                                if (has_inject(last)) {
                                    // case 1: defun
                                    if (stat instanceof AST_Defun) {
                                        a.push(make_injector(stat, stat.name));
                                    }
                                    else if (stat instanceof AST_Definitions) {
                                        stat.definitions.forEach(function(def) {
                                            if (def.value && def.value instanceof AST_Lambda) {
                                                a.push(make_injector(def.value, def.name));
                                            }
                                        });
                                    }
                                    else {
                                        compressor.warn("Unknown statement marked with @ngInject [{file}:{line},{col}]", token);
                                    }
                                }
                            }
                        }
        
                        return a;
                    }, []);
                }
        
                function eliminate_spurious_blocks(statements) {
                    var seen_dirs = [];
                    return statements.reduce(function(a, stat){
                        if (stat instanceof AST_BlockStatement) {
                            CHANGED = true;
                            a.push.apply(a, eliminate_spurious_blocks(stat.body));
                        } else if (stat instanceof AST_EmptyStatement) {
                            CHANGED = true;
                        } else if (stat instanceof AST_Directive) {
                            if (seen_dirs.indexOf(stat.value) < 0) {
                                a.push(stat);
                                seen_dirs.push(stat.value);
                            } else {
                                CHANGED = true;
                            }
                        } else {
                            a.push(stat);
                        }
                        return a;
                    }, []);
                };
        
                function handle_if_return(statements, compressor) {
                    var self = compressor.self();
                    var in_lambda = self instanceof AST_Lambda;
                    var ret = [];
                    loop: for (var i = statements.length; --i >= 0;) {
                        var stat = statements[i];
                        switch (true) {
                          case (in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0):
                            CHANGED = true;
                            // note, ret.length is probably always zero
                            // because we drop unreachable code before this
                            // step.  nevertheless, it's good to check.
                            continue loop;
                          case stat instanceof AST_If:
                            if (stat.body instanceof AST_Return) {
                                //---
                                // pretty silly case, but:
                                // if (foo()) return; return; ==> foo(); return;
                                if (((in_lambda && ret.length == 0)
                                     || (ret[0] instanceof AST_Return && !ret[0].value))
                                    && !stat.body.value && !stat.alternative) {
                                    CHANGED = true;
                                    var cond = make_node(AST_SimpleStatement, stat.condition, {
                                        body: stat.condition
                                    });
                                    ret.unshift(cond);
                                    continue loop;
                                }
                                //---
                                // if (foo()) return x; return y; ==> return foo() ? x : y;
                                if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) {
                                    CHANGED = true;
                                    stat = stat.clone();
                                    stat.alternative = ret[0];
                                    ret[0] = stat.transform(compressor);
                                    continue loop;
                                }
                                //---
                                // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined;
                                if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) {
                                    CHANGED = true;
                                    stat = stat.clone();
                                    stat.alternative = ret[0] || make_node(AST_Return, stat, {
                                        value: make_node(AST_Undefined, stat)
                                    });
                                    ret[0] = stat.transform(compressor);
                                    continue loop;
                                }
                                //---
                                // if (foo()) return; [ else x... ]; y... ==> if (!foo()) { x...; y... }
                                if (!stat.body.value && in_lambda) {
                                    CHANGED = true;
                                    stat = stat.clone();
                                    stat.condition = stat.condition.negate(compressor);
                                    stat.body = make_node(AST_BlockStatement, stat, {
                                        body: as_statement_array(stat.alternative).concat(ret)
                                    });
                                    stat.alternative = null;
                                    ret = [ stat.transform(compressor) ];
                                    continue loop;
                                }
                                //---
                                if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement
                                    && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) {
                                    CHANGED = true;
                                    ret.push(make_node(AST_Return, ret[0], {
                                        value: make_node(AST_Undefined, ret[0])
                                    }).transform(compressor));
                                    ret = as_statement_array(stat.alternative).concat(ret);
                                    ret.unshift(stat);
                                    continue loop;
                                }
                            }
        
                            var ab = aborts(stat.body);
                            var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
                            if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
                                       || (ab instanceof AST_Continue && self === loop_body(lct))
                                       || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
                                if (ab.label) {
                                    remove(ab.label.thedef.references, ab);
                                }
                                CHANGED = true;
                                var body = as_statement_array(stat.body).slice(0, -1);
                                stat = stat.clone();
                                stat.condition = stat.condition.negate(compressor);
                                stat.body = make_node(AST_BlockStatement, stat, {
                                    body: as_statement_array(stat.alternative).concat(ret)
                                });
                                stat.alternative = make_node(AST_BlockStatement, stat, {
                                    body: body
                                });
                                ret = [ stat.transform(compressor) ];
                                continue loop;
                            }
        
                            var ab = aborts(stat.alternative);
                            var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
                            if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
                                       || (ab instanceof AST_Continue && self === loop_body(lct))
                                       || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
                                if (ab.label) {
                                    remove(ab.label.thedef.references, ab);
                                }
                                CHANGED = true;
                                stat = stat.clone();
                                stat.body = make_node(AST_BlockStatement, stat.body, {
                                    body: as_statement_array(stat.body).concat(ret)
                                });
                                stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
                                    body: as_statement_array(stat.alternative).slice(0, -1)
                                });
                                ret = [ stat.transform(compressor) ];
                                continue loop;
                            }
        
                            ret.unshift(stat);
                            break;
                          default:
                            ret.unshift(stat);
                            break;
                        }
                    }
                    return ret;
                };
        
                function eliminate_dead_code(statements, compressor) {
                    var has_quit = false;
                    var orig = statements.length;
                    var self = compressor.self();
                    statements = statements.reduce(function(a, stat){
                        if (has_quit) {
                            extract_declarations_from_unreachable_code(compressor, stat, a);
                        } else {
                            if (stat instanceof AST_LoopControl) {
                                var lct = compressor.loopcontrol_target(stat.label);
                                if ((stat instanceof AST_Break
                                     && lct instanceof AST_BlockStatement
                                     && loop_body(lct) === self) || (stat instanceof AST_Continue
                                                                     && loop_body(lct) === self)) {
                                    if (stat.label) {
                                        remove(stat.label.thedef.references, stat);
                                    }
                                } else {
                                    a.push(stat);
                                }
                            } else {
                                a.push(stat);
                            }
                            if (aborts(stat)) has_quit = true;
                        }
                        return a;
                    }, []);
                    CHANGED = statements.length != orig;
                    return statements;
                };
        
                function sequencesize(statements, compressor) {
                    if (statements.length < 2) return statements;
                    var seq = [], ret = [];
                    function push_seq() {
                        seq = AST_Seq.from_array(seq);
                        if (seq) ret.push(make_node(AST_SimpleStatement, seq, {
                            body: seq
                        }));
                        seq = [];
                    };
                    statements.forEach(function(stat){
                        if (stat instanceof AST_SimpleStatement) seq.push(stat.body);
                        else push_seq(), ret.push(stat);
                    });
                    push_seq();
                    ret = sequencesize_2(ret, compressor);
                    CHANGED = ret.length != statements.length;
                    return ret;
                };
        
                function sequencesize_2(statements, compressor) {
                    function cons_seq(right) {
                        ret.pop();
                        var left = prev.body;
                        if (left instanceof AST_Seq) {
                            left.add(right);
                        } else {
                            left = AST_Seq.cons(left, right);
                        }
                        return left.transform(compressor);
                    };
                    var ret = [], prev = null;
                    statements.forEach(function(stat){
                        if (prev) {
                            if (stat instanceof AST_For) {
                                var opera = {};
                                try {
                                    prev.body.walk(new TreeWalker(function(node){
                                        if (node instanceof AST_Binary && node.operator == "in")
                                            throw opera;
                                    }));
                                    if (stat.init && !(stat.init instanceof AST_Definitions)) {
                                        stat.init = cons_seq(stat.init);
                                    }
                                    else if (!stat.init) {
                                        stat.init = prev.body;
                                        ret.pop();
                                    }
                                } catch(ex) {
                                    if (ex !== opera) throw ex;
                                }
                            }
                            else if (stat instanceof AST_If) {
                                stat.condition = cons_seq(stat.condition);
                            }
                            else if (stat instanceof AST_With) {
                                stat.expression = cons_seq(stat.expression);
                            }
                            else if (stat instanceof AST_Exit && stat.value) {
                                stat.value = cons_seq(stat.value);
                            }
                            else if (stat instanceof AST_Exit) {
                                stat.value = cons_seq(make_node(AST_Undefined, stat));
                            }
                            else if (stat instanceof AST_Switch) {
                                stat.expression = cons_seq(stat.expression);
                            }
                        }
                        ret.push(stat);
                        prev = stat instanceof AST_SimpleStatement ? stat : null;
                    });
                    return ret;
                };
        
                function join_consecutive_vars(statements, compressor) {
                    var prev = null;
                    return statements.reduce(function(a, stat){
                        if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) {
                            prev.definitions = prev.definitions.concat(stat.definitions);
                            CHANGED = true;
                        }
                        else if (stat instanceof AST_For
                                 && prev instanceof AST_Definitions
                                 && (!stat.init || stat.init.TYPE == prev.TYPE)) {
                            CHANGED = true;
                            a.pop();
                            if (stat.init) {
                                stat.init.definitions = prev.definitions.concat(stat.init.definitions);
                            } else {
                                stat.init = prev;
                            }
                            a.push(stat);
                            prev = stat;
                        }
                        else {
                            prev = stat;
                            a.push(stat);
                        }
                        return a;
                    }, []);
                };
        
                function negate_iifes(statements, compressor) {
                    statements.forEach(function(stat){
                        if (stat instanceof AST_SimpleStatement) {
                            stat.body = (function transform(thing) {
                                return thing.transform(new TreeTransformer(function(node){
                                    if (node instanceof AST_Call && node.expression instanceof AST_Function) {
                                        return make_node(AST_UnaryPrefix, node, {
                                            operator: "!",
                                            expression: node
                                        });
                                    }
                                    else if (node instanceof AST_Call) {
                                        node.expression = transform(node.expression);
                                    }
                                    else if (node instanceof AST_Seq) {
                                        node.car = transform(node.car);
                                    }
                                    else if (node instanceof AST_Conditional) {
                                        var expr = transform(node.condition);
                                        if (expr !== node.condition) {
                                            // it has been negated, reverse
                                            node.condition = expr;
                                            var tmp = node.consequent;
                                            node.consequent = node.alternative;
                                            node.alternative = tmp;
                                        }
                                    }
                                    return node;
                                }));
                            })(stat.body);
                        }
                    });
                };
        
            };
        
            function extract_declarations_from_unreachable_code(compressor, stat, target) {
                compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start);
                stat.walk(new TreeWalker(function(node){
                    if (node instanceof AST_Definitions) {
                        compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start);
                        node.remove_initializers();
                        target.push(node);
                        return true;
                    }
                    if (node instanceof AST_Defun) {
                        target.push(node);
                        return true;
                    }
                    if (node instanceof AST_Scope) {
                        return true;
                    }
                }));
            };
        
            /* -----[ boolean/negation helpers ]----- */
        
            // methods to determine whether an expression has a boolean result type
            (function (def){
                var unary_bool = [ "!", "delete" ];
                var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ];
                def(AST_Node, function(){ return false });
                def(AST_UnaryPrefix, function(){
                    return member(this.operator, unary_bool);
                });
                def(AST_Binary, function(){
                    return member(this.operator, binary_bool) ||
                        ( (this.operator == "&&" || this.operator == "||") &&
                          this.left.is_boolean() && this.right.is_boolean() );
                });
                def(AST_Conditional, function(){
                    return this.consequent.is_boolean() && this.alternative.is_boolean();
                });
                def(AST_Assign, function(){
                    return this.operator == "=" && this.right.is_boolean();
                });
                def(AST_Seq, function(){
                    return this.cdr.is_boolean();
                });
                def(AST_True, function(){ return true });
                def(AST_False, function(){ return true });
            })(function(node, func){
                node.DEFMETHOD("is_boolean", func);
            });
        
            // methods to determine if an expression has a string result type
            (function (def){
                def(AST_Node, function(){ return false });
                def(AST_String, function(){ return true });
                def(AST_UnaryPrefix, function(){
                    return this.operator == "typeof";
                });
                def(AST_Binary, function(compressor){
                    return this.operator == "+" &&
                        (this.left.is_string(compressor) || this.right.is_string(compressor));
                });
                def(AST_Assign, function(compressor){
                    return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor);
                });
                def(AST_Seq, function(compressor){
                    return this.cdr.is_string(compressor);
                });
                def(AST_Conditional, function(compressor){
                    return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
                });
                def(AST_Call, function(compressor){
                    return compressor.option("unsafe")
                        && this.expression instanceof AST_SymbolRef
                        && this.expression.name == "String"
                        && this.expression.undeclared();
                });
            })(function(node, func){
                node.DEFMETHOD("is_string", func);
            });
        
            function best_of(ast1, ast2) {
                return ast1.print_to_string().length >
                    ast2.print_to_string().length
                    ? ast2 : ast1;
            };
        
            // methods to evaluate a constant expression
            (function (def){
                // The evaluate method returns an array with one or two
                // elements.  If the node has been successfully reduced to a
                // constant, then the second element tells us the value;
                // otherwise the second element is missing.  The first element
                // of the array is always an AST_Node descendant; if
                // evaluation was successful it's a node that represents the
                // constant; otherwise it's the original or a replacement node.
                AST_Node.DEFMETHOD("evaluate", function(compressor){
                    if (!compressor.option("evaluate")) return [ this ];
                    try {
                        var val = this._eval(compressor);
                        return [ best_of(make_node_from_constant(compressor, val, this), this), val ];
                    } catch(ex) {
                        if (ex !== def) throw ex;
                        return [ this ];
                    }
                });
                def(AST_Statement, function(){
                    throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
                });
                def(AST_Function, function(){
                    // XXX: AST_Function inherits from AST_Scope, which itself
                    // inherits from AST_Statement; however, an AST_Function
                    // isn't really a statement.  This could byte in other
                    // places too. :-( Wish JS had multiple inheritance.
                    throw def;
                });
                function ev(node, compressor) {
                    if (!compressor) throw new Error("Compressor must be passed");
        
                    return node._eval(compressor);
                };
                def(AST_Node, function(){
                    throw def;          // not constant
                });
                def(AST_Constant, function(){
                    return this.getValue();
                });
                def(AST_UnaryPrefix, function(compressor){
                    var e = this.expression;
                    switch (this.operator) {
                      case "!": return !ev(e, compressor);
                      case "typeof":
                        // Function would be evaluated to an array and so typeof would
                        // incorrectly return 'object'. Hence making is a special case.
                        if (e instanceof AST_Function) return typeof function(){};
        
                        e = ev(e, compressor);
        
                        // typeof <RegExp> returns "object" or "function" on different platforms
                        // so cannot evaluate reliably
                        if (e instanceof RegExp) throw def;
        
                        return typeof e;
                      case "void": return void ev(e, compressor);
                      case "~": return ~ev(e, compressor);
                      case "-":
                        e = ev(e, compressor);
                        if (e === 0) throw def;
                        return -e;
                      case "+": return +ev(e, compressor);
                    }
                    throw def;
                });
                def(AST_Binary, function(c){
                    var left = this.left, right = this.right;
                    switch (this.operator) {
                      case "&&"         : return ev(left, c) &&         ev(right, c);
                      case "||"         : return ev(left, c) ||         ev(right, c);
                      case "|"          : return ev(left, c) |          ev(right, c);
                      case "&"          : return ev(left, c) &          ev(right, c);
                      case "^"          : return ev(left, c) ^          ev(right, c);
                      case "+"          : return ev(left, c) +          ev(right, c);
                      case "*"          : return ev(left, c) *          ev(right, c);
                      case "/"          : return ev(left, c) /          ev(right, c);
                      case "%"          : return ev(left, c) %          ev(right, c);
                      case "-"          : return ev(left, c) -          ev(right, c);
                      case "<<"         : return ev(left, c) <<         ev(right, c);
                      case ">>"         : return ev(left, c) >>         ev(right, c);
                      case ">>>"        : return ev(left, c) >>>        ev(right, c);
                      case "=="         : return ev(left, c) ==         ev(right, c);
                      case "==="        : return ev(left, c) ===        ev(right, c);
                      case "!="         : return ev(left, c) !=         ev(right, c);
                      case "!=="        : return ev(left, c) !==        ev(right, c);
                      case "<"          : return ev(left, c) <          ev(right, c);
                      case "<="         : return ev(left, c) <=         ev(right, c);
                      case ">"          : return ev(left, c) >          ev(right, c);
                      case ">="         : return ev(left, c) >=         ev(right, c);
                      case "in"         : return ev(left, c) in         ev(right, c);
                      case "instanceof" : return ev(left, c) instanceof ev(right, c);
                    }
                    throw def;
                });
                def(AST_Conditional, function(compressor){
                    return ev(this.condition, compressor)
                        ? ev(this.consequent, compressor)
                        : ev(this.alternative, compressor);
                });
                def(AST_SymbolRef, function(compressor){
                    var d = this.definition();
                    if (d && d.constant && d.init) return ev(d.init, compressor);
                    throw def;
                });
                def(AST_Dot, function(compressor){
                    if (compressor.option("unsafe") && this.property == "length") {
                        var str = ev(this.expression, compressor);
                        if (typeof str == "string")
                            return str.length;
                    }
                    throw def;
                });
            })(function(node, func){
                node.DEFMETHOD("_eval", func);
            });
        
            // method to negate an expression
            (function(def){
                function basic_negation(exp) {
                    return make_node(AST_UnaryPrefix, exp, {
                        operator: "!",
                        expression: exp
                    });
                };
                def(AST_Node, function(){
                    return basic_negation(this);
                });
                def(AST_Statement, function(){
                    throw new Error("Cannot negate a statement");
                });
                def(AST_Function, function(){
                    return basic_negation(this);
                });
                def(AST_UnaryPrefix, function(){
                    if (this.operator == "!")
                        return this.expression;
                    return basic_negation(this);
                });
                def(AST_Seq, function(compressor){
                    var self = this.clone();
                    self.cdr = self.cdr.negate(compressor);
                    return self;
                });
                def(AST_Conditional, function(compressor){
                    var self = this.clone();
                    self.consequent = self.consequent.negate(compressor);
                    self.alternative = self.alternative.negate(compressor);
                    return best_of(basic_negation(this), self);
                });
                def(AST_Binary, function(compressor){
                    var self = this.clone(), op = this.operator;
                    if (compressor.option("unsafe_comps")) {
                        switch (op) {
                          case "<=" : self.operator = ">"  ; return self;
                          case "<"  : self.operator = ">=" ; return self;
                          case ">=" : self.operator = "<"  ; return self;
                          case ">"  : self.operator = "<=" ; return self;
                        }
                    }
                    switch (op) {
                      case "==" : self.operator = "!="; return self;
                      case "!=" : self.operator = "=="; return self;
                      case "===": self.operator = "!=="; return self;
                      case "!==": self.operator = "==="; return self;
                      case "&&":
                        self.operator = "||";
                        self.left = self.left.negate(compressor);
                        self.right = self.right.negate(compressor);
                        return best_of(basic_negation(this), self);
                      case "||":
                        self.operator = "&&";
                        self.left = self.left.negate(compressor);
                        self.right = self.right.negate(compressor);
                        return best_of(basic_negation(this), self);
                    }
                    return basic_negation(this);
                });
            })(function(node, func){
                node.DEFMETHOD("negate", function(compressor){
                    return func.call(this, compressor);
                });
            });
        
            // determine if expression has side effects
            (function(def){
                def(AST_Node, function(compressor){ return true });
        
                def(AST_EmptyStatement, function(compressor){ return false });
                def(AST_Constant, function(compressor){ return false });
                def(AST_This, function(compressor){ return false });
        
                def(AST_Call, function(compressor){
                    var pure = compressor.option("pure_funcs");
                    if (!pure) return true;
                    return pure.indexOf(this.expression.print_to_string()) < 0;
                });
        
                def(AST_Block, function(compressor){
                    for (var i = this.body.length; --i >= 0;) {
                        if (this.body[i].has_side_effects(compressor))
                            return true;
                    }
                    return false;
                });
        
                def(AST_SimpleStatement, function(compressor){
                    return this.body.has_side_effects(compressor);
                });
                def(AST_Defun, function(compressor){ return true });
                def(AST_Function, function(compressor){ return false });
                def(AST_Binary, function(compressor){
                    return this.left.has_side_effects(compressor)
                        || this.right.has_side_effects(compressor);
                });
                def(AST_Assign, function(compressor){ return true });
                def(AST_Conditional, function(compressor){
                    return this.condition.has_side_effects(compressor)
                        || this.consequent.has_side_effects(compressor)
                        || this.alternative.has_side_effects(compressor);
                });
                def(AST_Unary, function(compressor){
                    return this.operator == "delete"
                        || this.operator == "++"
                        || this.operator == "--"
                        || this.expression.has_side_effects(compressor);
                });
                def(AST_SymbolRef, function(compressor){
                    return this.global() && this.undeclared();
                });
                def(AST_Object, function(compressor){
                    for (var i = this.properties.length; --i >= 0;)
                        if (this.properties[i].has_side_effects(compressor))
                            return true;
                    return false;
                });
                def(AST_ObjectProperty, function(compressor){
                    return this.value.has_side_effects(compressor);
                });
                def(AST_Array, function(compressor){
                    for (var i = this.elements.length; --i >= 0;)
                        if (this.elements[i].has_side_effects(compressor))
                            return true;
                    return false;
                });
                def(AST_Dot, function(compressor){
                    if (!compressor.option("pure_getters")) return true;
                    return this.expression.has_side_effects(compressor);
                });
                def(AST_Sub, function(compressor){
                    if (!compressor.option("pure_getters")) return true;
                    return this.expression.has_side_effects(compressor)
                        || this.property.has_side_effects(compressor);
                });
                def(AST_PropAccess, function(compressor){
                    return !compressor.option("pure_getters");
                });
                def(AST_Seq, function(compressor){
                    return this.car.has_side_effects(compressor)
                        || this.cdr.has_side_effects(compressor);
                });
            })(function(node, func){
                node.DEFMETHOD("has_side_effects", func);
            });
        
            // tell me if a statement aborts
            function aborts(thing) {
                return thing && thing.aborts();
            };
            (function(def){
                def(AST_Statement, function(){ return null });
                def(AST_Jump, function(){ return this });
                function block_aborts(){
                    var n = this.body.length;
                    return n > 0 && aborts(this.body[n - 1]);
                };
                def(AST_BlockStatement, block_aborts);
                def(AST_SwitchBranch, block_aborts);
                def(AST_If, function(){
                    return this.alternative && aborts(this.body) && aborts(this.alternative) && this;
                });
            })(function(node, func){
                node.DEFMETHOD("aborts", func);
            });
        
            /* -----[ optimizers ]----- */
        
            OPT(AST_Directive, function(self, compressor){
                if (self.scope.has_directive(self.value) !== self.scope) {
                    return make_node(AST_EmptyStatement, self);
                }
                return self;
            });
        
            OPT(AST_Debugger, function(self, compressor){
                if (compressor.option("drop_debugger"))
                    return make_node(AST_EmptyStatement, self);
                return self;
            });
        
            OPT(AST_LabeledStatement, function(self, compressor){
                if (self.body instanceof AST_Break
                    && compressor.loopcontrol_target(self.body.label) === self.body) {
                    return make_node(AST_EmptyStatement, self);
                }
                return self.label.references.length == 0 ? self.body : self;
            });
        
            OPT(AST_Block, function(self, compressor){
                self.body = tighten_body(self.body, compressor);
                return self;
            });
        
            OPT(AST_BlockStatement, function(self, compressor){
                self.body = tighten_body(self.body, compressor);
                switch (self.body.length) {
                  case 1: return self.body[0];
                  case 0: return make_node(AST_EmptyStatement, self);
                }
                return self;
            });
        
            AST_Scope.DEFMETHOD("drop_unused", function(compressor){
                var self = this;
                if (compressor.option("unused")
                    && !(self instanceof AST_Toplevel)
                    && !self.uses_eval
                   ) {
                    var in_use = [];
                    var initializations = new Dictionary();
                    // pass 1: find out which symbols are directly used in
                    // this scope (not in nested scopes).
                    var scope = this;
                    var tw = new TreeWalker(function(node, descend){
                        if (node !== self) {
                            if (node instanceof AST_Defun) {
                                initializations.add(node.name.name, node);
                                return true; // don't go in nested scopes
                            }
                            if (node instanceof AST_Definitions && scope === self) {
                                node.definitions.forEach(function(def){
                                    if (def.value) {
                                        initializations.add(def.name.name, def.value);
                                        if (def.value.has_side_effects(compressor)) {
                                            def.value.walk(tw);
                                        }
                                    }
                                });
                                return true;
                            }
                            if (node instanceof AST_SymbolRef) {
                                push_uniq(in_use, node.definition());
                                return true;
                            }
                            if (node instanceof AST_Scope) {
                                var save_scope = scope;
                                scope = node;
                                descend();
                                scope = save_scope;
                                return true;
                            }
                        }
                    });
                    self.walk(tw);
                    // pass 2: for every used symbol we need to walk its
                    // initialization code to figure out if it uses other
                    // symbols (that may not be in_use).
                    for (var i = 0; i < in_use.length; ++i) {
                        in_use[i].orig.forEach(function(decl){
                            // undeclared globals will be instanceof AST_SymbolRef
                            var init = initializations.get(decl.name);
                            if (init) init.forEach(function(init){
                                var tw = new TreeWalker(function(node){
                                    if (node instanceof AST_SymbolRef) {
                                        push_uniq(in_use, node.definition());
                                    }
                                });
                                init.walk(tw);
                            });
                        });
                    }
                    // pass 3: we should drop declarations not in_use
                    var tt = new TreeTransformer(
                        function before(node, descend, in_list) {
                            if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
                                if (!compressor.option("keep_fargs")) {
                                    for (var a = node.argnames, i = a.length; --i >= 0;) {
                                        var sym = a[i];
                                        if (sym.unreferenced()) {
                                            a.pop();
                                            compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", {
                                                name : sym.name,
                                                file : sym.start.file,
                                                line : sym.start.line,
                                                col  : sym.start.col
                                            });
                                        }
                                        else break;
                                    }
                                }
                            }
                            if (node instanceof AST_Defun && node !== self) {
                                if (!member(node.name.definition(), in_use)) {
                                    compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", {
                                        name : node.name.name,
                                        file : node.name.start.file,
                                        line : node.name.start.line,
                                        col  : node.name.start.col
                                    });
                                    return make_node(AST_EmptyStatement, node);
                                }
                                return node;
                            }
                            if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) {
                                var def = node.definitions.filter(function(def){
                                    if (member(def.name.definition(), in_use)) return true;
                                    var w = {
                                        name : def.name.name,
                                        file : def.name.start.file,
                                        line : def.name.start.line,
                                        col  : def.name.start.col
                                    };
                                    if (def.value && def.value.has_side_effects(compressor)) {
                                        def._unused_side_effects = true;
                                        compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w);
                                        return true;
                                    }
                                    compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w);
                                    return false;
                                });
                                // place uninitialized names at the start
                                def = mergeSort(def, function(a, b){
                                    if (!a.value && b.value) return -1;
                                    if (!b.value && a.value) return 1;
                                    return 0;
                                });
                                // for unused names whose initialization has
                                // side effects, we can cascade the init. code
                                // into the next one, or next statement.
                                var side_effects = [];
                                for (var i = 0; i < def.length;) {
                                    var x = def[i];
                                    if (x._unused_side_effects) {
                                        side_effects.push(x.value);
                                        def.splice(i, 1);
                                    } else {
                                        if (side_effects.length > 0) {
                                            side_effects.push(x.value);
                                            x.value = AST_Seq.from_array(side_effects);
                                            side_effects = [];
                                        }
                                        ++i;
                                    }
                                }
                                if (side_effects.length > 0) {
                                    side_effects = make_node(AST_BlockStatement, node, {
                                        body: [ make_node(AST_SimpleStatement, node, {
                                            body: AST_Seq.from_array(side_effects)
                                        }) ]
                                    });
                                } else {
                                    side_effects = null;
                                }
                                if (def.length == 0 && !side_effects) {
                                    return make_node(AST_EmptyStatement, node);
                                }
                                if (def.length == 0) {
                                    return side_effects;
                                }
                                node.definitions = def;
                                if (side_effects) {
                                    side_effects.body.unshift(node);
                                    node = side_effects;
                                }
                                return node;
                            }
                            if (node instanceof AST_For) {
                                descend(node, this);
        
                                if (node.init instanceof AST_BlockStatement) {
                                    // certain combination of unused name + side effect leads to:
                                    //    https://github.com/mishoo/UglifyJS2/issues/44
                                    // that's an invalid AST.
                                    // We fix it at this stage by moving the `var` outside the `for`.
        
                                    var body = node.init.body.slice(0, -1);
                                    node.init = node.init.body.slice(-1)[0].body;
                                    body.push(node);
        
                                    return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, {
                                        body: body
                                    });
                                }
                            }
                            if (node instanceof AST_Scope && node !== self)
                                return node;
                        }
                    );
                    self.transform(tt);
                }
            });
        
            AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){
                var hoist_funs = compressor.option("hoist_funs");
                var hoist_vars = compressor.option("hoist_vars");
                var self = this;
                if (hoist_funs || hoist_vars) {
                    var dirs = [];
                    var hoisted = [];
                    var vars = new Dictionary(), vars_found = 0, var_decl = 0;
                    // let's count var_decl first, we seem to waste a lot of
                    // space if we hoist `var` when there's only one.
                    self.walk(new TreeWalker(function(node){
                        if (node instanceof AST_Scope && node !== self)
                            return true;
                        if (node instanceof AST_Var) {
                            ++var_decl;
                            return true;
                        }
                    }));
                    hoist_vars = hoist_vars && var_decl > 1;
                    var tt = new TreeTransformer(
                        function before(node) {
                            if (node !== self) {
                                if (node instanceof AST_Directive) {
                                    dirs.push(node);
                                    return make_node(AST_EmptyStatement, node);
                                }
                                if (node instanceof AST_Defun && hoist_funs) {
                                    hoisted.push(node);
                                    return make_node(AST_EmptyStatement, node);
                                }
                                if (node instanceof AST_Var && hoist_vars) {
                                    node.definitions.forEach(function(def){
                                        vars.set(def.name.name, def);
                                        ++vars_found;
                                    });
                                    var seq = node.to_assignments();
                                    var p = tt.parent();
                                    if (p instanceof AST_ForIn && p.init === node) {
                                        if (seq == null) return node.definitions[0].name;
                                        return seq;
                                    }
                                    if (p instanceof AST_For && p.init === node) {
                                        return seq;
                                    }
                                    if (!seq) return make_node(AST_EmptyStatement, node);
                                    return make_node(AST_SimpleStatement, node, {
                                        body: seq
                                    });
                                }
                                if (node instanceof AST_Scope)
                                    return node; // to avoid descending in nested scopes
                            }
                        }
                    );
                    self = self.transform(tt);
                    if (vars_found > 0) {
                        // collect only vars which don't show up in self's arguments list
                        var defs = [];
                        vars.each(function(def, name){
                            if (self instanceof AST_Lambda
                                && find_if(function(x){ return x.name == def.name.name },
                                           self.argnames)) {
                                vars.del(name);
                            } else {
                                def = def.clone();
                                def.value = null;
                                defs.push(def);
                                vars.set(name, def);
                            }
                        });
                        if (defs.length > 0) {
                            // try to merge in assignments
                            for (var i = 0; i < self.body.length;) {
                                if (self.body[i] instanceof AST_SimpleStatement) {
                                    var expr = self.body[i].body, sym, assign;
                                    if (expr instanceof AST_Assign
                                        && expr.operator == "="
                                        && (sym = expr.left) instanceof AST_Symbol
                                        && vars.has(sym.name))
                                    {
                                        var def = vars.get(sym.name);
                                        if (def.value) break;
                                        def.value = expr.right;
                                        remove(defs, def);
                                        defs.push(def);
                                        self.body.splice(i, 1);
                                        continue;
                                    }
                                    if (expr instanceof AST_Seq
                                        && (assign = expr.car) instanceof AST_Assign
                                        && assign.operator == "="
                                        && (sym = assign.left) instanceof AST_Symbol
                                        && vars.has(sym.name))
                                    {
                                        var def = vars.get(sym.name);
                                        if (def.value) break;
                                        def.value = assign.right;
                                        remove(defs, def);
                                        defs.push(def);
                                        self.body[i].body = expr.cdr;
                                        continue;
                                    }
                                }
                                if (self.body[i] instanceof AST_EmptyStatement) {
                                    self.body.splice(i, 1);
                                    continue;
                                }
                                if (self.body[i] instanceof AST_BlockStatement) {
                                    var tmp = [ i, 1 ].concat(self.body[i].body);
                                    self.body.splice.apply(self.body, tmp);
                                    continue;
                                }
                                break;
                            }
                            defs = make_node(AST_Var, self, {
                                definitions: defs
                            });
                            hoisted.push(defs);
                        };
                    }
                    self.body = dirs.concat(hoisted, self.body);
                }
                return self;
            });
        
            OPT(AST_SimpleStatement, function(self, compressor){
                if (compressor.option("side_effects")) {
                    if (!self.body.has_side_effects(compressor)) {
                        compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start);
                        return make_node(AST_EmptyStatement, self);
                    }
                }
                return self;
            });
        
            OPT(AST_DWLoop, function(self, compressor){
                var cond = self.condition.evaluate(compressor);
                self.condition = cond[0];
                if (!compressor.option("loops")) return self;
                if (cond.length > 1) {
                    if (cond[1]) {
                        return make_node(AST_For, self, {
                            body: self.body
                        });
                    } else if (self instanceof AST_While) {
                        if (compressor.option("dead_code")) {
                            var a = [];
                            extract_declarations_from_unreachable_code(compressor, self.body, a);
                            return make_node(AST_BlockStatement, self, { body: a });
                        }
                    }
                }
                return self;
            });
        
            function if_break_in_loop(self, compressor) {
                function drop_it(rest) {
                    rest = as_statement_array(rest);
                    if (self.body instanceof AST_BlockStatement) {
                        self.body = self.body.clone();
                        self.body.body = rest.concat(self.body.body.slice(1));
                        self.body = self.body.transform(compressor);
                    } else {
                        self.body = make_node(AST_BlockStatement, self.body, {
                            body: rest
                        }).transform(compressor);
                    }
                    if_break_in_loop(self, compressor);
                }
                var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
                if (first instanceof AST_If) {
                    if (first.body instanceof AST_Break
                        && compressor.loopcontrol_target(first.body.label) === self) {
                        if (self.condition) {
                            self.condition = make_node(AST_Binary, self.condition, {
                                left: self.condition,
                                operator: "&&",
                                right: first.condition.negate(compressor),
                            });
                        } else {
                            self.condition = first.condition.negate(compressor);
                        }
                        drop_it(first.alternative);
                    }
                    else if (first.alternative instanceof AST_Break
                             && compressor.loopcontrol_target(first.alternative.label) === self) {
                        if (self.condition) {
                            self.condition = make_node(AST_Binary, self.condition, {
                                left: self.condition,
                                operator: "&&",
                                right: first.condition,
                            });
                        } else {
                            self.condition = first.condition;
                        }
                        drop_it(first.body);
                    }
                }
            };
        
            OPT(AST_While, function(self, compressor) {
                if (!compressor.option("loops")) return self;
                self = AST_DWLoop.prototype.optimize.call(self, compressor);
                if (self instanceof AST_While) {
                    if_break_in_loop(self, compressor);
                    self = make_node(AST_For, self, self).transform(compressor);
                }
                return self;
            });
        
            OPT(AST_For, function(self, compressor){
                var cond = self.condition;
                if (cond) {
                    cond = cond.evaluate(compressor);
                    self.condition = cond[0];
                }
                if (!compressor.option("loops")) return self;
                if (cond) {
                    if (cond.length > 1 && !cond[1]) {
                        if (compressor.option("dead_code")) {
                            var a = [];
                            if (self.init instanceof AST_Statement) {
                                a.push(self.init);
                            }
                            else if (self.init) {
                                a.push(make_node(AST_SimpleStatement, self.init, {
                                    body: self.init
                                }));
                            }
                            extract_declarations_from_unreachable_code(compressor, self.body, a);
                            return make_node(AST_BlockStatement, self, { body: a });
                        }
                    }
                }
                if_break_in_loop(self, compressor);
                return self;
            });
        
            OPT(AST_If, function(self, compressor){
                if (!compressor.option("conditionals")) return self;
                // if condition can be statically determined, warn and drop
                // one of the blocks.  note, statically determined implies
                // “has no side effects”; also it doesn't work for cases like
                // `x && true`, though it probably should.
                var cond = self.condition.evaluate(compressor);
                self.condition = cond[0];
                if (cond.length > 1) {
                    if (cond[1]) {
                        compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
                        if (compressor.option("dead_code")) {
                            var a = [];
                            if (self.alternative) {
                                extract_declarations_from_unreachable_code(compressor, self.alternative, a);
                            }
                            a.push(self.body);
                            return make_node(AST_BlockStatement, self, { body: a }).transform(compressor);
                        }
                    } else {
                        compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
                        if (compressor.option("dead_code")) {
                            var a = [];
                            extract_declarations_from_unreachable_code(compressor, self.body, a);
                            if (self.alternative) a.push(self.alternative);
                            return make_node(AST_BlockStatement, self, { body: a }).transform(compressor);
                        }
                    }
                }
                if (is_empty(self.alternative)) self.alternative = null;
                var negated = self.condition.negate(compressor);
                var negated_is_best = best_of(self.condition, negated) === negated;
                if (self.alternative && negated_is_best) {
                    negated_is_best = false; // because we already do the switch here.
                    self.condition = negated;
                    var tmp = self.body;
                    self.body = self.alternative || make_node(AST_EmptyStatement);
                    self.alternative = tmp;
                }
                if (is_empty(self.body) && is_empty(self.alternative)) {
                    return make_node(AST_SimpleStatement, self.condition, {
                        body: self.condition
                    }).transform(compressor);
                }
                if (self.body instanceof AST_SimpleStatement
                    && self.alternative instanceof AST_SimpleStatement) {
                    return make_node(AST_SimpleStatement, self, {
                        body: make_node(AST_Conditional, self, {
                            condition   : self.condition,
                            consequent  : self.body.body,
                            alternative : self.alternative.body
                        })
                    }).transform(compressor);
                }
                if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
                    if (negated_is_best) return make_node(AST_SimpleStatement, self, {
                        body: make_node(AST_Binary, self, {
                            operator : "||",
                            left     : negated,
                            right    : self.body.body
                        })
                    }).transform(compressor);
                    return make_node(AST_SimpleStatement, self, {
                        body: make_node(AST_Binary, self, {
                            operator : "&&",
                            left     : self.condition,
                            right    : self.body.body
                        })
                    }).transform(compressor);
                }
                if (self.body instanceof AST_EmptyStatement
                    && self.alternative
                    && self.alternative instanceof AST_SimpleStatement) {
                    return make_node(AST_SimpleStatement, self, {
                        body: make_node(AST_Binary, self, {
                            operator : "||",
                            left     : self.condition,
                            right    : self.alternative.body
                        })
                    }).transform(compressor);
                }
                if (self.body instanceof AST_Exit
                    && self.alternative instanceof AST_Exit
                    && self.body.TYPE == self.alternative.TYPE) {
                    return make_node(self.body.CTOR, self, {
                        value: make_node(AST_Conditional, self, {
                            condition   : self.condition,
                            consequent  : self.body.value || make_node(AST_Undefined, self.body).optimize(compressor),
                            alternative : self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor)
                        })
                    }).transform(compressor);
                }
                if (self.body instanceof AST_If
                    && !self.body.alternative
                    && !self.alternative) {
                    self.condition = make_node(AST_Binary, self.condition, {
                        operator: "&&",
                        left: self.condition,
                        right: self.body.condition
                    }).transform(compressor);
                    self.body = self.body.body;
                }
                if (aborts(self.body)) {
                    if (self.alternative) {
                        var alt = self.alternative;
                        self.alternative = null;
                        return make_node(AST_BlockStatement, self, {
                            body: [ self, alt ]
                        }).transform(compressor);
                    }
                }
                if (aborts(self.alternative)) {
                    var body = self.body;
                    self.body = self.alternative;
                    self.condition = negated_is_best ? negated : self.condition.negate(compressor);
                    self.alternative = null;
                    return make_node(AST_BlockStatement, self, {
                        body: [ self, body ]
                    }).transform(compressor);
                }
                return self;
            });
        
            OPT(AST_Switch, function(self, compressor){
                if (self.body.length == 0 && compressor.option("conditionals")) {
                    return make_node(AST_SimpleStatement, self, {
                        body: self.expression
                    }).transform(compressor);
                }
                for(;;) {
                    var last_branch = self.body[self.body.length - 1];
                    if (last_branch) {
                        var stat = last_branch.body[last_branch.body.length - 1]; // last statement
                        if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self)
                            last_branch.body.pop();
                        if (last_branch instanceof AST_Default && last_branch.body.length == 0) {
                            self.body.pop();
                            continue;
                        }
                    }
                    break;
                }
                var exp = self.expression.evaluate(compressor);
                out: if (exp.length == 2) try {
                    // constant expression
                    self.expression = exp[0];
                    if (!compressor.option("dead_code")) break out;
                    var value = exp[1];
                    var in_if = false;
                    var in_block = false;
                    var started = false;
                    var stopped = false;
                    var ruined = false;
                    var tt = new TreeTransformer(function(node, descend, in_list){
                        if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) {
                            // no need to descend these node types
                            return node;
                        }
                        else if (node instanceof AST_Switch && node === self) {
                            node = node.clone();
                            descend(node, this);
                            return ruined ? node : make_node(AST_BlockStatement, node, {
                                body: node.body.reduce(function(a, branch){
                                    return a.concat(branch.body);
                                }, [])
                            }).transform(compressor);
                        }
                        else if (node instanceof AST_If || node instanceof AST_Try) {
                            var save = in_if;
                            in_if = !in_block;
                            descend(node, this);
                            in_if = save;
                            return node;
                        }
                        else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) {
                            var save = in_block;
                            in_block = true;
                            descend(node, this);
                            in_block = save;
                            return node;
                        }
                        else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) {
                            if (in_if) {
                                ruined = true;
                                return node;
                            }
                            if (in_block) return node;
                            stopped = true;
                            return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
                        }
                        else if (node instanceof AST_SwitchBranch && this.parent() === self) {
                            if (stopped) return MAP.skip;
                            if (node instanceof AST_Case) {
                                var exp = node.expression.evaluate(compressor);
                                if (exp.length < 2) {
                                    // got a case with non-constant expression, baling out
                                    throw self;
                                }
                                if (exp[1] === value || started) {
                                    started = true;
                                    if (aborts(node)) stopped = true;
                                    descend(node, this);
                                    return node;
                                }
                                return MAP.skip;
                            }
                            descend(node, this);
                            return node;
                        }
                    });
                    tt.stack = compressor.stack.slice(); // so that's able to see parent nodes
                    self = self.transform(tt);
                } catch(ex) {
                    if (ex !== self) throw ex;
                }
                return self;
            });
        
            OPT(AST_Case, function(self, compressor){
                self.body = tighten_body(self.body, compressor);
                return self;
            });
        
            OPT(AST_Try, function(self, compressor){
                self.body = tighten_body(self.body, compressor);
                return self;
            });
        
            AST_Definitions.DEFMETHOD("remove_initializers", function(){
                this.definitions.forEach(function(def){ def.value = null });
            });
        
            AST_Definitions.DEFMETHOD("to_assignments", function(){
                var assignments = this.definitions.reduce(function(a, def){
                    if (def.value) {
                        var name = make_node(AST_SymbolRef, def.name, def.name);
                        a.push(make_node(AST_Assign, def, {
                            operator : "=",
                            left     : name,
                            right    : def.value
                        }));
                    }
                    return a;
                }, []);
                if (assignments.length == 0) return null;
                return AST_Seq.from_array(assignments);
            });
        
            OPT(AST_Definitions, function(self, compressor){
                if (self.definitions.length == 0)
                    return make_node(AST_EmptyStatement, self);
                return self;
            });
        
            OPT(AST_Function, function(self, compressor){
                self = AST_Lambda.prototype.optimize.call(self, compressor);
                if (compressor.option("unused") && !compressor.option("keep_fnames")) {
                    if (self.name && self.name.unreferenced()) {
                        self.name = null;
                    }
                }
                return self;
            });
        
            OPT(AST_Call, function(self, compressor){
                if (compressor.option("unsafe")) {
                    var exp = self.expression;
                    if (exp instanceof AST_SymbolRef && exp.undeclared()) {
                        switch (exp.name) {
                          case "Array":
                            if (self.args.length != 1) {
                                return make_node(AST_Array, self, {
                                    elements: self.args
                                }).transform(compressor);
                            }
                            break;
                          case "Object":
                            if (self.args.length == 0) {
                                return make_node(AST_Object, self, {
                                    properties: []
                                });
                            }
                            break;
                          case "String":
                            if (self.args.length == 0) return make_node(AST_String, self, {
                                value: ""
                            });
                            if (self.args.length <= 1) return make_node(AST_Binary, self, {
                                left: self.args[0],
                                operator: "+",
                                right: make_node(AST_String, self, { value: "" })
                            }).transform(compressor);
                            break;
                          case "Number":
                            if (self.args.length == 0) return make_node(AST_Number, self, {
                                value: 0
                            });
                            if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
                                expression: self.args[0],
                                operator: "+"
                            }).transform(compressor);
                          case "Boolean":
                            if (self.args.length == 0) return make_node(AST_False, self);
                            if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
                                expression: make_node(AST_UnaryPrefix, null, {
                                    expression: self.args[0],
                                    operator: "!"
                                }),
                                operator: "!"
                            }).transform(compressor);
                            break;
                          case "Function":
                            // new Function() => function(){}
                            if (self.args.length == 0) return make_node(AST_Function, self, {
                                argnames: [],
                                body: []
                            });
                            if (all(self.args, function(x){ return x instanceof AST_String })) {
                                // quite a corner-case, but we can handle it:
                                //   https://github.com/mishoo/UglifyJS2/issues/203
                                // if the code argument is a constant, then we can minify it.
                                try {
                                    var code = "(function(" + self.args.slice(0, -1).map(function(arg){
                                        return arg.value;
                                    }).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
                                    var ast = parse(code);
                                    ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
                                    var comp = new Compressor(compressor.options);
                                    ast = ast.transform(comp);
                                    ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
                                    ast.mangle_names();
                                    var fun;
                                    try {
                                        ast.walk(new TreeWalker(function(node){
                                            if (node instanceof AST_Lambda) {
                                                fun = node;
                                                throw ast;
                                            }
                                        }));
                                    } catch(ex) {
                                        if (ex !== ast) throw ex;
                                    };
                                    if (!fun) return self;
                                    var args = fun.argnames.map(function(arg, i){
                                        return make_node(AST_String, self.args[i], {
                                            value: arg.print_to_string()
                                        });
                                    });
                                    var code = OutputStream();
                                    AST_BlockStatement.prototype._codegen.call(fun, fun, code);
                                    code = code.toString().replace(/^\{|\}$/g, "");
                                    args.push(make_node(AST_String, self.args[self.args.length - 1], {
                                        value: code
                                    }));
                                    self.args = args;
                                    return self;
                                } catch(ex) {
                                    if (ex instanceof JS_Parse_Error) {
                                        compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
                                        compressor.warn(ex.toString());
                                    } else {
                                        console.log(ex);
                                        throw ex;
                                    }
                                }
                            }
                            break;
                        }
                    }
                    else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
                        return make_node(AST_Binary, self, {
                            left: make_node(AST_String, self, { value: "" }),
                            operator: "+",
                            right: exp.expression
                        }).transform(compressor);
                    }
                    else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: {
                        var separator = self.args.length == 0 ? "," : self.args[0].evaluate(compressor)[1];
                        if (separator == null) break EXIT; // not a constant
                        var elements = exp.expression.elements.reduce(function(a, el){
                            el = el.evaluate(compressor);
                            if (a.length == 0 || el.length == 1) {
                                a.push(el);
                            } else {
                                var last = a[a.length - 1];
                                if (last.length == 2) {
                                    // it's a constant
                                    var val = "" + last[1] + separator + el[1];
                                    a[a.length - 1] = [ make_node_from_constant(compressor, val, last[0]), val ];
                                } else {
                                    a.push(el);
                                }
                            }
                            return a;
                        }, []);
                        if (elements.length == 0) return make_node(AST_String, self, { value: "" });
                        if (elements.length == 1) return elements[0][0];
                        if (separator == "") {
                            var first;
                            if (elements[0][0] instanceof AST_String
                                || elements[1][0] instanceof AST_String) {
                                first = elements.shift()[0];
                            } else {
                                first = make_node(AST_String, self, { value: "" });
                            }
                            return elements.reduce(function(prev, el){
                                return make_node(AST_Binary, el[0], {
                                    operator : "+",
                                    left     : prev,
                                    right    : el[0],
                                });
                            }, first).transform(compressor);
                        }
                        // need this awkward cloning to not affect original element
                        // best_of will decide which one to get through.
                        var node = self.clone();
                        node.expression = node.expression.clone();
                        node.expression.expression = node.expression.expression.clone();
                        node.expression.expression.elements = elements.map(function(el){
                            return el[0];
                        });
                        return best_of(self, node);
                    }
                }
                if (compressor.option("side_effects")) {
                    if (self.expression instanceof AST_Function
                        && self.args.length == 0
                        && !AST_Block.prototype.has_side_effects.call(self.expression, compressor)) {
                        return make_node(AST_Undefined, self).transform(compressor);
                    }
                }
                if (compressor.option("drop_console")) {
                    if (self.expression instanceof AST_PropAccess &&
                        self.expression.expression instanceof AST_SymbolRef &&
                        self.expression.expression.name == "console" &&
                        self.expression.expression.undeclared()) {
                        return make_node(AST_Undefined, self).transform(compressor);
                    }
                }
                return self.evaluate(compressor)[0];
            });
        
            OPT(AST_New, function(self, compressor){
                if (compressor.option("unsafe")) {
                    var exp = self.expression;
                    if (exp instanceof AST_SymbolRef && exp.undeclared()) {
                        switch (exp.name) {
                          case "Object":
                          case "RegExp":
                          case "Function":
                          case "Error":
                          case "Array":
                            return make_node(AST_Call, self, self).transform(compressor);
                        }
                    }
                }
                return self;
            });
        
            OPT(AST_Seq, function(self, compressor){
                if (!compressor.option("side_effects"))
                    return self;
                if (!self.car.has_side_effects(compressor)) {
                    // we shouldn't compress (1,eval)(something) to
                    // eval(something) because that changes the meaning of
                    // eval (becomes lexical instead of global).
                    var p;
                    if (!(self.cdr instanceof AST_SymbolRef
                          && self.cdr.name == "eval"
                          && self.cdr.undeclared()
                          && (p = compressor.parent()) instanceof AST_Call
                          && p.expression === self)) {
                        return self.cdr;
                    }
                }
                if (compressor.option("cascade")) {
                    if (self.car instanceof AST_Assign
                        && !self.car.left.has_side_effects(compressor)) {
                        if (self.car.left.equivalent_to(self.cdr)) {
                            return self.car;
                        }
                        if (self.cdr instanceof AST_Call
                            && self.cdr.expression.equivalent_to(self.car.left)) {
                            self.cdr.expression = self.car;
                            return self.cdr;
                        }
                    }
                    if (!self.car.has_side_effects(compressor)
                        && !self.cdr.has_side_effects(compressor)
                        && self.car.equivalent_to(self.cdr)) {
                        return self.car;
                    }
                }
                if (self.cdr instanceof AST_UnaryPrefix
                    && self.cdr.operator == "void"
                    && !self.cdr.expression.has_side_effects(compressor)) {
                    self.cdr.expression = self.car;
                    return self.cdr;
                }
                if (self.cdr instanceof AST_Undefined) {
                    return make_node(AST_UnaryPrefix, self, {
                        operator   : "void",
                        expression : self.car
                    });
                }
                return self;
            });
        
            AST_Unary.DEFMETHOD("lift_sequences", function(compressor){
                if (compressor.option("sequences")) {
                    if (this.expression instanceof AST_Seq) {
                        var seq = this.expression;
                        var x = seq.to_array();
                        this.expression = x.pop();
                        x.push(this);
                        seq = AST_Seq.from_array(x).transform(compressor);
                        return seq;
                    }
                }
                return this;
            });
        
            OPT(AST_UnaryPostfix, function(self, compressor){
                return self.lift_sequences(compressor);
            });
        
            OPT(AST_UnaryPrefix, function(self, compressor){
                self = self.lift_sequences(compressor);
                var e = self.expression;
                if (compressor.option("booleans") && compressor.in_boolean_context()) {
                    switch (self.operator) {
                      case "!":
                        if (e instanceof AST_UnaryPrefix && e.operator == "!") {
                            // !!foo ==> foo, if we're in boolean context
                            return e.expression;
                        }
                        break;
                      case "typeof":
                        // typeof always returns a non-empty string, thus it's
                        // always true in booleans
                        compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
                        return make_node(AST_True, self);
                    }
                    if (e instanceof AST_Binary && self.operator == "!") {
                        self = best_of(self, e.negate(compressor));
                    }
                }
                return self.evaluate(compressor)[0];
            });
        
            function has_side_effects_or_prop_access(node, compressor) {
                var save_pure_getters = compressor.option("pure_getters");
                compressor.options.pure_getters = false;
                var ret = node.has_side_effects(compressor);
                compressor.options.pure_getters = save_pure_getters;
                return ret;
            }
        
            AST_Binary.DEFMETHOD("lift_sequences", function(compressor){
                if (compressor.option("sequences")) {
                    if (this.left instanceof AST_Seq) {
                        var seq = this.left;
                        var x = seq.to_array();
                        this.left = x.pop();
                        x.push(this);
                        seq = AST_Seq.from_array(x).transform(compressor);
                        return seq;
                    }
                    if (this.right instanceof AST_Seq
                        && this instanceof AST_Assign
                        && !has_side_effects_or_prop_access(this.left, compressor)) {
                        var seq = this.right;
                        var x = seq.to_array();
                        this.right = x.pop();
                        x.push(this);
                        seq = AST_Seq.from_array(x).transform(compressor);
                        return seq;
                    }
                }
                return this;
            });
        
            var commutativeOperators = makePredicate("== === != !== * & | ^");
        
            OPT(AST_Binary, function(self, compressor){
                var reverse = compressor.has_directive("use asm") ? noop
                    : function(op, force) {
                        if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) {
                            if (op) self.operator = op;
                            var tmp = self.left;
                            self.left = self.right;
                            self.right = tmp;
                        }
                    };
                if (commutativeOperators(self.operator)) {
                    if (self.right instanceof AST_Constant
                        && !(self.left instanceof AST_Constant)) {
                        // if right is a constant, whatever side effects the
                        // left side might have could not influence the
                        // result.  hence, force switch.
        
                        if (!(self.left instanceof AST_Binary
                              && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
                            reverse(null, true);
                        }
                    }
                    if (/^[!=]==?$/.test(self.operator)) {
                        if (self.left instanceof AST_SymbolRef && self.right instanceof AST_Conditional) {
                            if (self.right.consequent instanceof AST_SymbolRef
                                && self.right.consequent.definition() === self.left.definition()) {
                                if (/^==/.test(self.operator)) return self.right.condition;
                                if (/^!=/.test(self.operator)) return self.right.condition.negate(compressor);
                            }
                            if (self.right.alternative instanceof AST_SymbolRef
                                && self.right.alternative.definition() === self.left.definition()) {
                                if (/^==/.test(self.operator)) return self.right.condition.negate(compressor);
                                if (/^!=/.test(self.operator)) return self.right.condition;
                            }
                        }
                        if (self.right instanceof AST_SymbolRef && self.left instanceof AST_Conditional) {
                            if (self.left.consequent instanceof AST_SymbolRef
                                && self.left.consequent.definition() === self.right.definition()) {
                                if (/^==/.test(self.operator)) return self.left.condition;
                                if (/^!=/.test(self.operator)) return self.left.condition.negate(compressor);
                            }
                            if (self.left.alternative instanceof AST_SymbolRef
                                && self.left.alternative.definition() === self.right.definition()) {
                                if (/^==/.test(self.operator)) return self.left.condition.negate(compressor);
                                if (/^!=/.test(self.operator)) return self.left.condition;
                            }
                        }
                    }
                }
                self = self.lift_sequences(compressor);
                if (compressor.option("comparisons")) switch (self.operator) {
                  case "===":
                  case "!==":
                    if ((self.left.is_string(compressor) && self.right.is_string(compressor)) ||
                        (self.left.is_boolean() && self.right.is_boolean())) {
                        self.operator = self.operator.substr(0, 2);
                    }
                    // XXX: intentionally falling down to the next case
                  case "==":
                  case "!=":
                    if (self.left instanceof AST_String
                        && self.left.value == "undefined"
                        && self.right instanceof AST_UnaryPrefix
                        && self.right.operator == "typeof"
                        && compressor.option("unsafe")) {
                        if (!(self.right.expression instanceof AST_SymbolRef)
                            || !self.right.expression.undeclared()) {
                            self.right = self.right.expression;
                            self.left = make_node(AST_Undefined, self.left).optimize(compressor);
                            if (self.operator.length == 2) self.operator += "=";
                        }
                    }
                    break;
                }
                if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) {
                  case "&&":
                    var ll = self.left.evaluate(compressor);
                    var rr = self.right.evaluate(compressor);
                    if ((ll.length > 1 && !ll[1]) || (rr.length > 1 && !rr[1])) {
                        compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start);
                        return make_node(AST_False, self);
                    }
                    if (ll.length > 1 && ll[1]) {
                        return rr[0];
                    }
                    if (rr.length > 1 && rr[1]) {
                        return ll[0];
                    }
                    break;
                  case "||":
                    var ll = self.left.evaluate(compressor);
                    var rr = self.right.evaluate(compressor);
                    if ((ll.length > 1 && ll[1]) || (rr.length > 1 && rr[1])) {
                        compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start);
                        return make_node(AST_True, self);
                    }
                    if (ll.length > 1 && !ll[1]) {
                        return rr[0];
                    }
                    if (rr.length > 1 && !rr[1]) {
                        return ll[0];
                    }
                    break;
                  case "+":
                    var ll = self.left.evaluate(compressor);
                    var rr = self.right.evaluate(compressor);
                    if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1]) ||
                        (rr.length > 1 && rr[0] instanceof AST_String && rr[1])) {
                        compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
                        return make_node(AST_True, self);
                    }
                    break;
                }
                if (compressor.option("comparisons")) {
                    if (!(compressor.parent() instanceof AST_Binary)
                        || compressor.parent() instanceof AST_Assign) {
                        var negated = make_node(AST_UnaryPrefix, self, {
                            operator: "!",
                            expression: self.negate(compressor)
                        });
                        self = best_of(self, negated);
                    }
                    switch (self.operator) {
                      case "<": reverse(">"); break;
                      case "<=": reverse(">="); break;
                    }
                }
                if (self.operator == "+" && self.right instanceof AST_String
                    && self.right.getValue() === "" && self.left instanceof AST_Binary
                    && self.left.operator == "+" && self.left.is_string(compressor)) {
                    return self.left;
                }
                if (compressor.option("evaluate")) {
                    if (self.operator == "+") {
                        if (self.left instanceof AST_Constant
                            && self.right instanceof AST_Binary
                            && self.right.operator == "+"
                            && self.right.left instanceof AST_Constant
                            && self.right.is_string(compressor)) {
                            self = make_node(AST_Binary, self, {
                                operator: "+",
                                left: make_node(AST_String, null, {
                                    value: "" + self.left.getValue() + self.right.left.getValue(),
                                    start: self.left.start,
                                    end: self.right.left.end
                                }),
                                right: self.right.right
                            });
                        }
                        if (self.right instanceof AST_Constant
                            && self.left instanceof AST_Binary
                            && self.left.operator == "+"
                            && self.left.right instanceof AST_Constant
                            && self.left.is_string(compressor)) {
                            self = make_node(AST_Binary, self, {
                                operator: "+",
                                left: self.left.left,
                                right: make_node(AST_String, null, {
                                    value: "" + self.left.right.getValue() + self.right.getValue(),
                                    start: self.left.right.start,
                                    end: self.right.end
                                })
                            });
                        }
                        if (self.left instanceof AST_Binary
                            && self.left.operator == "+"
                            && self.left.is_string(compressor)
                            && self.left.right instanceof AST_Constant
                            && self.right instanceof AST_Binary
                            && self.right.operator == "+"
                            && self.right.left instanceof AST_Constant
                            && self.right.is_string(compressor)) {
                            self = make_node(AST_Binary, self, {
                                operator: "+",
                                left: make_node(AST_Binary, self.left, {
                                    operator: "+",
                                    left: self.left.left,
                                    right: make_node(AST_String, null, {
                                        value: "" + self.left.right.getValue() + self.right.left.getValue(),
                                        start: self.left.right.start,
                                        end: self.right.left.end
                                    })
                                }),
                                right: self.right.right
                            });
                        }
                    }
                }
                // x * (y * z)  ==>  x * y * z
                if (self.right instanceof AST_Binary
                    && self.right.operator == self.operator
                    && (self.operator == "*" || self.operator == "&&" || self.operator == "||"))
                {
                    self.left = make_node(AST_Binary, self.left, {
                        operator : self.operator,
                        left     : self.left,
                        right    : self.right.left
                    });
                    self.right = self.right.right;
                    return self.transform(compressor);
                }
                return self.evaluate(compressor)[0];
            });
        
            OPT(AST_SymbolRef, function(self, compressor){
                if (self.undeclared()) {
                    var defines = compressor.option("global_defs");
                    if (defines && defines.hasOwnProperty(self.name)) {
                        return make_node_from_constant(compressor, defines[self.name], self);
                    }
                    switch (self.name) {
                      case "undefined":
                        return make_node(AST_Undefined, self);
                      case "NaN":
                        return make_node(AST_NaN, self).transform(compressor);
                      case "Infinity":
                        return make_node(AST_Infinity, self).transform(compressor);
                    }
                }
                return self;
            });
        
            OPT(AST_Infinity, function (self, compressor) {
                return make_node(AST_Binary, self, {
                    operator : '/',
                    left     : make_node(AST_Number, null, {value: 1}),
                    right    : make_node(AST_Number, null, {value: 0})
                });
            });
        
            OPT(AST_NaN, function (self, compressor) {
                return make_node(AST_Binary, self, {
                    operator : '/',
                    left     : make_node(AST_Number, null, {value: 0}),
                    right    : make_node(AST_Number, null, {value: 0})
                });
            });
        
            OPT(AST_Undefined, function(self, compressor){
                if (compressor.option("unsafe")) {
                    var scope = compressor.find_parent(AST_Scope);
                    var undef = scope.find_variable("undefined");
                    if (undef) {
                        var ref = make_node(AST_SymbolRef, self, {
                            name   : "undefined",
                            scope  : scope,
                            thedef : undef
                        });
                        ref.reference();
                        return ref;
                    }
                }
                return self;
            });
        
            var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
            OPT(AST_Assign, function(self, compressor){
                self = self.lift_sequences(compressor);
                if (self.operator == "="
                    && self.left instanceof AST_SymbolRef
                    && self.right instanceof AST_Binary
                    && self.right.left instanceof AST_SymbolRef
                    && self.right.left.name == self.left.name
                    && member(self.right.operator, ASSIGN_OPS)) {
                    self.operator = self.right.operator + "=";
                    self.right = self.right.right;
                }
                return self;
            });
        
            OPT(AST_Conditional, function(self, compressor){
                if (!compressor.option("conditionals")) return self;
                if (self.condition instanceof AST_Seq) {
                    var car = self.condition.car;
                    self.condition = self.condition.cdr;
                    return AST_Seq.cons(car, self);
                }
                var cond = self.condition.evaluate(compressor);
                if (cond.length > 1) {
                    if (cond[1]) {
                        compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
                        return self.consequent;
                    } else {
                        compressor.warn("Condition always false [{file}:{line},{col}]", self.start);
                        return self.alternative;
                    }
                }
                var negated = cond[0].negate(compressor);
                if (best_of(cond[0], negated) === negated) {
                    self = make_node(AST_Conditional, self, {
                        condition: negated,
                        consequent: self.alternative,
                        alternative: self.consequent
                    });
                }
                var consequent = self.consequent;
                var alternative = self.alternative;
                if (consequent instanceof AST_Assign
                    && alternative instanceof AST_Assign
                    && consequent.operator == alternative.operator
                    && consequent.left.equivalent_to(alternative.left)
                   ) {
                    /*
                     * Stuff like this:
                     * if (foo) exp = something; else exp = something_else;
                     * ==>
                     * exp = foo ? something : something_else;
                     */
                    return make_node(AST_Assign, self, {
                        operator: consequent.operator,
                        left: consequent.left,
                        right: make_node(AST_Conditional, self, {
                            condition: self.condition,
                            consequent: consequent.right,
                            alternative: alternative.right
                        })
                    });
                }
                if (consequent instanceof AST_Call
                    && alternative.TYPE === consequent.TYPE
                    && consequent.args.length == alternative.args.length
                    && consequent.expression.equivalent_to(alternative.expression)) {
                    if (consequent.args.length == 0) {
                        return make_node(AST_Seq, self, {
                            car: self.condition,
                            cdr: consequent
                        });
                    }
                    if (consequent.args.length == 1) {
                        consequent.args[0] = make_node(AST_Conditional, self, {
                            condition: self.condition,
                            consequent: consequent.args[0],
                            alternative: alternative.args[0]
                        });
                        return consequent;
                    }
                }
                // x?y?z:a:a --> x&&y?z:a
                if (consequent instanceof AST_Conditional
                    && consequent.alternative.equivalent_to(alternative)) {
                    return make_node(AST_Conditional, self, {
                        condition: make_node(AST_Binary, self, {
                            left: self.condition,
                            operator: "&&",
                            right: consequent.condition
                        }),
                        consequent: consequent.consequent,
                        alternative: alternative
                    });
                }
                // x=y?1:1 --> x=1
                if (consequent instanceof AST_Constant
                    && alternative instanceof AST_Constant
                    && consequent.equivalent_to(alternative)) {
                    if (self.condition.has_side_effects(compressor)) {
                        return AST_Seq.from_array([self.condition, make_node_from_constant(compressor, consequent.value, self)]);
                    } else {
                        return make_node_from_constant(compressor, consequent.value, self);
        
                    }
                }
                // x=y?true:false --> x=!!y
                if (consequent instanceof AST_True
                    && alternative instanceof AST_False) {
                    self.condition = self.condition.negate(compressor);
                    return make_node(AST_UnaryPrefix, self.condition, {
                        operator: "!",
                        expression: self.condition
                    });
                }
                // x=y?false:true --> x=!y
                if (consequent instanceof AST_False
                    && alternative instanceof AST_True) {
                    return self.condition.negate(compressor)
                }
                return self;
            });
        
            OPT(AST_Boolean, function(self, compressor){
                if (compressor.option("booleans")) {
                    var p = compressor.parent();
                    if (p instanceof AST_Binary && (p.operator == "=="
                                                    || p.operator == "!=")) {
                        compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", {
                            operator : p.operator,
                            value    : self.value,
                            file     : p.start.file,
                            line     : p.start.line,
                            col      : p.start.col,
                        });
                        return make_node(AST_Number, self, {
                            value: +self.value
                        });
                    }
                    return make_node(AST_UnaryPrefix, self, {
                        operator: "!",
                        expression: make_node(AST_Number, self, {
                            value: 1 - self.value
                        })
                    });
                }
                return self;
            });
        
            OPT(AST_Sub, function(self, compressor){
                var prop = self.property;
                if (prop instanceof AST_String && compressor.option("properties")) {
                    prop = prop.getValue();
                    if (RESERVED_WORDS(prop) ? compressor.option("screw_ie8") : is_identifier_string(prop)) {
                        return make_node(AST_Dot, self, {
                            expression : self.expression,
                            property   : prop
                        }).optimize(compressor);
                    }
                    var v = parseFloat(prop);
                    if (!isNaN(v) && v.toString() == prop) {
                        self.property = make_node(AST_Number, self.property, {
                            value: v
                        });
                    }
                }
                return self;
            });
        
            OPT(AST_Dot, function(self, compressor){
                var prop = self.property;
                if (RESERVED_WORDS(prop) && !compressor.option("screw_ie8")) {
                    return make_node(AST_Sub, self, {
                        expression : self.expression,
                        property   : make_node(AST_String, self, {
                            value: prop
                        })
                    }).optimize(compressor);
                }
                return self.evaluate(compressor)[0];
            });
        
            function literals_in_boolean_context(self, compressor) {
                if (compressor.option("booleans") && compressor.in_boolean_context()) {
                    return make_node(AST_True, self);
                }
                return self;
            };
            OPT(AST_Array, literals_in_boolean_context);
            OPT(AST_Object, literals_in_boolean_context);
            OPT(AST_RegExp, literals_in_boolean_context);
        
        })();
        
      • mozilla-ast.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        (function(){
        
            var MOZ_TO_ME = {
                ExpressionStatement: function(M) {
                    var expr = M.expression;
                    if (expr.type === "Literal" && typeof expr.value === "string") {
                        return new AST_Directive({
                            start: my_start_token(M),
                            end: my_end_token(M),
                            value: expr.value
                        });
                    }
                    return new AST_SimpleStatement({
                        start: my_start_token(M),
                        end: my_end_token(M),
                        body: from_moz(expr)
                    });
                },
                TryStatement: function(M) {
                    var handlers = M.handlers || [M.handler];
                    if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) {
                        throw new Error("Multiple catch clauses are not supported.");
                    }
                    return new AST_Try({
                        start    : my_start_token(M),
                        end      : my_end_token(M),
                        body     : from_moz(M.block).body,
                        bcatch   : from_moz(handlers[0]),
                        bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
                    });
                },
                Property: function(M) {
                    var key = M.key;
                    var name = key.type == "Identifier" ? key.name : key.value;
                    var args = {
                        start    : my_start_token(key),
                        end      : my_end_token(M.value),
                        key      : name,
                        value    : from_moz(M.value)
                    };
                    switch (M.kind) {
                      case "init":
                        return new AST_ObjectKeyVal(args);
                      case "set":
                        args.value.name = from_moz(key);
                        return new AST_ObjectSetter(args);
                      case "get":
                        args.value.name = from_moz(key);
                        return new AST_ObjectGetter(args);
                    }
                },
                ObjectExpression: function(M) {
                    return new AST_Object({
                        start      : my_start_token(M),
                        end        : my_end_token(M),
                        properties : M.properties.map(function(prop){
                            prop.type = "Property";
                            return from_moz(prop)
                        })
                    });
                },
                SequenceExpression: function(M) {
                    return AST_Seq.from_array(M.expressions.map(from_moz));
                },
                MemberExpression: function(M) {
                    return new (M.computed ? AST_Sub : AST_Dot)({
                        start      : my_start_token(M),
                        end        : my_end_token(M),
                        property   : M.computed ? from_moz(M.property) : M.property.name,
                        expression : from_moz(M.object)
                    });
                },
                SwitchCase: function(M) {
                    return new (M.test ? AST_Case : AST_Default)({
                        start      : my_start_token(M),
                        end        : my_end_token(M),
                        expression : from_moz(M.test),
                        body       : M.consequent.map(from_moz)
                    });
                },
                VariableDeclaration: function(M) {
                    return new (M.kind === "const" ? AST_Const : AST_Var)({
                        start       : my_start_token(M),
                        end         : my_end_token(M),
                        definitions : M.declarations.map(from_moz)
                    });
                },
                Literal: function(M) {
                    var val = M.value, args = {
                        start  : my_start_token(M),
                        end    : my_end_token(M)
                    };
                    if (val === null) return new AST_Null(args);
                    switch (typeof val) {
                      case "string":
                        args.value = val;
                        return new AST_String(args);
                      case "number":
                        args.value = val;
                        return new AST_Number(args);
                      case "boolean":
                        return new (val ? AST_True : AST_False)(args);
                      default:
                        args.value = val;
                        return new AST_RegExp(args);
                    }
                },
                Identifier: function(M) {
                    var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
                    return new (  p.type == "LabeledStatement" ? AST_Label
                                : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar)
                                : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
                                : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
                                : p.type == "CatchClause" ? AST_SymbolCatch
                                : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef
                                : AST_SymbolRef)({
                                    start : my_start_token(M),
                                    end   : my_end_token(M),
                                    name  : M.name
                                });
                }
            };
        
            MOZ_TO_ME.UpdateExpression =
            MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) {
                var prefix = "prefix" in M ? M.prefix
                    : M.type == "UnaryExpression" ? true : false;
                return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
                    start      : my_start_token(M),
                    end        : my_end_token(M),
                    operator   : M.operator,
                    expression : from_moz(M.argument)
                });
            };
        
            map("Program", AST_Toplevel, "body@body");
            map("EmptyStatement", AST_EmptyStatement);
            map("BlockStatement", AST_BlockStatement, "body@body");
            map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
            map("LabeledStatement", AST_LabeledStatement, "label>label, body>body");
            map("BreakStatement", AST_Break, "label>label");
            map("ContinueStatement", AST_Continue, "label>label");
            map("WithStatement", AST_With, "object>expression, body>body");
            map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body");
            map("ReturnStatement", AST_Return, "argument>value");
            map("ThrowStatement", AST_Throw, "argument>value");
            map("WhileStatement", AST_While, "test>condition, body>body");
            map("DoWhileStatement", AST_Do, "test>condition, body>body");
            map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
            map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
            map("DebuggerStatement", AST_Debugger);
            map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body");
            map("VariableDeclarator", AST_VarDef, "id>name, init>value");
            map("CatchClause", AST_Catch, "param>argname, body%body");
        
            map("ThisExpression", AST_This);
            map("ArrayExpression", AST_Array, "elements@elements");
            map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body");
            map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
            map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
            map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
            map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
            map("NewExpression", AST_New, "callee>expression, arguments@args");
            map("CallExpression", AST_Call, "callee>expression, arguments@args");
        
            def_to_moz(AST_Directive, function To_Moz_Directive(M) {
                return {
                    type: "ExpressionStatement",
                    expression: {
                        type: "Literal",
                        value: M.value
                    }
                };
            });
        
            def_to_moz(AST_SimpleStatement, function To_Moz_ExpressionStatement(M) {
                return {
                    type: "ExpressionStatement",
                    expression: to_moz(M.body)
                };
            });
        
            def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) {
                return {
                    type: "SwitchCase",
                    test: to_moz(M.expression),
                    consequent: M.body.map(to_moz)
                };
            });
        
            def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
                return {
                    type: "TryStatement",
                    block: to_moz_block(M),
                    handler: to_moz(M.bcatch),
                    guardedHandlers: [],
                    finalizer: to_moz(M.bfinally)
                };
            });
        
            def_to_moz(AST_Catch, function To_Moz_CatchClause(M) {
                return {
                    type: "CatchClause",
                    param: to_moz(M.argname),
                    guard: null,
                    body: to_moz_block(M)
                };
            });
        
            def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
                return {
                    type: "VariableDeclaration",
                    kind: M instanceof AST_Const ? "const" : "var",
                    declarations: M.definitions.map(to_moz)
                };
            });
        
            def_to_moz(AST_Seq, function To_Moz_SequenceExpression(M) {
                return {
                    type: "SequenceExpression",
                    expressions: M.to_array().map(to_moz)
                };
            });
        
            def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) {
                var isComputed = M instanceof AST_Sub;
                return {
                    type: "MemberExpression",
                    object: to_moz(M.expression),
                    computed: isComputed,
                    property: isComputed ? to_moz(M.property) : {type: "Identifier", name: M.property}
                };
            });
        
            def_to_moz(AST_Unary, function To_Moz_Unary(M) {
                return {
                    type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression",
                    operator: M.operator,
                    prefix: M instanceof AST_UnaryPrefix,
                    argument: to_moz(M.expression)
                };
            });
        
            def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
                return {
                    type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression",
                    left: to_moz(M.left),
                    operator: M.operator,
                    right: to_moz(M.right)
                };
            });
        
            def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) {
                return {
                    type: "ObjectExpression",
                    properties: M.properties.map(to_moz)
                };
            });
        
            def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
                var key = (
                    is_identifier(M.key)
                    ? {type: "Identifier", name: M.key}
                    : {type: "Literal", value: M.key}
                );
                var kind;
                if (M instanceof AST_ObjectKeyVal) {
                    kind = "init";
                } else
                if (M instanceof AST_ObjectGetter) {
                    kind = "get";
                } else
                if (M instanceof AST_ObjectSetter) {
                    kind = "set";
                }
                return {
                    type: "Property",
                    kind: kind,
                    key: key,
                    value: to_moz(M.value)
                };
            });
        
            def_to_moz(AST_Symbol, function To_Moz_Identifier(M) {
                var def = M.definition();
                return {
                    type: "Identifier",
                    name: def ? def.mangled_name || def.name : M.name
                };
            });
        
            def_to_moz(AST_Constant, function To_Moz_Literal(M) {
                var value = M.value;
                if (typeof value === 'number' && (value < 0 || (value === 0 && 1 / value < 0))) {
                    return {
                        type: "UnaryExpression",
                        operator: "-",
                        prefix: true,
                        argument: {
                            type: "Literal",
                            value: -value
                        }
                    };
                }
                return {
                    type: "Literal",
                    value: value
                };
            });
        
            def_to_moz(AST_Atom, function To_Moz_Atom(M) {
                return {
                    type: "Identifier",
                    name: String(M.value)
                };
            });
        
            AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
            AST_Null.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
            AST_Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null });
        
            AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast);
            AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast);
        
            /* -----[ tools ]----- */
        
            function my_start_token(moznode) {
                var loc = moznode.loc, start = loc && loc.start;
                var range = moznode.range;
                return new AST_Token({
                    file    : loc && loc.source,
                    line    : start && start.line,
                    col     : start && start.column,
                    pos     : range ? range[0] : moznode.start,
                    endline : start && start.line,
                    endcol  : start && start.column,
                    endpos  : range ? range[0] : moznode.start
                });
            };
        
            function my_end_token(moznode) {
                var loc = moznode.loc, end = loc && loc.end;
                var range = moznode.range;
                return new AST_Token({
                    file    : loc && loc.source,
                    line    : end && end.line,
                    col     : end && end.column,
                    pos     : range ? range[1] : moznode.end,
                    endline : end && end.line,
                    endcol  : end && end.column,
                    endpos  : range ? range[1] : moznode.end
                });
            };
        
            function map(moztype, mytype, propmap) {
                var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
                moz_to_me += "return new " + mytype.name + "({\n" +
                    "start: my_start_token(M),\n" +
                    "end: my_end_token(M)";
        
                var me_to_moz = "function To_Moz_" + moztype + "(M){\n";
                me_to_moz += "return {\n" +
                    "type: " + JSON.stringify(moztype);
        
                if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){
                    var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
                    if (!m) throw new Error("Can't understand property map: " + prop);
                    var moz = m[1], how = m[2], my = m[3];
                    moz_to_me += ",\n" + my + ": ";
                    me_to_moz += ",\n" + moz + ": ";
                    switch (how) {
                        case "@":
                            moz_to_me += "M." + moz + ".map(from_moz)";
                            me_to_moz += "M." +  my + ".map(to_moz)";
                            break;
                        case ">":
                            moz_to_me += "from_moz(M." + moz + ")";
                            me_to_moz += "to_moz(M." + my + ")";
                            break;
                        case "=":
                            moz_to_me += "M." + moz;
                            me_to_moz += "M." + my;
                            break;
                        case "%":
                            moz_to_me += "from_moz(M." + moz + ").body";
                            me_to_moz += "to_moz_block(M)";
                            break;
                        default:
                            throw new Error("Can't understand operator in propmap: " + prop);
                    }
                });
        
                moz_to_me += "\n})\n}";
                me_to_moz += "\n}\n}";
        
                //moz_to_me = parse(moz_to_me).print_to_string({ beautify: true });
                //me_to_moz = parse(me_to_moz).print_to_string({ beautify: true });
                //console.log(moz_to_me);
        
                moz_to_me = new Function("my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
                    my_start_token, my_end_token, from_moz
                );
                me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(
                    to_moz, to_moz_block
                );
                MOZ_TO_ME[moztype] = moz_to_me;
                def_to_moz(mytype, me_to_moz);
            };
        
            var FROM_MOZ_STACK = null;
        
            function from_moz(node) {
                FROM_MOZ_STACK.push(node);
                var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
                FROM_MOZ_STACK.pop();
                return ret;
            };
        
            AST_Node.from_mozilla_ast = function(node){
                var save_stack = FROM_MOZ_STACK;
                FROM_MOZ_STACK = [];
                var ast = from_moz(node);
                FROM_MOZ_STACK = save_stack;
                return ast;
            };
        
            function set_moz_loc(mynode, moznode, myparent) {
                var start = mynode.start;
                var end = mynode.end;
                if (start.pos != null && end.endpos != null) {
                    moznode.range = [start.pos, end.endpos];
                }
                if (start.line) {
                    moznode.loc = {
                        start: {line: start.line, column: start.col},
                        end: end.endline ? {line: end.endline, column: end.endcol} : null
                    };
                    if (start.file) {
                        moznode.loc.source = start.file;
                    }
                }
                return moznode;
            };
        
            function def_to_moz(mytype, handler) {
                mytype.DEFMETHOD("to_mozilla_ast", function() {
                    return set_moz_loc(this, handler(this));
                });
            };
        
            function to_moz(node) {
                return node != null ? node.to_mozilla_ast() : null;
            };
        
            function to_moz_block(node) {
                return {
                    type: "BlockStatement",
                    body: node.body.map(to_moz)
                };
            };
        
        })();
        
      • output.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        function OutputStream(options) {
        
            options = defaults(options, {
                indent_start     : 0,
                indent_level     : 4,
                quote_keys       : false,
                space_colon      : true,
                ascii_only       : false,
                unescape_regexps : false,
                inline_script    : false,
                width            : 80,
                max_line_len     : 32000,
                beautify         : false,
                source_map       : null,
                bracketize       : false,
                semicolons       : true,
                comments         : false,
                preserve_line    : false,
                screw_ie8        : false,
                preamble         : null,
                quote_style      : 0
            }, true);
        
            var indentation = 0;
            var current_col = 0;
            var current_line = 1;
            var current_pos = 0;
            var OUTPUT = "";
        
            function to_ascii(str, identifier) {
                return str.replace(/[\u0080-\uffff]/g, function(ch) {
                    var code = ch.charCodeAt(0).toString(16);
                    if (code.length <= 2 && !identifier) {
                        while (code.length < 2) code = "0" + code;
                        return "\\x" + code;
                    } else {
                        while (code.length < 4) code = "0" + code;
                        return "\\u" + code;
                    }
                });
            };
        
            function make_string(str, quote) {
                var dq = 0, sq = 0;
                str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0\ufeff]/g, function(s){
                    switch (s) {
                      case "\\": return "\\\\";
                      case "\b": return "\\b";
                      case "\f": return "\\f";
                      case "\n": return "\\n";
                      case "\r": return "\\r";
                      case "\u2028": return "\\u2028";
                      case "\u2029": return "\\u2029";
                      case '"': ++dq; return '"';
                      case "'": ++sq; return "'";
                      case "\0": return "\\x00";
                      case "\ufeff": return "\\ufeff";
                    }
                    return s;
                });
                function quote_single() {
                    return "'" + str.replace(/\x27/g, "\\'") + "'";
                }
                function quote_double() {
                    return '"' + str.replace(/\x22/g, '\\"') + '"';
                }
                if (options.ascii_only) str = to_ascii(str);
                switch (options.quote_style) {
                  case 1:
                    return quote_single();
                  case 2:
                    return quote_double();
                  case 3:
                    return quote == "'" ? quote_single() : quote_double();
                  default:
                    return dq > sq ? quote_single() : quote_double();
                }
            };
        
            function encode_string(str, quote) {
                var ret = make_string(str, quote);
                if (options.inline_script)
                    ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
                return ret;
            };
        
            function make_name(name) {
                name = name.toString();
                if (options.ascii_only)
                    name = to_ascii(name, true);
                return name;
            };
        
            function make_indent(back) {
                return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
            };
        
            /* -----[ beautification/minification ]----- */
        
            var might_need_space = false;
            var might_need_semicolon = false;
            var last = null;
        
            function last_char() {
                return last.charAt(last.length - 1);
            };
        
            function maybe_newline() {
                if (options.max_line_len && current_col > options.max_line_len)
                    print("\n");
            };
        
            var requireSemicolonChars = makePredicate("( [ + * / - , .");
        
            function print(str) {
                str = String(str);
                var ch = str.charAt(0);
                if (might_need_semicolon) {
                    if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {
                        if (options.semicolons || requireSemicolonChars(ch)) {
                            OUTPUT += ";";
                            current_col++;
                            current_pos++;
                        } else {
                            OUTPUT += "\n";
                            current_pos++;
                            current_line++;
                            current_col = 0;
                        }
                        if (!options.beautify)
                            might_need_space = false;
                    }
                    might_need_semicolon = false;
                    maybe_newline();
                }
        
                if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
                    var target_line = stack[stack.length - 1].start.line;
                    while (current_line < target_line) {
                        OUTPUT += "\n";
                        current_pos++;
                        current_line++;
                        current_col = 0;
                        might_need_space = false;
                    }
                }
        
                if (might_need_space) {
                    var prev = last_char();
                    if ((is_identifier_char(prev)
                         && (is_identifier_char(ch) || ch == "\\"))
                        || (/^[\+\-\/]$/.test(ch) && ch == prev))
                    {
                        OUTPUT += " ";
                        current_col++;
                        current_pos++;
                    }
                    might_need_space = false;
                }
                var a = str.split(/\r?\n/), n = a.length - 1;
                current_line += n;
                if (n == 0) {
                    current_col += a[n].length;
                } else {
                    current_col = a[n].length;
                }
                current_pos += str.length;
                last = str;
                OUTPUT += str;
            };
        
            var space = options.beautify ? function() {
                print(" ");
            } : function() {
                might_need_space = true;
            };
        
            var indent = options.beautify ? function(half) {
                if (options.beautify) {
                    print(make_indent(half ? 0.5 : 0));
                }
            } : noop;
        
            var with_indent = options.beautify ? function(col, cont) {
                if (col === true) col = next_indent();
                var save_indentation = indentation;
                indentation = col;
                var ret = cont();
                indentation = save_indentation;
                return ret;
            } : function(col, cont) { return cont() };
        
            var newline = options.beautify ? function() {
                print("\n");
            } : maybe_newline;
        
            var semicolon = options.beautify ? function() {
                print(";");
            } : function() {
                might_need_semicolon = true;
            };
        
            function force_semicolon() {
                might_need_semicolon = false;
                print(";");
            };
        
            function next_indent() {
                return indentation + options.indent_level;
            };
        
            function with_block(cont) {
                var ret;
                print("{");
                newline();
                with_indent(next_indent(), function(){
                    ret = cont();
                });
                indent();
                print("}");
                return ret;
            };
        
            function with_parens(cont) {
                print("(");
                //XXX: still nice to have that for argument lists
                //var ret = with_indent(current_col, cont);
                var ret = cont();
                print(")");
                return ret;
            };
        
            function with_square(cont) {
                print("[");
                //var ret = with_indent(current_col, cont);
                var ret = cont();
                print("]");
                return ret;
            };
        
            function comma() {
                print(",");
                space();
            };
        
            function colon() {
                print(":");
                if (options.space_colon) space();
            };
        
            var add_mapping = options.source_map ? function(token, name) {
                try {
                    if (token) options.source_map.add(
                        token.file || "?",
                        current_line, current_col,
                        token.line, token.col,
                        (!name && token.type == "name") ? token.value : name
                    );
                } catch(ex) {
                    AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
                        file: token.file,
                        line: token.line,
                        col: token.col,
                        cline: current_line,
                        ccol: current_col,
                        name: name || ""
                    })
                }
            } : noop;
        
            function get() {
                return OUTPUT;
            };
        
            if (options.preamble) {
                print(options.preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
            }
        
            var stack = [];
            return {
                get             : get,
                toString        : get,
                indent          : indent,
                indentation     : function() { return indentation },
                current_width   : function() { return current_col - indentation },
                should_break    : function() { return options.width && this.current_width() >= options.width },
                newline         : newline,
                print           : print,
                space           : space,
                comma           : comma,
                colon           : colon,
                last            : function() { return last },
                semicolon       : semicolon,
                force_semicolon : force_semicolon,
                to_ascii        : to_ascii,
                print_name      : function(name) { print(make_name(name)) },
                print_string    : function(str, quote) { print(encode_string(str, quote)) },
                next_indent     : next_indent,
                with_indent     : with_indent,
                with_block      : with_block,
                with_parens     : with_parens,
                with_square     : with_square,
                add_mapping     : add_mapping,
                option          : function(opt) { return options[opt] },
                line            : function() { return current_line },
                col             : function() { return current_col },
                pos             : function() { return current_pos },
                push_node       : function(node) { stack.push(node) },
                pop_node        : function() { return stack.pop() },
                stack           : function() { return stack },
                parent          : function(n) {
                    return stack[stack.length - 2 - (n || 0)];
                }
            };
        
        };
        
        /* -----[ code generators ]----- */
        
        (function(){
        
            /* -----[ utils ]----- */
        
            function DEFPRINT(nodetype, generator) {
                nodetype.DEFMETHOD("_codegen", generator);
            };
        
            AST_Node.DEFMETHOD("print", function(stream, force_parens){
                var self = this, generator = self._codegen;
                function doit() {
                    self.add_comments(stream);
                    self.add_source_map(stream);
                    generator(self, stream);
                }
                stream.push_node(self);
                if (force_parens || self.needs_parens(stream)) {
                    stream.with_parens(doit);
                } else {
                    doit();
                }
                stream.pop_node();
            });
        
            AST_Node.DEFMETHOD("print_to_string", function(options){
                var s = OutputStream(options);
                this.print(s);
                return s.get();
            });
        
            /* -----[ comments ]----- */
        
            AST_Node.DEFMETHOD("add_comments", function(output){
                var c = output.option("comments"), self = this;
                if (c) {
                    var start = self.start;
                    if (start && !start._comments_dumped) {
                        start._comments_dumped = true;
                        var comments = start.comments_before || [];
        
                        // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112
                        //               and https://github.com/mishoo/UglifyJS2/issues/372
                        if (self instanceof AST_Exit && self.value) {
                            self.value.walk(new TreeWalker(function(node){
                                if (node.start && node.start.comments_before) {
                                    comments = comments.concat(node.start.comments_before);
                                    node.start.comments_before = [];
                                }
                                if (node instanceof AST_Function ||
                                    node instanceof AST_Array ||
                                    node instanceof AST_Object)
                                {
                                    return true; // don't go inside.
                                }
                            }));
                        }
        
                        if (c.test) {
                            comments = comments.filter(function(comment){
                                return c.test(comment.value);
                            });
                        } else if (typeof c == "function") {
                            comments = comments.filter(function(comment){
                                return c(self, comment);
                            });
                        }
        
                        // Keep single line comments after nlb, after nlb
                        if (!output.option("beautify") && comments.length > 0 &&
                            /comment[134]/.test(comments[0].type) &&
                            output.col() !== 0 && comments[0].nlb)
                        {
                            output.print("\n");
                        }
        
                        comments.forEach(function(c){
                            if (/comment[134]/.test(c.type)) {
                                output.print("//" + c.value + "\n");
                                output.indent();
                            }
                            else if (c.type == "comment2") {
                                output.print("/*" + c.value + "*/");
                                if (start.nlb) {
                                    output.print("\n");
                                    output.indent();
                                } else {
                                    output.space();
                                }
                            }
                        });
                    }
                }
            });
        
            /* -----[ PARENTHESES ]----- */
        
            function PARENS(nodetype, func) {
                if (Array.isArray(nodetype)) {
                    nodetype.forEach(function(nodetype){
                        PARENS(nodetype, func);
                    });
                } else {
                    nodetype.DEFMETHOD("needs_parens", func);
                }
            };
        
            PARENS(AST_Node, function(){
                return false;
            });
        
            // a function expression needs parens around it when it's provably
            // the first token to appear in a statement.
            PARENS(AST_Function, function(output){
                return first_in_statement(output);
            });
        
            // same goes for an object literal, because otherwise it would be
            // interpreted as a block of code.
            PARENS(AST_Object, function(output){
                return first_in_statement(output);
            });
        
            PARENS([ AST_Unary, AST_Undefined ], function(output){
                var p = output.parent();
                return p instanceof AST_PropAccess && p.expression === this;
            });
        
            PARENS(AST_Seq, function(output){
                var p = output.parent();
                return p instanceof AST_Call             // (foo, bar)() or foo(1, (2, 3), 4)
                    || p instanceof AST_Unary            // !(foo, bar, baz)
                    || p instanceof AST_Binary           // 1 + (2, 3) + 4 ==> 8
                    || p instanceof AST_VarDef           // var a = (1, 2), b = a + a; ==> b == 4
                    || p instanceof AST_PropAccess       // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
                    || p instanceof AST_Array            // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
                    || p instanceof AST_ObjectProperty   // { foo: (1, 2) }.foo ==> 2
                    || p instanceof AST_Conditional      /* (false, true) ? (a = 10, b = 20) : (c = 30)
                                                          * ==> 20 (side effect, set a := 10 and b := 20) */
                ;
            });
        
            PARENS(AST_Binary, function(output){
                var p = output.parent();
                // (foo && bar)()
                if (p instanceof AST_Call && p.expression === this)
                    return true;
                // typeof (foo && bar)
                if (p instanceof AST_Unary)
                    return true;
                // (foo && bar)["prop"], (foo && bar).prop
                if (p instanceof AST_PropAccess && p.expression === this)
                    return true;
                // this deals with precedence: 3 * (2 + 1)
                if (p instanceof AST_Binary) {
                    var po = p.operator, pp = PRECEDENCE[po];
                    var so = this.operator, sp = PRECEDENCE[so];
                    if (pp > sp
                        || (pp == sp
                            && this === p.right)) {
                        return true;
                    }
                }
            });
        
            PARENS(AST_PropAccess, function(output){
                var p = output.parent();
                if (p instanceof AST_New && p.expression === this) {
                    // i.e. new (foo.bar().baz)
                    //
                    // if there's one call into this subtree, then we need
                    // parens around it too, otherwise the call will be
                    // interpreted as passing the arguments to the upper New
                    // expression.
                    try {
                        this.walk(new TreeWalker(function(node){
                            if (node instanceof AST_Call) throw p;
                        }));
                    } catch(ex) {
                        if (ex !== p) throw ex;
                        return true;
                    }
                }
            });
        
            PARENS(AST_Call, function(output){
                var p = output.parent(), p1;
                if (p instanceof AST_New && p.expression === this)
                    return true;
        
                // workaround for Safari bug.
                // https://bugs.webkit.org/show_bug.cgi?id=123506
                return this.expression instanceof AST_Function
                    && p instanceof AST_PropAccess
                    && p.expression === this
                    && (p1 = output.parent(1)) instanceof AST_Assign
                    && p1.left === p;
            });
        
            PARENS(AST_New, function(output){
                var p = output.parent();
                if (no_constructor_parens(this, output)
                    && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]()
                        || p instanceof AST_Call && p.expression === this)) // (new foo)(bar)
                    return true;
            });
        
            PARENS(AST_Number, function(output){
                var p = output.parent();
                if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this)
                    return true;
            });
        
            PARENS([ AST_Assign, AST_Conditional ], function (output){
                var p = output.parent();
                // !(a = false) → true
                if (p instanceof AST_Unary)
                    return true;
                // 1 + (a = 2) + 3 → 6, side effect setting a = 2
                if (p instanceof AST_Binary && !(p instanceof AST_Assign))
                    return true;
                // (a = func)() —or— new (a = Object)()
                if (p instanceof AST_Call && p.expression === this)
                    return true;
                // (a = foo) ? bar : baz
                if (p instanceof AST_Conditional && p.condition === this)
                    return true;
                // (a = foo)["prop"] —or— (a = foo).prop
                if (p instanceof AST_PropAccess && p.expression === this)
                    return true;
            });
        
            /* -----[ PRINTERS ]----- */
        
            DEFPRINT(AST_Directive, function(self, output){
                output.print_string(self.value, self.quote);
                output.semicolon();
            });
            DEFPRINT(AST_Debugger, function(self, output){
                output.print("debugger");
                output.semicolon();
            });
        
            /* -----[ statements ]----- */
        
            function display_body(body, is_toplevel, output) {
                var last = body.length - 1;
                body.forEach(function(stmt, i){
                    if (!(stmt instanceof AST_EmptyStatement)) {
                        output.indent();
                        stmt.print(output);
                        if (!(i == last && is_toplevel)) {
                            output.newline();
                            if (is_toplevel) output.newline();
                        }
                    }
                });
            };
        
            AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){
                force_statement(this.body, output);
            });
        
            DEFPRINT(AST_Statement, function(self, output){
                self.body.print(output);
                output.semicolon();
            });
            DEFPRINT(AST_Toplevel, function(self, output){
                display_body(self.body, true, output);
                output.print("");
            });
            DEFPRINT(AST_LabeledStatement, function(self, output){
                self.label.print(output);
                output.colon();
                self.body.print(output);
            });
            DEFPRINT(AST_SimpleStatement, function(self, output){
                self.body.print(output);
                output.semicolon();
            });
            function print_bracketed(body, output) {
                if (body.length > 0) output.with_block(function(){
                    display_body(body, false, output);
                });
                else output.print("{}");
            };
            DEFPRINT(AST_BlockStatement, function(self, output){
                print_bracketed(self.body, output);
            });
            DEFPRINT(AST_EmptyStatement, function(self, output){
                output.semicolon();
            });
            DEFPRINT(AST_Do, function(self, output){
                output.print("do");
                output.space();
                self._do_print_body(output);
                output.space();
                output.print("while");
                output.space();
                output.with_parens(function(){
                    self.condition.print(output);
                });
                output.semicolon();
            });
            DEFPRINT(AST_While, function(self, output){
                output.print("while");
                output.space();
                output.with_parens(function(){
                    self.condition.print(output);
                });
                output.space();
                self._do_print_body(output);
            });
            DEFPRINT(AST_For, function(self, output){
                output.print("for");
                output.space();
                output.with_parens(function(){
                    if (self.init && !(self.init instanceof AST_EmptyStatement)) {
                        if (self.init instanceof AST_Definitions) {
                            self.init.print(output);
                        } else {
                            parenthesize_for_noin(self.init, output, true);
                        }
                        output.print(";");
                        output.space();
                    } else {
                        output.print(";");
                    }
                    if (self.condition) {
                        self.condition.print(output);
                        output.print(";");
                        output.space();
                    } else {
                        output.print(";");
                    }
                    if (self.step) {
                        self.step.print(output);
                    }
                });
                output.space();
                self._do_print_body(output);
            });
            DEFPRINT(AST_ForIn, function(self, output){
                output.print("for");
                output.space();
                output.with_parens(function(){
                    self.init.print(output);
                    output.space();
                    output.print("in");
                    output.space();
                    self.object.print(output);
                });
                output.space();
                self._do_print_body(output);
            });
            DEFPRINT(AST_With, function(self, output){
                output.print("with");
                output.space();
                output.with_parens(function(){
                    self.expression.print(output);
                });
                output.space();
                self._do_print_body(output);
            });
        
            /* -----[ functions ]----- */
            AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){
                var self = this;
                if (!nokeyword) {
                    output.print("function");
                }
                if (self.name) {
                    output.space();
                    self.name.print(output);
                }
                output.with_parens(function(){
                    self.argnames.forEach(function(arg, i){
                        if (i) output.comma();
                        arg.print(output);
                    });
                });
                output.space();
                print_bracketed(self.body, output);
            });
            DEFPRINT(AST_Lambda, function(self, output){
                self._do_print(output);
            });
        
            /* -----[ exits ]----- */
            AST_Exit.DEFMETHOD("_do_print", function(output, kind){
                output.print(kind);
                if (this.value) {
                    output.space();
                    this.value.print(output);
                }
                output.semicolon();
            });
            DEFPRINT(AST_Return, function(self, output){
                self._do_print(output, "return");
            });
            DEFPRINT(AST_Throw, function(self, output){
                self._do_print(output, "throw");
            });
        
            /* -----[ loop control ]----- */
            AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){
                output.print(kind);
                if (this.label) {
                    output.space();
                    this.label.print(output);
                }
                output.semicolon();
            });
            DEFPRINT(AST_Break, function(self, output){
                self._do_print(output, "break");
            });
            DEFPRINT(AST_Continue, function(self, output){
                self._do_print(output, "continue");
            });
        
            /* -----[ if ]----- */
            function make_then(self, output) {
                if (output.option("bracketize")) {
                    make_block(self.body, output);
                    return;
                }
                // The squeezer replaces "block"-s that contain only a single
                // statement with the statement itself; technically, the AST
                // is correct, but this can create problems when we output an
                // IF having an ELSE clause where the THEN clause ends in an
                // IF *without* an ELSE block (then the outer ELSE would refer
                // to the inner IF).  This function checks for this case and
                // adds the block brackets if needed.
                if (!self.body)
                    return output.force_semicolon();
                if (self.body instanceof AST_Do
                    && !output.option("screw_ie8")) {
                    // https://github.com/mishoo/UglifyJS/issues/#issue/57 IE
                    // croaks with "syntax error" on code like this: if (foo)
                    // do ... while(cond); else ...  we need block brackets
                    // around do/while
                    make_block(self.body, output);
                    return;
                }
                var b = self.body;
                while (true) {
                    if (b instanceof AST_If) {
                        if (!b.alternative) {
                            make_block(self.body, output);
                            return;
                        }
                        b = b.alternative;
                    }
                    else if (b instanceof AST_StatementWithBody) {
                        b = b.body;
                    }
                    else break;
                }
                force_statement(self.body, output);
            };
            DEFPRINT(AST_If, function(self, output){
                output.print("if");
                output.space();
                output.with_parens(function(){
                    self.condition.print(output);
                });
                output.space();
                if (self.alternative) {
                    make_then(self, output);
                    output.space();
                    output.print("else");
                    output.space();
                    force_statement(self.alternative, output);
                } else {
                    self._do_print_body(output);
                }
            });
        
            /* -----[ switch ]----- */
            DEFPRINT(AST_Switch, function(self, output){
                output.print("switch");
                output.space();
                output.with_parens(function(){
                    self.expression.print(output);
                });
                output.space();
                if (self.body.length > 0) output.with_block(function(){
                    self.body.forEach(function(stmt, i){
                        if (i) output.newline();
                        output.indent(true);
                        stmt.print(output);
                    });
                });
                else output.print("{}");
            });
            AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){
                if (this.body.length > 0) {
                    output.newline();
                    this.body.forEach(function(stmt){
                        output.indent();
                        stmt.print(output);
                        output.newline();
                    });
                }
            });
            DEFPRINT(AST_Default, function(self, output){
                output.print("default:");
                self._do_print_body(output);
            });
            DEFPRINT(AST_Case, function(self, output){
                output.print("case");
                output.space();
                self.expression.print(output);
                output.print(":");
                self._do_print_body(output);
            });
        
            /* -----[ exceptions ]----- */
            DEFPRINT(AST_Try, function(self, output){
                output.print("try");
                output.space();
                print_bracketed(self.body, output);
                if (self.bcatch) {
                    output.space();
                    self.bcatch.print(output);
                }
                if (self.bfinally) {
                    output.space();
                    self.bfinally.print(output);
                }
            });
            DEFPRINT(AST_Catch, function(self, output){
                output.print("catch");
                output.space();
                output.with_parens(function(){
                    self.argname.print(output);
                });
                output.space();
                print_bracketed(self.body, output);
            });
            DEFPRINT(AST_Finally, function(self, output){
                output.print("finally");
                output.space();
                print_bracketed(self.body, output);
            });
        
            /* -----[ var/const ]----- */
            AST_Definitions.DEFMETHOD("_do_print", function(output, kind){
                output.print(kind);
                output.space();
                this.definitions.forEach(function(def, i){
                    if (i) output.comma();
                    def.print(output);
                });
                var p = output.parent();
                var in_for = p instanceof AST_For || p instanceof AST_ForIn;
                var avoid_semicolon = in_for && p.init === this;
                if (!avoid_semicolon)
                    output.semicolon();
            });
            DEFPRINT(AST_Var, function(self, output){
                self._do_print(output, "var");
            });
            DEFPRINT(AST_Const, function(self, output){
                self._do_print(output, "const");
            });
        
            function parenthesize_for_noin(node, output, noin) {
                if (!noin) node.print(output);
                else try {
                    // need to take some precautions here:
                    //    https://github.com/mishoo/UglifyJS2/issues/60
                    node.walk(new TreeWalker(function(node){
                        if (node instanceof AST_Binary && node.operator == "in")
                            throw output;
                    }));
                    node.print(output);
                } catch(ex) {
                    if (ex !== output) throw ex;
                    node.print(output, true);
                }
            };
        
            DEFPRINT(AST_VarDef, function(self, output){
                self.name.print(output);
                if (self.value) {
                    output.space();
                    output.print("=");
                    output.space();
                    var p = output.parent(1);
                    var noin = p instanceof AST_For || p instanceof AST_ForIn;
                    parenthesize_for_noin(self.value, output, noin);
                }
            });
        
            /* -----[ other expressions ]----- */
            DEFPRINT(AST_Call, function(self, output){
                self.expression.print(output);
                if (self instanceof AST_New && no_constructor_parens(self, output))
                    return;
                output.with_parens(function(){
                    self.args.forEach(function(expr, i){
                        if (i) output.comma();
                        expr.print(output);
                    });
                });
            });
            DEFPRINT(AST_New, function(self, output){
                output.print("new");
                output.space();
                AST_Call.prototype._codegen(self, output);
            });
        
            AST_Seq.DEFMETHOD("_do_print", function(output){
                this.car.print(output);
                if (this.cdr) {
                    output.comma();
                    if (output.should_break()) {
                        output.newline();
                        output.indent();
                    }
                    this.cdr.print(output);
                }
            });
            DEFPRINT(AST_Seq, function(self, output){
                self._do_print(output);
                // var p = output.parent();
                // if (p instanceof AST_Statement) {
                //     output.with_indent(output.next_indent(), function(){
                //         self._do_print(output);
                //     });
                // } else {
                //     self._do_print(output);
                // }
            });
            DEFPRINT(AST_Dot, function(self, output){
                var expr = self.expression;
                expr.print(output);
                if (expr instanceof AST_Number && expr.getValue() >= 0) {
                    if (!/[xa-f.]/i.test(output.last())) {
                        output.print(".");
                    }
                }
                output.print(".");
                // the name after dot would be mapped about here.
                output.add_mapping(self.end);
                output.print_name(self.property);
            });
            DEFPRINT(AST_Sub, function(self, output){
                self.expression.print(output);
                output.print("[");
                self.property.print(output);
                output.print("]");
            });
            DEFPRINT(AST_UnaryPrefix, function(self, output){
                var op = self.operator;
                output.print(op);
                if (/^[a-z]/i.test(op)
                    || (/[+-]$/.test(op)
                        && self.expression instanceof AST_UnaryPrefix
                        && /^[+-]/.test(self.expression.operator))) {
                    output.space();
                }
                self.expression.print(output);
            });
            DEFPRINT(AST_UnaryPostfix, function(self, output){
                self.expression.print(output);
                output.print(self.operator);
            });
            DEFPRINT(AST_Binary, function(self, output){
                self.left.print(output);
                output.space();
                output.print(self.operator);
                if (self.operator == "<"
                    && self.right instanceof AST_UnaryPrefix
                    && self.right.operator == "!"
                    && self.right.expression instanceof AST_UnaryPrefix
                    && self.right.expression.operator == "--") {
                    // space is mandatory to avoid outputting <!--
                    // http://javascript.spec.whatwg.org/#comment-syntax
                    output.print(" ");
                } else {
                    // the space is optional depending on "beautify"
                    output.space();
                }
                self.right.print(output);
            });
            DEFPRINT(AST_Conditional, function(self, output){
                self.condition.print(output);
                output.space();
                output.print("?");
                output.space();
                self.consequent.print(output);
                output.space();
                output.colon();
                self.alternative.print(output);
            });
        
            /* -----[ literals ]----- */
            DEFPRINT(AST_Array, function(self, output){
                output.with_square(function(){
                    var a = self.elements, len = a.length;
                    if (len > 0) output.space();
                    a.forEach(function(exp, i){
                        if (i) output.comma();
                        exp.print(output);
                        // If the final element is a hole, we need to make sure it
                        // doesn't look like a trailing comma, by inserting an actual
                        // trailing comma.
                        if (i === len - 1 && exp instanceof AST_Hole)
                          output.comma();
                    });
                    if (len > 0) output.space();
                });
            });
            DEFPRINT(AST_Object, function(self, output){
                if (self.properties.length > 0) output.with_block(function(){
                    self.properties.forEach(function(prop, i){
                        if (i) {
                            output.print(",");
                            output.newline();
                        }
                        output.indent();
                        prop.print(output);
                    });
                    output.newline();
                });
                else output.print("{}");
            });
            DEFPRINT(AST_ObjectKeyVal, function(self, output){
                var key = self.key;
                var quote = self.quote;
                if (output.option("quote_keys")) {
                    output.print_string(key + "");
                } else if ((typeof key == "number"
                            || !output.option("beautify")
                            && +key + "" == key)
                           && parseFloat(key) >= 0) {
                    output.print(make_num(key));
                } else if (RESERVED_WORDS(key) ? output.option("screw_ie8") : is_identifier_string(key)) {
                    output.print_name(key);
                } else {
                    output.print_string(key, quote);
                }
                output.colon();
                self.value.print(output);
            });
            DEFPRINT(AST_ObjectSetter, function(self, output){
                output.print("set");
                output.space();
                self.key.print(output);
                self.value._do_print(output, true);
            });
            DEFPRINT(AST_ObjectGetter, function(self, output){
                output.print("get");
                output.space();
                self.key.print(output);
                self.value._do_print(output, true);
            });
            DEFPRINT(AST_Symbol, function(self, output){
                var def = self.definition();
                output.print_name(def ? def.mangled_name || def.name : self.name);
            });
            DEFPRINT(AST_Undefined, function(self, output){
                output.print("void 0");
            });
            DEFPRINT(AST_Hole, noop);
            DEFPRINT(AST_Infinity, function(self, output){
                output.print("Infinity");
            });
            DEFPRINT(AST_NaN, function(self, output){
                output.print("NaN");
            });
            DEFPRINT(AST_This, function(self, output){
                output.print("this");
            });
            DEFPRINT(AST_Constant, function(self, output){
                output.print(self.getValue());
            });
            DEFPRINT(AST_String, function(self, output){
                output.print_string(self.getValue(), self.quote);
            });
            DEFPRINT(AST_Number, function(self, output){
                output.print(make_num(self.getValue()));
            });
        
            function regexp_safe_literal(code) {
                return [
                    0x5c   , // \
                    0x2f   , // /
                    0x2e   , // .
                    0x2b   , // +
                    0x2a   , // *
                    0x3f   , // ?
                    0x28   , // (
                    0x29   , // )
                    0x5b   , // [
                    0x5d   , // ]
                    0x7b   , // {
                    0x7d   , // }
                    0x24   , // $
                    0x5e   , // ^
                    0x3a   , // :
                    0x7c   , // |
                    0x21   , // !
                    0x0a   , // \n
                    0x0d   , // \r
                    0x00   , // \0
                    0xfeff , // Unicode BOM
                    0x2028 , // unicode "line separator"
                    0x2029 , // unicode "paragraph separator"
                ].indexOf(code) < 0;
            };
        
            DEFPRINT(AST_RegExp, function(self, output){
                var str = self.getValue().toString();
                if (output.option("ascii_only")) {
                    str = output.to_ascii(str);
                } else if (output.option("unescape_regexps")) {
                    str = str.split("\\\\").map(function(str){
                        return str.replace(/\\u[0-9a-fA-F]{4}|\\x[0-9a-fA-F]{2}/g, function(s){
                            var code = parseInt(s.substr(2), 16);
                            return regexp_safe_literal(code) ? String.fromCharCode(code) : s;
                        });
                    }).join("\\\\");
                }
                output.print(str);
                var p = output.parent();
                if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
                    output.print(" ");
            });
        
            function force_statement(stat, output) {
                if (output.option("bracketize")) {
                    if (!stat || stat instanceof AST_EmptyStatement)
                        output.print("{}");
                    else if (stat instanceof AST_BlockStatement)
                        stat.print(output);
                    else output.with_block(function(){
                        output.indent();
                        stat.print(output);
                        output.newline();
                    });
                } else {
                    if (!stat || stat instanceof AST_EmptyStatement)
                        output.force_semicolon();
                    else
                        stat.print(output);
                }
            };
        
            // return true if the node at the top of the stack (that means the
            // innermost node in the current output) is lexically the first in
            // a statement.
            function first_in_statement(output) {
                var a = output.stack(), i = a.length, node = a[--i], p = a[--i];
                while (i > 0) {
                    if (p instanceof AST_Statement && p.body === node)
                        return true;
                    if ((p instanceof AST_Seq           && p.car === node        ) ||
                        (p instanceof AST_Call          && p.expression === node && !(p instanceof AST_New) ) ||
                        (p instanceof AST_Dot           && p.expression === node ) ||
                        (p instanceof AST_Sub           && p.expression === node ) ||
                        (p instanceof AST_Conditional   && p.condition === node  ) ||
                        (p instanceof AST_Binary        && p.left === node       ) ||
                        (p instanceof AST_UnaryPostfix  && p.expression === node ))
                    {
                        node = p;
                        p = a[--i];
                    } else {
                        return false;
                    }
                }
            };
        
            // self should be AST_New.  decide if we want to show parens or not.
            function no_constructor_parens(self, output) {
                return self.args.length == 0 && !output.option("beautify");
            };
        
            function best_of(a) {
                var best = a[0], len = best.length;
                for (var i = 1; i < a.length; ++i) {
                    if (a[i].length < len) {
                        best = a[i];
                        len = best.length;
                    }
                }
                return best;
            };
        
            function make_num(num) {
                var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m;
                if (Math.floor(num) === num) {
                    if (num >= 0) {
                        a.push("0x" + num.toString(16).toLowerCase(), // probably pointless
                               "0" + num.toString(8)); // same.
                    } else {
                        a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless
                               "-0" + (-num).toString(8)); // same.
                    }
                    if ((m = /^(.*?)(0+)$/.exec(num))) {
                        a.push(m[1] + "e" + m[2].length);
                    }
                } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {
                    a.push(m[2] + "e-" + (m[1].length + m[2].length),
                           str.substr(str.indexOf(".")));
                }
                return best_of(a);
            };
        
            function make_block(stmt, output) {
                if (stmt instanceof AST_BlockStatement) {
                    stmt.print(output);
                    return;
                }
                output.with_block(function(){
                    output.indent();
                    stmt.print(output);
                    output.newline();
                });
            };
        
            /* -----[ source map generators ]----- */
        
            function DEFMAP(nodetype, generator) {
                nodetype.DEFMETHOD("add_source_map", function(stream){
                    generator(this, stream);
                });
            };
        
            // We could easily add info for ALL nodes, but it seems to me that
            // would be quite wasteful, hence this noop in the base class.
            DEFMAP(AST_Node, noop);
        
            function basic_sourcemap_gen(self, output) {
                output.add_mapping(self.start);
            };
        
            // XXX: I'm not exactly sure if we need it for all of these nodes,
            // or if we should add even more.
        
            DEFMAP(AST_Directive, basic_sourcemap_gen);
            DEFMAP(AST_Debugger, basic_sourcemap_gen);
            DEFMAP(AST_Symbol, basic_sourcemap_gen);
            DEFMAP(AST_Jump, basic_sourcemap_gen);
            DEFMAP(AST_StatementWithBody, basic_sourcemap_gen);
            DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it
            DEFMAP(AST_Lambda, basic_sourcemap_gen);
            DEFMAP(AST_Switch, basic_sourcemap_gen);
            DEFMAP(AST_SwitchBranch, basic_sourcemap_gen);
            DEFMAP(AST_BlockStatement, basic_sourcemap_gen);
            DEFMAP(AST_Toplevel, noop);
            DEFMAP(AST_New, basic_sourcemap_gen);
            DEFMAP(AST_Try, basic_sourcemap_gen);
            DEFMAP(AST_Catch, basic_sourcemap_gen);
            DEFMAP(AST_Finally, basic_sourcemap_gen);
            DEFMAP(AST_Definitions, basic_sourcemap_gen);
            DEFMAP(AST_Constant, basic_sourcemap_gen);
            DEFMAP(AST_ObjectProperty, function(self, output){
                output.add_mapping(self.start, self.key);
            });
        
        })();
        
      • parse.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
            Parser based on parse-js (http://marijn.haverbeke.nl/parse-js/).
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with';
        var KEYWORDS_ATOM = 'false null true';
        var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile yield'
            + " " + KEYWORDS_ATOM + " " + KEYWORDS;
        var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case';
        
        KEYWORDS = makePredicate(KEYWORDS);
        RESERVED_WORDS = makePredicate(RESERVED_WORDS);
        KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION);
        KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);
        
        var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
        
        var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
        var RE_OCT_NUMBER = /^0[0-7]+$/;
        var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
        
        var OPERATORS = makePredicate([
            "in",
            "instanceof",
            "typeof",
            "new",
            "void",
            "delete",
            "++",
            "--",
            "+",
            "-",
            "!",
            "~",
            "&",
            "|",
            "^",
            "*",
            "/",
            "%",
            ">>",
            "<<",
            ">>>",
            "<",
            ">",
            "<=",
            ">=",
            "==",
            "===",
            "!=",
            "!==",
            "?",
            "=",
            "+=",
            "-=",
            "/=",
            "*=",
            "%=",
            ">>=",
            "<<=",
            ">>>=",
            "|=",
            "^=",
            "&=",
            "&&",
            "||"
        ]);
        
        var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000"));
        
        var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
        
        var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
        
        var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
        
        /* -----[ Tokenizer ]----- */
        
        // regexps adapted from http://xregexp.com/plugins/#unicode
        var UNICODE = {
            letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B2\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),
            digit: new RegExp("[\\u0030-\\u0039\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0DE6-\\u0DEF\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\u1040-\\u1049\\u1090-\\u1099\\u17E0-\\u17E9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19D9\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\uA620-\\uA629\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uA9F0-\\uA9F9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19]"),
            non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"),
            space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"),
            connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]")
        };
        
        function is_letter(code) {
            return (code >= 97 && code <= 122)
                || (code >= 65 && code <= 90)
                || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code)));
        };
        
        function is_digit(code) {
            return code >= 48 && code <= 57;
        };
        
        function is_alphanumeric_char(code) {
            return is_digit(code) || is_letter(code);
        };
        
        function is_unicode_digit(code) {
            return UNICODE.digit.test(String.fromCharCode(code));
        }
        
        function is_unicode_combining_mark(ch) {
            return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
        };
        
        function is_unicode_connector_punctuation(ch) {
            return UNICODE.connector_punctuation.test(ch);
        };
        
        function is_identifier(name) {
            return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name);
        };
        
        function is_identifier_start(code) {
            return code == 36 || code == 95 || is_letter(code);
        };
        
        function is_identifier_char(ch) {
            var code = ch.charCodeAt(0);
            return is_identifier_start(code)
                || is_digit(code)
                || code == 8204 // \u200c: zero-width non-joiner <ZWNJ>
                || code == 8205 // \u200d: zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)
                || is_unicode_combining_mark(ch)
                || is_unicode_connector_punctuation(ch)
                || is_unicode_digit(code)
            ;
        };
        
        function is_identifier_string(str){
            return /^[a-z_$][a-z0-9_$]*$/i.test(str);
        };
        
        function parse_js_number(num) {
            if (RE_HEX_NUMBER.test(num)) {
                return parseInt(num.substr(2), 16);
            } else if (RE_OCT_NUMBER.test(num)) {
                return parseInt(num.substr(1), 8);
            } else if (RE_DEC_NUMBER.test(num)) {
                return parseFloat(num);
            }
        };
        
        function JS_Parse_Error(message, line, col, pos) {
            this.message = message;
            this.line = line;
            this.col = col;
            this.pos = pos;
            this.stack = new Error().stack;
        };
        
        JS_Parse_Error.prototype.toString = function() {
            return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
        };
        
        function js_error(message, filename, line, col, pos) {
            throw new JS_Parse_Error(message, line, col, pos);
        };
        
        function is_token(token, type, val) {
            return token.type == type && (val == null || token.value == val);
        };
        
        var EX_EOF = {};
        
        function tokenizer($TEXT, filename, html5_comments) {
        
            var S = {
                text            : $TEXT.replace(/\uFEFF/g, ''),
                filename        : filename,
                pos             : 0,
                tokpos          : 0,
                line            : 1,
                tokline         : 0,
                col             : 0,
                tokcol          : 0,
                newline_before  : false,
                regex_allowed   : false,
                comments_before : []
            };
        
            function peek() { return S.text.charAt(S.pos); };
        
            function next(signal_eof, in_string) {
                var ch = S.text.charAt(S.pos++);
                if (signal_eof && !ch)
                    throw EX_EOF;
                if ("\r\n\u2028\u2029".indexOf(ch) >= 0) {
                    S.newline_before = S.newline_before || !in_string;
                    ++S.line;
                    S.col = 0;
                    if (!in_string && ch == "\r" && peek() == "\n") {
                        // treat a \r\n sequence as a single \n
                        ++S.pos;
                        ch = "\n";
                    }
                } else {
                    ++S.col;
                }
                return ch;
            };
        
            function forward(i) {
                while (i-- > 0) next();
            };
        
            function looking_at(str) {
                return S.text.substr(S.pos, str.length) == str;
            };
        
            function find(what, signal_eof) {
                var pos = S.text.indexOf(what, S.pos);
                if (signal_eof && pos == -1) throw EX_EOF;
                return pos;
            };
        
            function start_token() {
                S.tokline = S.line;
                S.tokcol = S.col;
                S.tokpos = S.pos;
            };
        
            var prev_was_dot = false;
            function token(type, value, is_comment) {
                S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX(value)) ||
                                   (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) ||
                                   (type == "punc" && PUNC_BEFORE_EXPRESSION(value)));
                prev_was_dot = (type == "punc" && value == ".");
                var ret = {
                    type    : type,
                    value   : value,
                    line    : S.tokline,
                    col     : S.tokcol,
                    pos     : S.tokpos,
                    endline : S.line,
                    endcol  : S.col,
                    endpos  : S.pos,
                    nlb     : S.newline_before,
                    file    : filename
                };
                if (!is_comment) {
                    ret.comments_before = S.comments_before;
                    S.comments_before = [];
                    // make note of any newlines in the comments that came before
                    for (var i = 0, len = ret.comments_before.length; i < len; i++) {
                        ret.nlb = ret.nlb || ret.comments_before[i].nlb;
                    }
                }
                S.newline_before = false;
                return new AST_Token(ret);
            };
        
            function skip_whitespace() {
                while (WHITESPACE_CHARS(peek()))
                    next();
            };
        
            function read_while(pred) {
                var ret = "", ch, i = 0;
                while ((ch = peek()) && pred(ch, i++))
                    ret += next();
                return ret;
            };
        
            function parse_error(err) {
                js_error(err, filename, S.tokline, S.tokcol, S.tokpos);
            };
        
            function read_num(prefix) {
                var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
                var num = read_while(function(ch, i){
                    var code = ch.charCodeAt(0);
                    switch (code) {
                      case 120: case 88: // xX
                        return has_x ? false : (has_x = true);
                      case 101: case 69: // eE
                        return has_x ? true : has_e ? false : (has_e = after_e = true);
                      case 45: // -
                        return after_e || (i == 0 && !prefix);
                      case 43: // +
                        return after_e;
                      case (after_e = false, 46): // .
                        return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false;
                    }
                    return is_alphanumeric_char(code);
                });
                if (prefix) num = prefix + num;
                var valid = parse_js_number(num);
                if (!isNaN(valid)) {
                    return token("num", valid);
                } else {
                    parse_error("Invalid syntax: " + num);
                }
            };
        
            function read_escaped_char(in_string) {
                var ch = next(true, in_string);
                switch (ch.charCodeAt(0)) {
                  case 110 : return "\n";
                  case 114 : return "\r";
                  case 116 : return "\t";
                  case 98  : return "\b";
                  case 118 : return "\u000b"; // \v
                  case 102 : return "\f";
                  case 48  : return "\0";
                  case 120 : return String.fromCharCode(hex_bytes(2)); // \x
                  case 117 : return String.fromCharCode(hex_bytes(4)); // \u
                  case 10  : return ""; // newline
                  default  : return ch;
                }
            };
        
            function hex_bytes(n) {
                var num = 0;
                for (; n > 0; --n) {
                    var digit = parseInt(next(true), 16);
                    if (isNaN(digit))
                        parse_error("Invalid hex-character pattern in string");
                    num = (num << 4) | digit;
                }
                return num;
            };
        
            var read_string = with_eof_error("Unterminated string constant", function(quote_char){
                var quote = next(), ret = "";
                for (;;) {
                    var ch = next(true);
                    if (ch == "\\") {
                        // read OctalEscapeSequence (XXX: deprecated if "strict mode")
                        // https://github.com/mishoo/UglifyJS/issues/178
                        var octal_len = 0, first = null;
                        ch = read_while(function(ch){
                            if (ch >= "0" && ch <= "7") {
                                if (!first) {
                                    first = ch;
                                    return ++octal_len;
                                }
                                else if (first <= "3" && octal_len <= 2) return ++octal_len;
                                else if (first >= "4" && octal_len <= 1) return ++octal_len;
                            }
                            return false;
                        });
                        if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8));
                        else ch = read_escaped_char(true);
                    }
                    else if (ch == quote) break;
                    ret += ch;
                }
                var tok = token("string", ret);
                tok.quote = quote_char;
                return tok;
            });
        
            function skip_line_comment(type) {
                var regex_allowed = S.regex_allowed;
                var i = find("\n"), ret;
                if (i == -1) {
                    ret = S.text.substr(S.pos);
                    S.pos = S.text.length;
                } else {
                    ret = S.text.substring(S.pos, i);
                    S.pos = i;
                }
                S.col = S.tokcol + (S.pos - S.tokpos);
                S.comments_before.push(token(type, ret, true));
                S.regex_allowed = regex_allowed;
                return next_token();
            };
        
            var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function(){
                var regex_allowed = S.regex_allowed;
                var i = find("*/", true);
                var text = S.text.substring(S.pos, i);
                var a = text.split("\n"), n = a.length;
                // update stream position
                S.pos = i + 2;
                S.line += n - 1;
                if (n > 1) S.col = a[n - 1].length;
                else S.col += a[n - 1].length;
                S.col += 2;
                var nlb = S.newline_before = S.newline_before || text.indexOf("\n") >= 0;
                S.comments_before.push(token("comment2", text, true));
                S.regex_allowed = regex_allowed;
                S.newline_before = nlb;
                return next_token();
            });
        
            function read_name() {
                var backslash = false, name = "", ch, escaped = false, hex;
                while ((ch = peek()) != null) {
                    if (!backslash) {
                        if (ch == "\\") escaped = backslash = true, next();
                        else if (is_identifier_char(ch)) name += next();
                        else break;
                    }
                    else {
                        if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
                        ch = read_escaped_char();
                        if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
                        name += ch;
                        backslash = false;
                    }
                }
                if (KEYWORDS(name) && escaped) {
                    hex = name.charCodeAt(0).toString(16).toUpperCase();
                    name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
                }
                return name;
            };
        
            var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){
                var prev_backslash = false, ch, in_class = false;
                while ((ch = next(true))) if (prev_backslash) {
                    regexp += "\\" + ch;
                    prev_backslash = false;
                } else if (ch == "[") {
                    in_class = true;
                    regexp += ch;
                } else if (ch == "]" && in_class) {
                    in_class = false;
                    regexp += ch;
                } else if (ch == "/" && !in_class) {
                    break;
                } else if (ch == "\\") {
                    prev_backslash = true;
                } else {
                    regexp += ch;
                }
                var mods = read_name();
                return token("regexp", new RegExp(regexp, mods));
            });
        
            function read_operator(prefix) {
                function grow(op) {
                    if (!peek()) return op;
                    var bigger = op + peek();
                    if (OPERATORS(bigger)) {
                        next();
                        return grow(bigger);
                    } else {
                        return op;
                    }
                };
                return token("operator", grow(prefix || next()));
            };
        
            function handle_slash() {
                next();
                switch (peek()) {
                  case "/":
                    next();
                    return skip_line_comment("comment1");
                  case "*":
                    next();
                    return skip_multiline_comment();
                }
                return S.regex_allowed ? read_regexp("") : read_operator("/");
            };
        
            function handle_dot() {
                next();
                return is_digit(peek().charCodeAt(0))
                    ? read_num(".")
                    : token("punc", ".");
            };
        
            function read_word() {
                var word = read_name();
                if (prev_was_dot) return token("name", word);
                return KEYWORDS_ATOM(word) ? token("atom", word)
                    : !KEYWORDS(word) ? token("name", word)
                    : OPERATORS(word) ? token("operator", word)
                    : token("keyword", word);
            };
        
            function with_eof_error(eof_error, cont) {
                return function(x) {
                    try {
                        return cont(x);
                    } catch(ex) {
                        if (ex === EX_EOF) parse_error(eof_error);
                        else throw ex;
                    }
                };
            };
        
            function next_token(force_regexp) {
                if (force_regexp != null)
                    return read_regexp(force_regexp);
                skip_whitespace();
                start_token();
                if (html5_comments) {
                    if (looking_at("<!--")) {
                        forward(4);
                        return skip_line_comment("comment3");
                    }
                    if (looking_at("-->") && S.newline_before) {
                        forward(3);
                        return skip_line_comment("comment4");
                    }
                }
                var ch = peek();
                if (!ch) return token("eof");
                var code = ch.charCodeAt(0);
                switch (code) {
                  case 34: case 39: return read_string(ch);
                  case 46: return handle_dot();
                  case 47: return handle_slash();
                }
                if (is_digit(code)) return read_num();
                if (PUNC_CHARS(ch)) return token("punc", next());
                if (OPERATOR_CHARS(ch)) return read_operator();
                if (code == 92 || is_identifier_start(code)) return read_word();
                parse_error("Unexpected character '" + ch + "'");
            };
        
            next_token.context = function(nc) {
                if (nc) S = nc;
                return S;
            };
        
            return next_token;
        
        };
        
        /* -----[ Parser (constants) ]----- */
        
        var UNARY_PREFIX = makePredicate([
            "typeof",
            "void",
            "delete",
            "--",
            "++",
            "!",
            "~",
            "-",
            "+"
        ]);
        
        var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
        
        var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
        
        var PRECEDENCE = (function(a, ret){
            for (var i = 0; i < a.length; ++i) {
                var b = a[i];
                for (var j = 0; j < b.length; ++j) {
                    ret[b[j]] = i + 1;
                }
            }
            return ret;
        })(
            [
                ["||"],
                ["&&"],
                ["|"],
                ["^"],
                ["&"],
                ["==", "===", "!=", "!=="],
                ["<", ">", "<=", ">=", "in", "instanceof"],
                [">>", "<<", ">>>"],
                ["+", "-"],
                ["*", "/", "%"]
            ],
            {}
        );
        
        var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
        
        var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
        
        /* -----[ Parser ]----- */
        
        function parse($TEXT, options) {
        
            options = defaults(options, {
                strict         : false,
                filename       : null,
                toplevel       : null,
                expression     : false,
                html5_comments : true,
                bare_returns   : false,
            });
        
            var S = {
                input         : (typeof $TEXT == "string"
                                 ? tokenizer($TEXT, options.filename,
                                             options.html5_comments)
                                 : $TEXT),
                token         : null,
                prev          : null,
                peeked        : null,
                in_function   : 0,
                in_directives : true,
                in_loop       : 0,
                labels        : []
            };
        
            S.token = next();
        
            function is(type, value) {
                return is_token(S.token, type, value);
            };
        
            function peek() { return S.peeked || (S.peeked = S.input()); };
        
            function next() {
                S.prev = S.token;
                if (S.peeked) {
                    S.token = S.peeked;
                    S.peeked = null;
                } else {
                    S.token = S.input();
                }
                S.in_directives = S.in_directives && (
                    S.token.type == "string" || is("punc", ";")
                );
                return S.token;
            };
        
            function prev() {
                return S.prev;
            };
        
            function croak(msg, line, col, pos) {
                var ctx = S.input.context();
                js_error(msg,
                         ctx.filename,
                         line != null ? line : ctx.tokline,
                         col != null ? col : ctx.tokcol,
                         pos != null ? pos : ctx.tokpos);
            };
        
            function token_error(token, msg) {
                croak(msg, token.line, token.col);
            };
        
            function unexpected(token) {
                if (token == null)
                    token = S.token;
                token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
            };
        
            function expect_token(type, val) {
                if (is(type, val)) {
                    return next();
                }
                token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
            };
        
            function expect(punc) { return expect_token("punc", punc); };
        
            function can_insert_semicolon() {
                return !options.strict && (
                    S.token.nlb || is("eof") || is("punc", "}")
                );
            };
        
            function semicolon() {
                if (is("punc", ";")) next();
                else if (!can_insert_semicolon()) unexpected();
            };
        
            function parenthesised() {
                expect("(");
                var exp = expression(true);
                expect(")");
                return exp;
            };
        
            function embed_tokens(parser) {
                return function() {
                    var start = S.token;
                    var expr = parser();
                    var end = prev();
                    expr.start = start;
                    expr.end = end;
                    return expr;
                };
            };
        
            function handle_regexp() {
                if (is("operator", "/") || is("operator", "/=")) {
                    S.peeked = null;
                    S.token = S.input(S.token.value.substr(1)); // force regexp
                }
            };
        
            var statement = embed_tokens(function() {
                var tmp;
                handle_regexp();
                switch (S.token.type) {
                  case "string":
                    var dir = S.in_directives, stat = simple_statement();
                    // XXXv2: decide how to fix directives
                    if (dir && stat.body instanceof AST_String && !is("punc", ",")) {
                        return new AST_Directive({
                            start : stat.body.start,
                            end   : stat.body.end,
                            quote : stat.body.quote,
                            value : stat.body.value,
                        });
                    }
                    return stat;
                  case "num":
                  case "regexp":
                  case "operator":
                  case "atom":
                    return simple_statement();
        
                  case "name":
                    return is_token(peek(), "punc", ":")
                        ? labeled_statement()
                        : simple_statement();
        
                  case "punc":
                    switch (S.token.value) {
                      case "{":
                        return new AST_BlockStatement({
                            start : S.token,
                            body  : block_(),
                            end   : prev()
                        });
                      case "[":
                      case "(":
                        return simple_statement();
                      case ";":
                        next();
                        return new AST_EmptyStatement();
                      default:
                        unexpected();
                    }
        
                  case "keyword":
                    switch (tmp = S.token.value, next(), tmp) {
                      case "break":
                        return break_cont(AST_Break);
        
                      case "continue":
                        return break_cont(AST_Continue);
        
                      case "debugger":
                        semicolon();
                        return new AST_Debugger();
        
                      case "do":
                        return new AST_Do({
                            body      : in_loop(statement),
                            condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), tmp)
                        });
        
                      case "while":
                        return new AST_While({
                            condition : parenthesised(),
                            body      : in_loop(statement)
                        });
        
                      case "for":
                        return for_();
        
                      case "function":
                        return function_(AST_Defun);
        
                      case "if":
                        return if_();
        
                      case "return":
                        if (S.in_function == 0 && !options.bare_returns)
                            croak("'return' outside of function");
                        return new AST_Return({
                            value: ( is("punc", ";")
                                     ? (next(), null)
                                     : can_insert_semicolon()
                                     ? null
                                     : (tmp = expression(true), semicolon(), tmp) )
                        });
        
                      case "switch":
                        return new AST_Switch({
                            expression : parenthesised(),
                            body       : in_loop(switch_body_)
                        });
        
                      case "throw":
                        if (S.token.nlb)
                            croak("Illegal newline after 'throw'");
                        return new AST_Throw({
                            value: (tmp = expression(true), semicolon(), tmp)
                        });
        
                      case "try":
                        return try_();
        
                      case "var":
                        return tmp = var_(), semicolon(), tmp;
        
                      case "const":
                        return tmp = const_(), semicolon(), tmp;
        
                      case "with":
                        return new AST_With({
                            expression : parenthesised(),
                            body       : statement()
                        });
        
                      default:
                        unexpected();
                    }
                }
            });
        
            function labeled_statement() {
                var label = as_symbol(AST_Label);
                if (find_if(function(l){ return l.name == label.name }, S.labels)) {
                    // ECMA-262, 12.12: An ECMAScript program is considered
                    // syntactically incorrect if it contains a
                    // LabelledStatement that is enclosed by a
                    // LabelledStatement with the same Identifier as label.
                    croak("Label " + label.name + " defined twice");
                }
                expect(":");
                S.labels.push(label);
                var stat = statement();
                S.labels.pop();
                if (!(stat instanceof AST_IterationStatement)) {
                    // check for `continue` that refers to this label.
                    // those should be reported as syntax errors.
                    // https://github.com/mishoo/UglifyJS2/issues/287
                    label.references.forEach(function(ref){
                        if (ref instanceof AST_Continue) {
                            ref = ref.label.start;
                            croak("Continue label `" + label.name + "` refers to non-IterationStatement.",
                                  ref.line, ref.col, ref.pos);
                        }
                    });
                }
                return new AST_LabeledStatement({ body: stat, label: label });
            };
        
            function simple_statement(tmp) {
                return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) });
            };
        
            function break_cont(type) {
                var label = null, ldef;
                if (!can_insert_semicolon()) {
                    label = as_symbol(AST_LabelRef, true);
                }
                if (label != null) {
                    ldef = find_if(function(l){ return l.name == label.name }, S.labels);
                    if (!ldef)
                        croak("Undefined label " + label.name);
                    label.thedef = ldef;
                }
                else if (S.in_loop == 0)
                    croak(type.TYPE + " not inside a loop or switch");
                semicolon();
                var stat = new type({ label: label });
                if (ldef) ldef.references.push(stat);
                return stat;
            };
        
            function for_() {
                expect("(");
                var init = null;
                if (!is("punc", ";")) {
                    init = is("keyword", "var")
                        ? (next(), var_(true))
                        : expression(true, true);
                    if (is("operator", "in")) {
                        if (init instanceof AST_Var && init.definitions.length > 1)
                            croak("Only one variable declaration allowed in for..in loop");
                        next();
                        return for_in(init);
                    }
                }
                return regular_for(init);
            };
        
            function regular_for(init) {
                expect(";");
                var test = is("punc", ";") ? null : expression(true);
                expect(";");
                var step = is("punc", ")") ? null : expression(true);
                expect(")");
                return new AST_For({
                    init      : init,
                    condition : test,
                    step      : step,
                    body      : in_loop(statement)
                });
            };
        
            function for_in(init) {
                var lhs = init instanceof AST_Var ? init.definitions[0].name : null;
                var obj = expression(true);
                expect(")");
                return new AST_ForIn({
                    init   : init,
                    name   : lhs,
                    object : obj,
                    body   : in_loop(statement)
                });
            };
        
            var function_ = function(ctor) {
                var in_statement = ctor === AST_Defun;
                var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
                if (in_statement && !name)
                    unexpected();
                expect("(");
                return new ctor({
                    name: name,
                    argnames: (function(first, a){
                        while (!is("punc", ")")) {
                            if (first) first = false; else expect(",");
                            a.push(as_symbol(AST_SymbolFunarg));
                        }
                        next();
                        return a;
                    })(true, []),
                    body: (function(loop, labels){
                        ++S.in_function;
                        S.in_directives = true;
                        S.in_loop = 0;
                        S.labels = [];
                        var a = block_();
                        --S.in_function;
                        S.in_loop = loop;
                        S.labels = labels;
                        return a;
                    })(S.in_loop, S.labels)
                });
            };
        
            function if_() {
                var cond = parenthesised(), body = statement(), belse = null;
                if (is("keyword", "else")) {
                    next();
                    belse = statement();
                }
                return new AST_If({
                    condition   : cond,
                    body        : body,
                    alternative : belse
                });
            };
        
            function block_() {
                expect("{");
                var a = [];
                while (!is("punc", "}")) {
                    if (is("eof")) unexpected();
                    a.push(statement());
                }
                next();
                return a;
            };
        
            function switch_body_() {
                expect("{");
                var a = [], cur = null, branch = null, tmp;
                while (!is("punc", "}")) {
                    if (is("eof")) unexpected();
                    if (is("keyword", "case")) {
                        if (branch) branch.end = prev();
                        cur = [];
                        branch = new AST_Case({
                            start      : (tmp = S.token, next(), tmp),
                            expression : expression(true),
                            body       : cur
                        });
                        a.push(branch);
                        expect(":");
                    }
                    else if (is("keyword", "default")) {
                        if (branch) branch.end = prev();
                        cur = [];
                        branch = new AST_Default({
                            start : (tmp = S.token, next(), expect(":"), tmp),
                            body  : cur
                        });
                        a.push(branch);
                    }
                    else {
                        if (!cur) unexpected();
                        cur.push(statement());
                    }
                }
                if (branch) branch.end = prev();
                next();
                return a;
            };
        
            function try_() {
                var body = block_(), bcatch = null, bfinally = null;
                if (is("keyword", "catch")) {
                    var start = S.token;
                    next();
                    expect("(");
                    var name = as_symbol(AST_SymbolCatch);
                    expect(")");
                    bcatch = new AST_Catch({
                        start   : start,
                        argname : name,
                        body    : block_(),
                        end     : prev()
                    });
                }
                if (is("keyword", "finally")) {
                    var start = S.token;
                    next();
                    bfinally = new AST_Finally({
                        start : start,
                        body  : block_(),
                        end   : prev()
                    });
                }
                if (!bcatch && !bfinally)
                    croak("Missing catch/finally blocks");
                return new AST_Try({
                    body     : body,
                    bcatch   : bcatch,
                    bfinally : bfinally
                });
            };
        
            function vardefs(no_in, in_const) {
                var a = [];
                for (;;) {
                    a.push(new AST_VarDef({
                        start : S.token,
                        name  : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
                        value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
                        end   : prev()
                    }));
                    if (!is("punc", ","))
                        break;
                    next();
                }
                return a;
            };
        
            var var_ = function(no_in) {
                return new AST_Var({
                    start       : prev(),
                    definitions : vardefs(no_in, false),
                    end         : prev()
                });
            };
        
            var const_ = function() {
                return new AST_Const({
                    start       : prev(),
                    definitions : vardefs(false, true),
                    end         : prev()
                });
            };
        
            var new_ = function() {
                var start = S.token;
                expect_token("operator", "new");
                var newexp = expr_atom(false), args;
                if (is("punc", "(")) {
                    next();
                    args = expr_list(")");
                } else {
                    args = [];
                }
                return subscripts(new AST_New({
                    start      : start,
                    expression : newexp,
                    args       : args,
                    end        : prev()
                }), true);
            };
        
            function as_atom_node() {
                var tok = S.token, ret;
                switch (tok.type) {
                  case "name":
                  case "keyword":
                    ret = _make_symbol(AST_SymbolRef);
                    break;
                  case "num":
                    ret = new AST_Number({ start: tok, end: tok, value: tok.value });
                    break;
                  case "string":
                    ret = new AST_String({
                        start : tok,
                        end   : tok,
                        value : tok.value,
                        quote : tok.quote
                    });
                    break;
                  case "regexp":
                    ret = new AST_RegExp({ start: tok, end: tok, value: tok.value });
                    break;
                  case "atom":
                    switch (tok.value) {
                      case "false":
                        ret = new AST_False({ start: tok, end: tok });
                        break;
                      case "true":
                        ret = new AST_True({ start: tok, end: tok });
                        break;
                      case "null":
                        ret = new AST_Null({ start: tok, end: tok });
                        break;
                    }
                    break;
                }
                next();
                return ret;
            };
        
            var expr_atom = function(allow_calls) {
                if (is("operator", "new")) {
                    return new_();
                }
                var start = S.token;
                if (is("punc")) {
                    switch (start.value) {
                      case "(":
                        next();
                        var ex = expression(true);
                        ex.start = start;
                        ex.end = S.token;
                        expect(")");
                        return subscripts(ex, allow_calls);
                      case "[":
                        return subscripts(array_(), allow_calls);
                      case "{":
                        return subscripts(object_(), allow_calls);
                    }
                    unexpected();
                }
                if (is("keyword", "function")) {
                    next();
                    var func = function_(AST_Function);
                    func.start = start;
                    func.end = prev();
                    return subscripts(func, allow_calls);
                }
                if (ATOMIC_START_TOKEN[S.token.type]) {
                    return subscripts(as_atom_node(), allow_calls);
                }
                unexpected();
            };
        
            function expr_list(closing, allow_trailing_comma, allow_empty) {
                var first = true, a = [];
                while (!is("punc", closing)) {
                    if (first) first = false; else expect(",");
                    if (allow_trailing_comma && is("punc", closing)) break;
                    if (is("punc", ",") && allow_empty) {
                        a.push(new AST_Hole({ start: S.token, end: S.token }));
                    } else {
                        a.push(expression(false));
                    }
                }
                next();
                return a;
            };
        
            var array_ = embed_tokens(function() {
                expect("[");
                return new AST_Array({
                    elements: expr_list("]", !options.strict, true)
                });
            });
        
            var object_ = embed_tokens(function() {
                expect("{");
                var first = true, a = [];
                while (!is("punc", "}")) {
                    if (first) first = false; else expect(",");
                    if (!options.strict && is("punc", "}"))
                        // allow trailing comma
                        break;
                    var start = S.token;
                    var type = start.type;
                    var name = as_property_name();
                    if (type == "name" && !is("punc", ":")) {
                        if (name == "get") {
                            a.push(new AST_ObjectGetter({
                                start : start,
                                key   : as_atom_node(),
                                value : function_(AST_Accessor),
                                end   : prev()
                            }));
                            continue;
                        }
                        if (name == "set") {
                            a.push(new AST_ObjectSetter({
                                start : start,
                                key   : as_atom_node(),
                                value : function_(AST_Accessor),
                                end   : prev()
                            }));
                            continue;
                        }
                    }
                    expect(":");
                    a.push(new AST_ObjectKeyVal({
                        start : start,
                        quote : start.quote,
                        key   : name,
                        value : expression(false),
                        end   : prev()
                    }));
                }
                next();
                return new AST_Object({ properties: a });
            });
        
            function as_property_name() {
                var tmp = S.token;
                next();
                switch (tmp.type) {
                  case "num":
                  case "string":
                  case "name":
                  case "operator":
                  case "keyword":
                  case "atom":
                    return tmp.value;
                  default:
                    unexpected();
                }
            };
        
            function as_name() {
                var tmp = S.token;
                next();
                switch (tmp.type) {
                  case "name":
                  case "operator":
                  case "keyword":
                  case "atom":
                    return tmp.value;
                  default:
                    unexpected();
                }
            };
        
            function _make_symbol(type) {
                var name = S.token.value;
                return new (name == "this" ? AST_This : type)({
                    name  : String(name),
                    start : S.token,
                    end   : S.token
                });
            };
        
            function as_symbol(type, noerror) {
                if (!is("name")) {
                    if (!noerror) croak("Name expected");
                    return null;
                }
                var sym = _make_symbol(type);
                next();
                return sym;
            };
        
            var subscripts = function(expr, allow_calls) {
                var start = expr.start;
                if (is("punc", ".")) {
                    next();
                    return subscripts(new AST_Dot({
                        start      : start,
                        expression : expr,
                        property   : as_name(),
                        end        : prev()
                    }), allow_calls);
                }
                if (is("punc", "[")) {
                    next();
                    var prop = expression(true);
                    expect("]");
                    return subscripts(new AST_Sub({
                        start      : start,
                        expression : expr,
                        property   : prop,
                        end        : prev()
                    }), allow_calls);
                }
                if (allow_calls && is("punc", "(")) {
                    next();
                    return subscripts(new AST_Call({
                        start      : start,
                        expression : expr,
                        args       : expr_list(")"),
                        end        : prev()
                    }), true);
                }
                return expr;
            };
        
            var maybe_unary = function(allow_calls) {
                var start = S.token;
                if (is("operator") && UNARY_PREFIX(start.value)) {
                    next();
                    handle_regexp();
                    var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls));
                    ex.start = start;
                    ex.end = prev();
                    return ex;
                }
                var val = expr_atom(allow_calls);
                while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) {
                    val = make_unary(AST_UnaryPostfix, S.token.value, val);
                    val.start = start;
                    val.end = S.token;
                    next();
                }
                return val;
            };
        
            function make_unary(ctor, op, expr) {
                if ((op == "++" || op == "--") && !is_assignable(expr))
                    croak("Invalid use of " + op + " operator");
                return new ctor({ operator: op, expression: expr });
            };
        
            var expr_op = function(left, min_prec, no_in) {
                var op = is("operator") ? S.token.value : null;
                if (op == "in" && no_in) op = null;
                var prec = op != null ? PRECEDENCE[op] : null;
                if (prec != null && prec > min_prec) {
                    next();
                    var right = expr_op(maybe_unary(true), prec, no_in);
                    return expr_op(new AST_Binary({
                        start    : left.start,
                        left     : left,
                        operator : op,
                        right    : right,
                        end      : right.end
                    }), min_prec, no_in);
                }
                return left;
            };
        
            function expr_ops(no_in) {
                return expr_op(maybe_unary(true), 0, no_in);
            };
        
            var maybe_conditional = function(no_in) {
                var start = S.token;
                var expr = expr_ops(no_in);
                if (is("operator", "?")) {
                    next();
                    var yes = expression(false);
                    expect(":");
                    return new AST_Conditional({
                        start       : start,
                        condition   : expr,
                        consequent  : yes,
                        alternative : expression(false, no_in),
                        end         : prev()
                    });
                }
                return expr;
            };
        
            function is_assignable(expr) {
                if (!options.strict) return true;
                if (expr instanceof AST_This) return false;
                return (expr instanceof AST_PropAccess || expr instanceof AST_Symbol);
            };
        
            var maybe_assign = function(no_in) {
                var start = S.token;
                var left = maybe_conditional(no_in), val = S.token.value;
                if (is("operator") && ASSIGNMENT(val)) {
                    if (is_assignable(left)) {
                        next();
                        return new AST_Assign({
                            start    : start,
                            left     : left,
                            operator : val,
                            right    : maybe_assign(no_in),
                            end      : prev()
                        });
                    }
                    croak("Invalid assignment");
                }
                return left;
            };
        
            var expression = function(commas, no_in) {
                var start = S.token;
                var expr = maybe_assign(no_in);
                if (commas && is("punc", ",")) {
                    next();
                    return new AST_Seq({
                        start  : start,
                        car    : expr,
                        cdr    : expression(true, no_in),
                        end    : peek()
                    });
                }
                return expr;
            };
        
            function in_loop(cont) {
                ++S.in_loop;
                var ret = cont();
                --S.in_loop;
                return ret;
            };
        
            if (options.expression) {
                return expression(true);
            }
        
            return (function(){
                var start = S.token;
                var body = [];
                while (!is("eof"))
                    body.push(statement());
                var end = prev();
                var toplevel = options.toplevel;
                if (toplevel) {
                    toplevel.body = toplevel.body.concat(body);
                    toplevel.end = end;
                } else {
                    toplevel = new AST_Toplevel({ start: start, body: body, end: end });
                }
                return toplevel;
            })();
        
        };
        
      • scope.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        function SymbolDef(scope, index, orig) {
            this.name = orig.name;
            this.orig = [ orig ];
            this.scope = scope;
            this.references = [];
            this.global = false;
            this.mangled_name = null;
            this.undeclared = false;
            this.constant = false;
            this.index = index;
        };
        
        SymbolDef.prototype = {
            unmangleable: function(options) {
                if (!options) options = {};
        
                return (this.global && !options.toplevel)
                    || this.undeclared
                    || (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
                    || (options.keep_fnames
                        && (this.orig[0] instanceof AST_SymbolLambda
                            || this.orig[0] instanceof AST_SymbolDefun));
            },
            mangle: function(options) {
                if (!this.mangled_name && !this.unmangleable(options)) {
                    var s = this.scope;
                    if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda)
                        s = s.parent_scope;
                    this.mangled_name = s.next_mangled(options, this);
                }
            }
        };
        
        AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
            options = defaults(options, {
                screw_ie8: false
            });
        
            // pass 1: setup scope chaining and handle definitions
            var self = this;
            var scope = self.parent_scope = null;
            var defun = null;
            var nesting = 0;
            var tw = new TreeWalker(function(node, descend){
                if (options.screw_ie8 && node instanceof AST_Catch) {
                    var save_scope = scope;
                    scope = new AST_Scope(node);
                    scope.init_scope_vars(nesting);
                    scope.parent_scope = save_scope;
                    descend();
                    scope = save_scope;
                    return true;
                }
                if (node instanceof AST_Scope) {
                    node.init_scope_vars(nesting);
                    var save_scope = node.parent_scope = scope;
                    var save_defun = defun;
                    defun = scope = node;
                    ++nesting; descend(); --nesting;
                    scope = save_scope;
                    defun = save_defun;
                    return true;        // don't descend again in TreeWalker
                }
                if (node instanceof AST_Directive) {
                    node.scope = scope;
                    push_uniq(scope.directives, node.value);
                    return true;
                }
                if (node instanceof AST_With) {
                    for (var s = scope; s; s = s.parent_scope)
                        s.uses_with = true;
                    return;
                }
                if (node instanceof AST_Symbol) {
                    node.scope = scope;
                }
                if (node instanceof AST_SymbolLambda) {
                    defun.def_function(node);
                }
                else if (node instanceof AST_SymbolDefun) {
                    // Careful here, the scope where this should be defined is
                    // the parent scope.  The reason is that we enter a new
                    // scope when we encounter the AST_Defun node (which is
                    // instanceof AST_Scope) but we get to the symbol a bit
                    // later.
                    (node.scope = defun.parent_scope).def_function(node);
                }
                else if (node instanceof AST_SymbolVar
                         || node instanceof AST_SymbolConst) {
                    var def = defun.def_variable(node);
                    def.constant = node instanceof AST_SymbolConst;
                    def.init = tw.parent().value;
                }
                else if (node instanceof AST_SymbolCatch) {
                    (options.screw_ie8 ? scope : defun)
                        .def_variable(node);
                }
            });
            self.walk(tw);
        
            // pass 2: find back references and eval
            var func = null;
            var globals = self.globals = new Dictionary();
            var tw = new TreeWalker(function(node, descend){
                if (node instanceof AST_Lambda) {
                    var prev_func = func;
                    func = node;
                    descend();
                    func = prev_func;
                    return true;
                }
                if (node instanceof AST_SymbolRef) {
                    var name = node.name;
                    var sym = node.scope.find_variable(name);
                    if (!sym) {
                        var g;
                        if (globals.has(name)) {
                            g = globals.get(name);
                        } else {
                            g = new SymbolDef(self, globals.size(), node);
                            g.undeclared = true;
                            g.global = true;
                            globals.set(name, g);
                        }
                        node.thedef = g;
                        if (name == "eval" && tw.parent() instanceof AST_Call) {
                            for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope)
                                s.uses_eval = true;
                        }
                        if (func && name == "arguments") {
                            func.uses_arguments = true;
                        }
                    } else {
                        node.thedef = sym;
                    }
                    node.reference();
                    return true;
                }
            });
            self.walk(tw);
        });
        
        AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){
            this.directives = [];     // contains the directives defined in this scope, i.e. "use strict"
            this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
            this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
            this.uses_with = false;   // will be set to true if this or some nested scope uses the `with` statement
            this.uses_eval = false;   // will be set to true if this or nested scope uses the global `eval`
            this.parent_scope = null; // the parent scope
            this.enclosed = [];       // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
            this.cname = -1;          // the current index for mangling functions/variables
            this.nesting = nesting;   // the nesting level of this scope (0 means toplevel)
        });
        
        AST_Scope.DEFMETHOD("strict", function(){
            return this.has_directive("use strict");
        });
        
        AST_Lambda.DEFMETHOD("init_scope_vars", function(){
            AST_Scope.prototype.init_scope_vars.apply(this, arguments);
            this.uses_arguments = false;
        });
        
        AST_SymbolRef.DEFMETHOD("reference", function() {
            var def = this.definition();
            def.references.push(this);
            var s = this.scope;
            while (s) {
                push_uniq(s.enclosed, def);
                if (s === def.scope) break;
                s = s.parent_scope;
            }
            this.frame = this.scope.nesting - def.scope.nesting;
        });
        
        AST_Scope.DEFMETHOD("find_variable", function(name){
            if (name instanceof AST_Symbol) name = name.name;
            return this.variables.get(name)
                || (this.parent_scope && this.parent_scope.find_variable(name));
        });
        
        AST_Scope.DEFMETHOD("has_directive", function(value){
            return this.parent_scope && this.parent_scope.has_directive(value)
                || (this.directives.indexOf(value) >= 0 ? this : null);
        });
        
        AST_Scope.DEFMETHOD("def_function", function(symbol){
            this.functions.set(symbol.name, this.def_variable(symbol));
        });
        
        AST_Scope.DEFMETHOD("def_variable", function(symbol){
            var def;
            if (!this.variables.has(symbol.name)) {
                def = new SymbolDef(this, this.variables.size(), symbol);
                this.variables.set(symbol.name, def);
                def.global = !this.parent_scope;
            } else {
                def = this.variables.get(symbol.name);
                def.orig.push(symbol);
            }
            return symbol.thedef = def;
        });
        
        AST_Scope.DEFMETHOD("next_mangled", function(options){
            var ext = this.enclosed;
            out: while (true) {
                var m = base54(++this.cname);
                if (!is_identifier(m)) continue; // skip over "do"
        
                // https://github.com/mishoo/UglifyJS2/issues/242 -- do not
                // shadow a name excepted from mangling.
                if (options.except.indexOf(m) >= 0) continue;
        
                // we must ensure that the mangled name does not shadow a name
                // from some parent scope that is referenced in this or in
                // inner scopes.
                for (var i = ext.length; --i >= 0;) {
                    var sym = ext[i];
                    var name = sym.mangled_name || (sym.unmangleable(options) && sym.name);
                    if (m == name) continue out;
                }
                return m;
            }
        });
        
        AST_Function.DEFMETHOD("next_mangled", function(options, def){
            // #179, #326
            // in Safari strict mode, something like (function x(x){...}) is a syntax error;
            // a function expression's argument cannot shadow the function expression's name
        
            var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition();
            while (true) {
                var name = AST_Lambda.prototype.next_mangled.call(this, options, def);
                if (!(tricky_def && tricky_def.mangled_name == name))
                    return name;
            }
        });
        
        AST_Scope.DEFMETHOD("references", function(sym){
            if (sym instanceof AST_Symbol) sym = sym.definition();
            return this.enclosed.indexOf(sym) < 0 ? null : sym;
        });
        
        AST_Symbol.DEFMETHOD("unmangleable", function(options){
            return this.definition().unmangleable(options);
        });
        
        // property accessors are not mangleable
        AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){
            return true;
        });
        
        // labels are always mangleable
        AST_Label.DEFMETHOD("unmangleable", function(){
            return false;
        });
        
        AST_Symbol.DEFMETHOD("unreferenced", function(){
            return this.definition().references.length == 0
                && !(this.scope.uses_eval || this.scope.uses_with);
        });
        
        AST_Symbol.DEFMETHOD("undeclared", function(){
            return this.definition().undeclared;
        });
        
        AST_LabelRef.DEFMETHOD("undeclared", function(){
            return false;
        });
        
        AST_Label.DEFMETHOD("undeclared", function(){
            return false;
        });
        
        AST_Symbol.DEFMETHOD("definition", function(){
            return this.thedef;
        });
        
        AST_Symbol.DEFMETHOD("global", function(){
            return this.definition().global;
        });
        
        AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
            return defaults(options, {
                except      : [],
                eval        : false,
                sort        : false,
                toplevel    : false,
                screw_ie8   : false,
                keep_fnames : false
            });
        });
        
        AST_Toplevel.DEFMETHOD("mangle_names", function(options){
            options = this._default_mangler_options(options);
            // We only need to mangle declaration nodes.  Special logic wired
            // into the code generator will display the mangled name if it's
            // present (and for AST_SymbolRef-s it'll use the mangled name of
            // the AST_SymbolDeclaration that it points to).
            var lname = -1;
            var to_mangle = [];
            var tw = new TreeWalker(function(node, descend){
                if (node instanceof AST_LabeledStatement) {
                    // lname is incremented when we get to the AST_Label
                    var save_nesting = lname;
                    descend();
                    lname = save_nesting;
                    return true;        // don't descend again in TreeWalker
                }
                if (node instanceof AST_Scope) {
                    var p = tw.parent(), a = [];
                    node.variables.each(function(symbol){
                        if (options.except.indexOf(symbol.name) < 0) {
                            a.push(symbol);
                        }
                    });
                    if (options.sort) a.sort(function(a, b){
                        return b.references.length - a.references.length;
                    });
                    to_mangle.push.apply(to_mangle, a);
                    return;
                }
                if (node instanceof AST_Label) {
                    var name;
                    do name = base54(++lname); while (!is_identifier(name));
                    node.mangled_name = name;
                    return true;
                }
                if (options.screw_ie8 && node instanceof AST_SymbolCatch) {
                    to_mangle.push(node.definition());
                    return;
                }
            });
            this.walk(tw);
            to_mangle.forEach(function(def){ def.mangle(options) });
        });
        
        AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
            options = this._default_mangler_options(options);
            var tw = new TreeWalker(function(node){
                if (node instanceof AST_Constant)
                    base54.consider(node.print_to_string());
                else if (node instanceof AST_Return)
                    base54.consider("return");
                else if (node instanceof AST_Throw)
                    base54.consider("throw");
                else if (node instanceof AST_Continue)
                    base54.consider("continue");
                else if (node instanceof AST_Break)
                    base54.consider("break");
                else if (node instanceof AST_Debugger)
                    base54.consider("debugger");
                else if (node instanceof AST_Directive)
                    base54.consider(node.value);
                else if (node instanceof AST_While)
                    base54.consider("while");
                else if (node instanceof AST_Do)
                    base54.consider("do while");
                else if (node instanceof AST_If) {
                    base54.consider("if");
                    if (node.alternative) base54.consider("else");
                }
                else if (node instanceof AST_Var)
                    base54.consider("var");
                else if (node instanceof AST_Const)
                    base54.consider("const");
                else if (node instanceof AST_Lambda)
                    base54.consider("function");
                else if (node instanceof AST_For)
                    base54.consider("for");
                else if (node instanceof AST_ForIn)
                    base54.consider("for in");
                else if (node instanceof AST_Switch)
                    base54.consider("switch");
                else if (node instanceof AST_Case)
                    base54.consider("case");
                else if (node instanceof AST_Default)
                    base54.consider("default");
                else if (node instanceof AST_With)
                    base54.consider("with");
                else if (node instanceof AST_ObjectSetter)
                    base54.consider("set" + node.key);
                else if (node instanceof AST_ObjectGetter)
                    base54.consider("get" + node.key);
                else if (node instanceof AST_ObjectKeyVal)
                    base54.consider(node.key);
                else if (node instanceof AST_New)
                    base54.consider("new");
                else if (node instanceof AST_This)
                    base54.consider("this");
                else if (node instanceof AST_Try)
                    base54.consider("try");
                else if (node instanceof AST_Catch)
                    base54.consider("catch");
                else if (node instanceof AST_Finally)
                    base54.consider("finally");
                else if (node instanceof AST_Symbol && node.unmangleable(options))
                    base54.consider(node.name);
                else if (node instanceof AST_Unary || node instanceof AST_Binary)
                    base54.consider(node.operator);
                else if (node instanceof AST_Dot)
                    base54.consider(node.property);
            });
            this.walk(tw);
            base54.sort();
        });
        
        var base54 = (function() {
            var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
            var chars, frequency;
            function reset() {
                frequency = Object.create(null);
                chars = string.split("").map(function(ch){ return ch.charCodeAt(0) });
                chars.forEach(function(ch){ frequency[ch] = 0 });
            }
            base54.consider = function(str){
                for (var i = str.length; --i >= 0;) {
                    var code = str.charCodeAt(i);
                    if (code in frequency) ++frequency[code];
                }
            };
            base54.sort = function() {
                chars = mergeSort(chars, function(a, b){
                    if (is_digit(a) && !is_digit(b)) return 1;
                    if (is_digit(b) && !is_digit(a)) return -1;
                    return frequency[b] - frequency[a];
                });
            };
            base54.reset = reset;
            reset();
            base54.get = function(){ return chars };
            base54.freq = function(){ return frequency };
            function base54(num) {
                var ret = "", base = 54;
                num++;
                do {
                    num--;
                    ret += String.fromCharCode(chars[num % base]);
                    num = Math.floor(num / base);
                    base = 64;
                } while (num > 0);
                return ret;
            };
            return base54;
        })();
        
        AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
            options = defaults(options, {
                undeclared       : false, // this makes a lot of noise
                unreferenced     : true,
                assign_to_global : true,
                func_arguments   : true,
                nested_defuns    : true,
                eval             : true
            });
            var tw = new TreeWalker(function(node){
                if (options.undeclared
                    && node instanceof AST_SymbolRef
                    && node.undeclared())
                {
                    // XXX: this also warns about JS standard names,
                    // i.e. Object, Array, parseInt etc.  Should add a list of
                    // exceptions.
                    AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", {
                        name: node.name,
                        file: node.start.file,
                        line: node.start.line,
                        col: node.start.col
                    });
                }
                if (options.assign_to_global)
                {
                    var sym = null;
                    if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef)
                        sym = node.left;
                    else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef)
                        sym = node.init;
                    if (sym
                        && (sym.undeclared()
                            || (sym.global() && sym.scope !== sym.definition().scope))) {
                        AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", {
                            msg: sym.undeclared() ? "Accidental global?" : "Assignment to global",
                            name: sym.name,
                            file: sym.start.file,
                            line: sym.start.line,
                            col: sym.start.col
                        });
                    }
                }
                if (options.eval
                    && node instanceof AST_SymbolRef
                    && node.undeclared()
                    && node.name == "eval") {
                    AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start);
                }
                if (options.unreferenced
                    && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label)
                    && !(node instanceof AST_SymbolCatch)
                    && node.unreferenced()) {
                    AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
                        type: node instanceof AST_Label ? "Label" : "Symbol",
                        name: node.name,
                        file: node.start.file,
                        line: node.start.line,
                        col: node.start.col
                    });
                }
                if (options.func_arguments
                    && node instanceof AST_Lambda
                    && node.uses_arguments) {
                    AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", {
                        name: node.name ? node.name.name : "anonymous",
                        file: node.start.file,
                        line: node.start.line,
                        col: node.start.col
                    });
                }
                if (options.nested_defuns
                    && node instanceof AST_Defun
                    && !(tw.parent() instanceof AST_Scope)) {
                    AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", {
                        name: node.name.name,
                        type: tw.parent().TYPE,
                        file: node.start.file,
                        line: node.start.line,
                        col: node.start.col
                    });
                }
            });
            this.walk(tw);
        });
        
      • sourcemap.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        // a small wrapper around fitzgen's source-map library
        function SourceMap(options) {
            options = defaults(options, {
                file : null,
                root : null,
                orig : null,
        
                orig_line_diff : 0,
                dest_line_diff : 0,
            });
            var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
            var generator;
            if (orig_map) {
              generator = MOZ_SourceMap.SourceMapGenerator.fromSourceMap(orig_map);
            } else {
                generator = new MOZ_SourceMap.SourceMapGenerator({
                    file       : options.file,
                    sourceRoot : options.root
                });
            }
            function add(source, gen_line, gen_col, orig_line, orig_col, name) {
                if (orig_map) {
                    var info = orig_map.originalPositionFor({
                        line: orig_line,
                        column: orig_col
                    });
                    if (info.source === null) {
                        return;
                    }
                    source = info.source;
                    orig_line = info.line;
                    orig_col = info.column;
                    name = info.name || name;
                }
                generator.addMapping({
                    generated : { line: gen_line + options.dest_line_diff, column: gen_col },
                    original  : { line: orig_line + options.orig_line_diff, column: orig_col },
                    source    : source,
                    name      : name
                });
            }
            return {
                add        : add,
                get        : function() { return generator },
                toString   : function() { return JSON.stringify(generator.toJSON()); }
            };
        };
        
      • transform.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        // Tree transformer helpers.
        
        function TreeTransformer(before, after) {
            TreeWalker.call(this);
            this.before = before;
            this.after = after;
        }
        TreeTransformer.prototype = new TreeWalker;
        
        (function(undefined){
        
            function _(node, descend) {
                node.DEFMETHOD("transform", function(tw, in_list){
                    var x, y;
                    tw.push(this);
                    if (tw.before) x = tw.before(this, descend, in_list);
                    if (x === undefined) {
                        if (!tw.after) {
                            x = this;
                            descend(x, tw);
                        } else {
                            tw.stack[tw.stack.length - 1] = x = this.clone();
                            descend(x, tw);
                            y = tw.after(x, in_list);
                            if (y !== undefined) x = y;
                        }
                    }
                    tw.pop();
                    return x;
                });
            };
        
            function do_list(list, tw) {
                return MAP(list, function(node){
                    return node.transform(tw, true);
                });
            };
        
            _(AST_Node, noop);
        
            _(AST_LabeledStatement, function(self, tw){
                self.label = self.label.transform(tw);
                self.body = self.body.transform(tw);
            });
        
            _(AST_SimpleStatement, function(self, tw){
                self.body = self.body.transform(tw);
            });
        
            _(AST_Block, function(self, tw){
                self.body = do_list(self.body, tw);
            });
        
            _(AST_DWLoop, function(self, tw){
                self.condition = self.condition.transform(tw);
                self.body = self.body.transform(tw);
            });
        
            _(AST_For, function(self, tw){
                if (self.init) self.init = self.init.transform(tw);
                if (self.condition) self.condition = self.condition.transform(tw);
                if (self.step) self.step = self.step.transform(tw);
                self.body = self.body.transform(tw);
            });
        
            _(AST_ForIn, function(self, tw){
                self.init = self.init.transform(tw);
                self.object = self.object.transform(tw);
                self.body = self.body.transform(tw);
            });
        
            _(AST_With, function(self, tw){
                self.expression = self.expression.transform(tw);
                self.body = self.body.transform(tw);
            });
        
            _(AST_Exit, function(self, tw){
                if (self.value) self.value = self.value.transform(tw);
            });
        
            _(AST_LoopControl, function(self, tw){
                if (self.label) self.label = self.label.transform(tw);
            });
        
            _(AST_If, function(self, tw){
                self.condition = self.condition.transform(tw);
                self.body = self.body.transform(tw);
                if (self.alternative) self.alternative = self.alternative.transform(tw);
            });
        
            _(AST_Switch, function(self, tw){
                self.expression = self.expression.transform(tw);
                self.body = do_list(self.body, tw);
            });
        
            _(AST_Case, function(self, tw){
                self.expression = self.expression.transform(tw);
                self.body = do_list(self.body, tw);
            });
        
            _(AST_Try, function(self, tw){
                self.body = do_list(self.body, tw);
                if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
                if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
            });
        
            _(AST_Catch, function(self, tw){
                self.argname = self.argname.transform(tw);
                self.body = do_list(self.body, tw);
            });
        
            _(AST_Definitions, function(self, tw){
                self.definitions = do_list(self.definitions, tw);
            });
        
            _(AST_VarDef, function(self, tw){
                self.name = self.name.transform(tw);
                if (self.value) self.value = self.value.transform(tw);
            });
        
            _(AST_Lambda, function(self, tw){
                if (self.name) self.name = self.name.transform(tw);
                self.argnames = do_list(self.argnames, tw);
                self.body = do_list(self.body, tw);
            });
        
            _(AST_Call, function(self, tw){
                self.expression = self.expression.transform(tw);
                self.args = do_list(self.args, tw);
            });
        
            _(AST_Seq, function(self, tw){
                self.car = self.car.transform(tw);
                self.cdr = self.cdr.transform(tw);
            });
        
            _(AST_Dot, function(self, tw){
                self.expression = self.expression.transform(tw);
            });
        
            _(AST_Sub, function(self, tw){
                self.expression = self.expression.transform(tw);
                self.property = self.property.transform(tw);
            });
        
            _(AST_Unary, function(self, tw){
                self.expression = self.expression.transform(tw);
            });
        
            _(AST_Binary, function(self, tw){
                self.left = self.left.transform(tw);
                self.right = self.right.transform(tw);
            });
        
            _(AST_Conditional, function(self, tw){
                self.condition = self.condition.transform(tw);
                self.consequent = self.consequent.transform(tw);
                self.alternative = self.alternative.transform(tw);
            });
        
            _(AST_Array, function(self, tw){
                self.elements = do_list(self.elements, tw);
            });
        
            _(AST_Object, function(self, tw){
                self.properties = do_list(self.properties, tw);
            });
        
            _(AST_ObjectProperty, function(self, tw){
                self.value = self.value.transform(tw);
            });
        
        })();
        
      • utils.js
        /***********************************************************************
        
          A JavaScript tokenizer / parser / beautifier / compressor.
          https://github.com/mishoo/UglifyJS2
        
          -------------------------------- (C) ---------------------------------
        
                                   Author: Mihai Bazon
                                 <mihai.bazon@gmail.com>
                               http://mihai.bazon.net/blog
        
          Distributed under the BSD license:
        
            Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
        
            Redistribution and use in source and binary forms, with or without
            modification, are permitted provided that the following conditions
            are met:
        
                * Redistributions of source code must retain the above
                  copyright notice, this list of conditions and the following
                  disclaimer.
        
                * Redistributions in binary form must reproduce the above
                  copyright notice, this list of conditions and the following
                  disclaimer in the documentation and/or other materials
                  provided with the distribution.
        
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
            PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
            THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
            TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
            SUCH DAMAGE.
        
         ***********************************************************************/
        
        "use strict";
        
        function array_to_hash(a) {
            var ret = Object.create(null);
            for (var i = 0; i < a.length; ++i)
                ret[a[i]] = true;
            return ret;
        };
        
        function slice(a, start) {
            return Array.prototype.slice.call(a, start || 0);
        };
        
        function characters(str) {
            return str.split("");
        };
        
        function member(name, array) {
            for (var i = array.length; --i >= 0;)
                if (array[i] == name)
                    return true;
            return false;
        };
        
        function find_if(func, array) {
            for (var i = 0, n = array.length; i < n; ++i) {
                if (func(array[i]))
                    return array[i];
            }
        };
        
        function repeat_string(str, i) {
            if (i <= 0) return "";
            if (i == 1) return str;
            var d = repeat_string(str, i >> 1);
            d += d;
            if (i & 1) d += str;
            return d;
        };
        
        function DefaultsError(msg, defs) {
            Error.call(this, msg);
            this.msg = msg;
            this.defs = defs;
        };
        DefaultsError.prototype = Object.create(Error.prototype);
        DefaultsError.prototype.constructor = DefaultsError;
        
        DefaultsError.croak = function(msg, defs) {
            throw new DefaultsError(msg, defs);
        };
        
        function defaults(args, defs, croak) {
            if (args === true)
                args = {};
            var ret = args || {};
            if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i))
                DefaultsError.croak("`" + i + "` is not a supported option", defs);
            for (var i in defs) if (defs.hasOwnProperty(i)) {
                ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i];
            }
            return ret;
        };
        
        function merge(obj, ext) {
            for (var i in ext) if (ext.hasOwnProperty(i)) {
                obj[i] = ext[i];
            }
            return obj;
        };
        
        function noop() {};
        
        var MAP = (function(){
            function MAP(a, f, backwards) {
                var ret = [], top = [], i;
                function doit() {
                    var val = f(a[i], i);
                    var is_last = val instanceof Last;
                    if (is_last) val = val.v;
                    if (val instanceof AtTop) {
                        val = val.v;
                        if (val instanceof Splice) {
                            top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
                        } else {
                            top.push(val);
                        }
                    }
                    else if (val !== skip) {
                        if (val instanceof Splice) {
                            ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
                        } else {
                            ret.push(val);
                        }
                    }
                    return is_last;
                };
                if (a instanceof Array) {
                    if (backwards) {
                        for (i = a.length; --i >= 0;) if (doit()) break;
                        ret.reverse();
                        top.reverse();
                    } else {
                        for (i = 0; i < a.length; ++i) if (doit()) break;
                    }
                }
                else {
                    for (i in a) if (a.hasOwnProperty(i)) if (doit()) break;
                }
                return top.concat(ret);
            };
            MAP.at_top = function(val) { return new AtTop(val) };
            MAP.splice = function(val) { return new Splice(val) };
            MAP.last = function(val) { return new Last(val) };
            var skip = MAP.skip = {};
            function AtTop(val) { this.v = val };
            function Splice(val) { this.v = val };
            function Last(val) { this.v = val };
            return MAP;
        })();
        
        function push_uniq(array, el) {
            if (array.indexOf(el) < 0)
                array.push(el);
        };
        
        function string_template(text, props) {
            return text.replace(/\{(.+?)\}/g, function(str, p){
                return props[p];
            });
        };
        
        function remove(array, el) {
            for (var i = array.length; --i >= 0;) {
                if (array[i] === el) array.splice(i, 1);
            }
        };
        
        function mergeSort(array, cmp) {
            if (array.length < 2) return array.slice();
            function merge(a, b) {
                var r = [], ai = 0, bi = 0, i = 0;
                while (ai < a.length && bi < b.length) {
                    cmp(a[ai], b[bi]) <= 0
                        ? r[i++] = a[ai++]
                        : r[i++] = b[bi++];
                }
                if (ai < a.length) r.push.apply(r, a.slice(ai));
                if (bi < b.length) r.push.apply(r, b.slice(bi));
                return r;
            };
            function _ms(a) {
                if (a.length <= 1)
                    return a;
                var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
                left = _ms(left);
                right = _ms(right);
                return merge(left, right);
            };
            return _ms(array);
        };
        
        function set_difference(a, b) {
            return a.filter(function(el){
                return b.indexOf(el) < 0;
            });
        };
        
        function set_intersection(a, b) {
            return a.filter(function(el){
                return b.indexOf(el) >= 0;
            });
        };
        
        // this function is taken from Acorn [1], written by Marijn Haverbeke
        // [1] https://github.com/marijnh/acorn
        function makePredicate(words) {
            if (!(words instanceof Array)) words = words.split(" ");
            var f = "", cats = [];
            out: for (var i = 0; i < words.length; ++i) {
                for (var j = 0; j < cats.length; ++j)
                    if (cats[j][0].length == words[i].length) {
                        cats[j].push(words[i]);
                        continue out;
                    }
                cats.push([words[i]]);
            }
            function compareTo(arr) {
                if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
                f += "switch(str){";
                for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
                f += "return true}return false;";
            }
            // When there are more than three length categories, an outer
            // switch first dispatches on the lengths, to save on comparisons.
            if (cats.length > 3) {
                cats.sort(function(a, b) {return b.length - a.length;});
                f += "switch(str.length){";
                for (var i = 0; i < cats.length; ++i) {
                    var cat = cats[i];
                    f += "case " + cat[0].length + ":";
                    compareTo(cat);
                }
                f += "}";
                // Otherwise, simply generate a flat `switch` statement.
            } else {
                compareTo(words);
            }
            return new Function("str", f);
        };
        
        function all(array, predicate) {
            for (var i = array.length; --i >= 0;)
                if (!predicate(array[i]))
                    return false;
            return true;
        };
        
        function Dictionary() {
            this._values = Object.create(null);
            this._size = 0;
        };
        Dictionary.prototype = {
            set: function(key, val) {
                if (!this.has(key)) ++this._size;
                this._values["$" + key] = val;
                return this;
            },
            add: function(key, val) {
                if (this.has(key)) {
                    this.get(key).push(val);
                } else {
                    this.set(key, [ val ]);
                }
                return this;
            },
            get: function(key) { return this._values["$" + key] },
            del: function(key) {
                if (this.has(key)) {
                    --this._size;
                    delete this._values["$" + key];
                }
                return this;
            },
            has: function(key) { return ("$" + key) in this._values },
            each: function(f) {
                for (var i in this._values)
                    f(this._values[i], i.substr(1));
            },
            size: function() {
                return this._size;
            },
            map: function(f) {
                var ret = [];
                for (var i in this._values)
                    ret.push(f(this._values[i], i.substr(1)));
                return ret;
            }
        };
        
    • uglifyCSS
      • uglifycss-lib.js
        /**
         * UglifyCSS
         * Port of YUI CSS Compressor to NodeJS
         * Author: Franck Marcia - https://github.com/fmarcia
         * MIT licenced
         */
        
        /**
         * cssmin.js
         * Author: Stoyan Stefanov - http://phpied.com/
         * This is a JavaScript port of the CSS minification tool
         * distributed with YUICompressor, itself a port
         * of the cssmin utility by Isaac Schlueter - http://foohack.com/
         * Permission is hereby granted to use the JavaScript version under the same
         * conditions as the YUICompressor (original YUICompressor note below).
         */
        
        /**
         * YUI Compressor
         * http://developer.yahoo.com/yui/compressor/
         * Author: Julien Lecomte - http://www.julienlecomte.net/
         * Copyright (c) 2011 Yahoo! Inc. All rights reserved.
         * The copyrights embodied in the content of this file are licensed
         * by Yahoo! Inc. under the BSD (revised) open source license.
         */
        
        'use strict';
        
        var util = require('util');
        var fs = require('fs');
        
        var defaultOptions = {
            maxLineLen: 0,
            expandVars: false,
            uglyComments: false,
            cuteComments: false
        };
        
        /**
         * Utility method to replace all data urls with tokens before we start
         * compressing, to avoid performance issues running some of the subsequent
         * regexes against large strings chunks.
         *
         * @private
         * @function extractDataUrls
         * @param {String} css The input css
         * @param {Array} The global array of tokens to preserve
         * @returns String The processed css
         */
        function extractDataUrls(css, preservedTokens) {
        
            // Leave data urls alone to increase parse performance.
            var maxIndex = css.length - 1,
                appendIndex = 0,
                startIndex,
                endIndex,
                terminator,
                foundTerminator,
                sb = [],
                m,
                preserver,
                token,
                pattern = /url\(\s*(["']?)data\:/g;
        
            // Since we need to account for non-base64 data urls, we need to handle
            // ' and ) being part of the data string. Hence switching to indexOf,
            // to determine whether or not we have matching string terminators and
            // handling sb appends directly, instead of using matcher.append* methods.
        
            while ((m = pattern.exec(css)) !== null) {
        
                startIndex = m.index + 4;  // "url(".length()
                terminator = m[1];         // ', " or empty (not quoted)
        
                if (terminator.length === 0) {
                    terminator = ")";
                }
        
                foundTerminator = false;
        
                endIndex = pattern.lastIndex - 1;
        
                while(foundTerminator === false && endIndex+1 <= maxIndex) {
                    endIndex = css.indexOf(terminator, endIndex + 1);
        
                    // endIndex == 0 doesn't really apply here
                    if ((endIndex > 0) && (css.charAt(endIndex - 1) !== '\\')) {
                        foundTerminator = true;
                        if (")" != terminator) {
                            endIndex = css.indexOf(")", endIndex);
                        }
                    }
                }
        
                // Enough searching, start moving stuff over to the buffer
                sb.push(css.substring(appendIndex, m.index));
        
                if (foundTerminator) {
                    token = css.substring(startIndex, endIndex);
                    token = token.replace(/\s+/g, "");
                    preservedTokens.push(token);
        
                    preserver = "url(___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___)";
                    sb.push(preserver);
        
                    appendIndex = endIndex + 1;
                } else {
                    // No end terminator found, re-add the whole match. Should we throw/warn here?
                    sb.push(css.substring(m.index, pattern.lastIndex));
                    appendIndex = pattern.lastIndex;
                }
            }
        
            sb.push(css.substring(appendIndex));
        
            return sb.join("");
        }
        
        /**
         * Utility method to compress hex color values of the form #AABBCC to #ABC.
         *
         * DOES NOT compress CSS ID selectors which match the above pattern (which would break things).
         * e.g. #AddressForm { ... }
         *
         * DOES NOT compress IE filters, which have hex color values (which would break things).
         * e.g. filter: chroma(color="#FFFFFF");
         *
         * DOES NOT compress invalid hex values.
         * e.g. background-color: #aabbccdd
         *
         * @private
         * @function compressHexColors
         * @param {String} css The input css
         * @returns String The processed css
         */
        function compressHexColors(css) {
        
            // Look for hex colors inside { ... } (to avoid IDs) and which don't have a =, or a " in front of them (to avoid filters)
            var pattern = /(\=\s*?["']?)?#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])(\}|[^0-9a-f{][^{]*?\})/gi,
                m,
                index = 0,
                isFilter,
                sb = [];
        
            while ((m = pattern.exec(css)) !== null) {
        
                sb.push(css.substring(index, m.index));
        
                isFilter = m[1];
        
                if (isFilter) {
                    // Restore, maintain case, otherwise filter will break
                    sb.push(m[1] + "#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7]));
                } else {
                    if (m[2].toLowerCase() == m[3].toLowerCase() &&
                        m[4].toLowerCase() == m[5].toLowerCase() &&
                        m[6].toLowerCase() == m[7].toLowerCase()) {
        
                        // Compress.
                        sb.push("#" + (m[3] + m[5] + m[7]).toLowerCase());
                    } else {
                        // Non compressible color, restore but lower case.
                        sb.push("#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7]).toLowerCase());
                    }
                }
        
                index = pattern.lastIndex = pattern.lastIndex - m[8].length;
            }
        
            sb.push(css.substring(index));
        
            return sb.join("");
        }
        
        // Preserve 0 followed by unit in keyframes steps
        
        function keyframes(content, preservedTokens) {
        
            var level,
                buffer,
                buffers,
                pattern = /@[a-z0-9-_]*keyframes\s+[a-z0-9-_]+\s*{/gi,
                index = 0,
                len,
                c,
                startIndex;
        
            var preserve = function (part, index) {
                part = part.replace(/(^\s|\s$)/g, '');
                if (part.charAt(0) === '0') {
                    preservedTokens.push(part);
                    buffer[index] = "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___";
                }
            };
        
            while (true) {
        
                level = 0;
                buffer = '';
        
                startIndex = content.slice(index).search(pattern);
                if (startIndex < 0) {
                    break;
                }
        
                index += startIndex;
                startIndex = index;
                len = content.length;
                buffers = [];
        
                for (; index < len; ++index) {
        
                    c = content.charAt(index);
        
                    if (c === '{') {
        
                        if (level === 0) {
                            buffers.push(buffer.replace(/(^\s|\s$)/g, ''));
        
                        } else if (level === 1) {
        
                            buffer = buffer.split(',');
        
                            buffer.forEach(preserve);
        
                            buffers.push(buffer.join(',').replace(/(^\s|\s$)/g, ''));
                        }
        
                        buffer = '';
                        level += 1;
        
                    } else if (c === '}') {
        
                        if (level === 2) {
                            buffers.push('{' + buffer.replace(/(^\s|\s$)/g, '') + '}');
                            buffer = '';
        
                        } else if (level === 1) {
                            content = content.slice(0, startIndex) +
                                buffers.shift() + '{' +
                                buffers.join('') +
                                content.slice(index);
                            break;
                        }
        
                        level -= 1;
                    }
        
                    if (level < 0) {
                        break;
        
                    } else if (c !== '{' && c !== '}') {
                        buffer += c;
                    }
                }
            }
        
            return content;
        }
        
        // Uglify a CSS string
        
        function processString(content, options) {
        
            var startIndex,
                endIndex,
                comments = [],
                preservedTokens = [],
                token,
                len = content.length,
                pattern,
                quote,
                rgbcolors,
                hexcolor,
                placeholder,
                val,
                i,
                c,
                line = [],
                lines = [],
                vars = {};
        
            options = options || defaultOptions;
        
            content = extractDataUrls(content, preservedTokens);
        
            // collect all comment blocks...
            while ((startIndex = content.indexOf("/*", startIndex)) >= 0) {
                endIndex = content.indexOf("*/", startIndex + 2);
                if (endIndex < 0) {
                    endIndex = len;
                }
                token = content.slice(startIndex + 2, endIndex);
                comments.push(token);
                content = content.slice(0, startIndex + 2) + "___PRESERVE_CANDIDATE_COMMENT_" + (comments.length - 1) + "___" + content.slice(endIndex);
                startIndex += 2;
            }
        
            // preserve strings so their content doesn't get accidentally minified
            pattern = /("([^\\"]|\\.|\\)*")|('([^\\']|\\.|\\)*')/g;
            content = content.replace(pattern, function (token) {
                quote = token.substring(0, 1);
                token = token.slice(1, -1);
                // maybe the string contains a comment-like substring or more? put'em back then
                if (token.indexOf("___PRESERVE_CANDIDATE_COMMENT_") >= 0) {
                    for (i = 0, len = comments.length; i < len; i += 1) {
                        token = token.replace("___PRESERVE_CANDIDATE_COMMENT_" + i + "___", comments[i]);
                    }
                }
                // minify alpha opacity in filter strings
                token = token.replace(/progid:DXImageTransform.Microsoft.Alpha\(Opacity=/gi, "alpha(opacity=");
                preservedTokens.push(token);
                return quote + "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___" + quote;
            });
        
            // strings are safe, now wrestle the comments
            for (i = 0, len = comments.length; i < len; i += 1) {
        
                token = comments[i];
                placeholder = "___PRESERVE_CANDIDATE_COMMENT_" + i + "___";
        
                // ! in the first position of the comment means preserve
                // so push to the preserved tokens keeping the !
                if (token.charAt(0) === "!") {
                    if (options.cuteComments) {
                        preservedTokens.push(token.substring(1));
                    } else if (options.uglyComments) {
                        preservedTokens.push(token.substring(1).replace(/[\r\n]/g, ''));
                    } else {
                        preservedTokens.push(token);
                    }
                    content = content.replace(placeholder,  "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
                    continue;
                }
        
                // \ in the last position looks like hack for Mac/IE5
                // shorten that to /*\*/ and the next one to /**/
                if (token.charAt(token.length - 1) === "\\") {
                    preservedTokens.push("\\");
                    content = content.replace(placeholder,  "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
                    i = i + 1; // attn: advancing the loop
                    preservedTokens.push("");
                    content = content.replace(
                        "___PRESERVE_CANDIDATE_COMMENT_" + i + "___",
                        "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"
                    );
                    continue;
                }
        
                // keep empty comments after child selectors (IE7 hack)
                // e.g. html >/**/ body
                if (token.length === 0) {
                    startIndex = content.indexOf(placeholder);
                    if (startIndex > 2) {
                        if (content.charAt(startIndex - 3) === '>') {
                            preservedTokens.push("");
                            content = content.replace(placeholder,  "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
                        }
                    }
                }
        
                // in all other cases kill the comment
                content = content.replace("/*" + placeholder + "*/", "");
            }
        
            if (options.expandVars) {
                // parse simple @variables blocks and remove them
                pattern = /@variables\s*\{\s*([^\}]+)\s*\}/g;
                content = content.replace(pattern, function (ignore, f1) {
                    pattern = /\s*([a-z0-9\-]+)\s*:\s*([^;\}]+)\s*/gi;
                    f1.replace(pattern, function (ignore, f1, f2) {
                        if (f1 && f2) {
                        vars[f1] = f2;
                        }
                        return '';
                    });
                    return '';
                });
        
                // replace var(x) with the value of x
                pattern = /var\s*\(\s*([^\)]+)\s*\)/g;
                content = content.replace(pattern, function (ignore, f1) {
                    return vars[f1] || 'none';
                });
            }
        
            // normalize all whitespace strings to single spaces. Easier to work with that way.
            content = content.replace(/\s+/g, " ");
        
            // preserve formulas in calc() before removing spaces
            pattern = /calc\(([^\)\()]*)\)/;
            var preserveCalc = function (ignore, f1) {
                preservedTokens.push('calc(' + f1.replace(/(^\s*|\s*$)/g, "") + ')');
                return "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___";
            };
            while (true) {
                if (pattern.test(content)) {
                    content = content.replace(pattern, preserveCalc);
                } else {
                    break;
                }
            }
        
            // preserve matrix
            pattern = /\s*filter:\s*progid:DXImageTransform.Microsoft.Matrix\(([^\)]+)\);/g;
            content = content.replace(pattern, function (ignore, f1) {
                preservedTokens.push(f1);
                return "filter:progid:DXImageTransform.Microsoft.Matrix(___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___);";
            });
        
            // remove the spaces before the things that should not have spaces before them.
            // but, be careful not to turn "p :link {...}" into "p:link{...}"
            // swap out any pseudo-class colons with the token, and then swap back.
            pattern = /(^|\})(([^\{:])+:)+([^\{]*\{)/g;
            content = content.replace(pattern, function (token) {
                return token.replace(/:/g, "___PSEUDOCLASSCOLON___");
            });
        
            // remove spaces before the things that should not have spaces before them.
            content = content.replace(/\s+([!{};:>+\(\)\],])/g, "$1");
        
            // restore spaces for !important
            content = content.replace(/!important/g, " !important");
        
            // bring back the colon
            content = content.replace(/___PSEUDOCLASSCOLON___/g, ":");
        
            // preserve 0 followed by a time unit for properties using time units
            pattern = /\s*(animation|animation-delay|animation-duration|transition|transition-delay|transition-duration):\s*([^;}]+)/gi;
            content = content.replace(pattern, function (ignore, f1, f2) {
        
                f2 = f2.replace(/(\s*)0?.?0(m?s)\s*/gi, function (ignore, g1, g2) {
                    preservedTokens.push('0s');
                    return g1 + "___PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___";
                });
        
                return f1 + ":" + f2;
            });
        
            // preserve 0 followed by unit in keyframes steps (WIP)
            content = keyframes(content, preservedTokens);
        
            // retain space for special IE6 cases
            content = content.replace(/:first-(line|letter)(\{|,)/gi, function (ignore, f1, f2) {
                return ":first-" + f1.toLowerCase() + " " + f2;
            });
        
            // newlines before and after the end of a preserved comment
            if (options.cuteComments) {
                content = content.replace(/\s*\/\*/g, "___PRESERVED_NEWLINE___/*");
                content = content.replace(/\*\/\s*/g, "*/___PRESERVED_NEWLINE___");
            // no space after the end of a preserved comment
            } else {
                content = content.replace(/\*\/\s*/g, '*/');
            }
        
            // If there are multiple @charset directives, push them to the top of the file.
            pattern = /^(.*)(@charset)( "[^"]*";)/gi;
            content = content.replace(pattern, function (ignore, f1, f2, f3) {
                return f2.toLowerCase() + f3 + f1;
            });
        
            // When all @charset are at the top, remove the second and after (as they are completely ignored).
            pattern = /^((\s*)(@charset)( [^;]+;\s*))+/gi;
            content = content.replace(pattern, function (ignore, ignore2, f2, f3, f4) {
                return f2 + f3.toLowerCase() + f4;
            });
        
            // lowercase some popular @directives (@charset is done right above)
            pattern = /@(font-face|import|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?keyframe|media|page|namespace)/gi;
            content = content.replace(pattern, function (ignore, f1) {
                return '@' + f1.toLowerCase();
            });
        
            // lowercase some more common pseudo-elements
            pattern = /:(active|after|before|checked|disabled|empty|enabled|first-(?:child|of-type)|focus|hover|last-(?:child|of-type)|link|only-(?:child|of-type)|root|:selection|target|visited)/gi;
            content = content.replace(pattern, function (ignore, f1) {
                return ':' + f1.toLowerCase();
            });
        
            // if there is a @charset, then only allow one, and push to the top of the file.
            content = content.replace(/^(.*)(@charset \"[^\"]*\";)/g, "$2$1");
            content = content.replace(/^(\s*@charset [^;]+;\s*)+/g, "$1");
        
            // lowercase some more common functions
            pattern = /:(lang|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?any)\(/gi;
            content = content.replace(pattern, function (ignore, f1) {
                return ':' + f1.toLowerCase() + '(';
            });
        
            // lower case some common function that can be values
            // NOTE: rgb() isn't useful as we replace with #hex later, as well as and() is already done for us right after this
            pattern = /([:,\( ]\s*)(attr|color-stop|from|rgba|to|url|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?(?:calc|max|min|(?:repeating-)?(?:linear|radial)-gradient)|-webkit-gradient)/gi;
            content = content.replace(pattern, function (ignore, f1, f2) {
                return f1 + f2.toLowerCase();
            });
        
            // put the space back in some cases, to support stuff like
            // @media screen and (-webkit-min-device-pixel-ratio:0){
            content = content.replace(/\band\(/gi, "and (");
        
            // remove the spaces after the things that should not have spaces after them.
            content = content.replace(/([!{}:;>+\(\[,])\s+/g, "$1");
        
            // remove unnecessary semicolons
            content = content.replace(/;+\}/g, "}");
        
            // replace 0(px,em,%) with 0.
            content = content.replace(/(^|[^.0-9])(?:0?\.)?0(?:ex|ch|r?em|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|g?rad|turn|m?s|k?Hz|dpi|dpcm|dppx|%)/gi, "$10");
        
            // Replace x.0(px,em,%) with x(px,em,%).
            content = content.replace(/([0-9])\.0(ex|ch|r?em|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|g?rad|turn|m?s|k?Hz|dpi|dpcm|dppx|%| |;)/gi, "$1$2");
        
            // replace 0 0 0 0; with 0.
            content = content.replace(/:0 0 0 0(;|\})/g, ":0$1");
            content = content.replace(/:0 0 0(;|\})/g, ":0$1");
            content = content.replace(/:0 0(;|\})/g, ":0$1");
        
            // replace background-position:0; with background-position:0 0;
            // same for transform-origin
            pattern = /(background-position|transform-origin|webkit-transform-origin|moz-transform-origin|o-transform-origin|ms-transform-origin):0(;|\})/gi;
            content = content.replace(pattern, function (ignore, f1, f2) {
                return f1.toLowerCase() + ":0 0" + f2;
            });
        
            // replace 0.6 to .6, but only when preceded by : or a white-space
            content = content.replace(/(:|\s)0+\.(\d+)/g, "$1.$2");
        
            // shorten colors from rgb(51,102,153) to #336699
            // this makes it more likely that it'll get further compressed in the next step.
            pattern = /rgb\s*\(\s*([0-9,\s]+)\s*\)/gi;
            content = content.replace(pattern, function (ignore, f1) {
                rgbcolors = f1.split(",");
                hexcolor = "#";
                for (i = 0; i < rgbcolors.length; i += 1) {
                    val = parseInt(rgbcolors[i], 10);
                    if (val < 16) {
                        hexcolor += "0";
                    }
                    if (val > 255) {
                        val = 255;
                    }
                    hexcolor += val.toString(16);
                }
                return hexcolor;
            });
        
            // Shorten colors from #AABBCC to #ABC.
            content = compressHexColors(content);
        
            // Replace #f00 -> red
            content = content.replace(/(:|\s)(#f00)(;|})/g, "$1red$3");
        
            // Replace other short color keywords
            content = content.replace(/(:|\s)(#000080)(;|})/g, "$1navy$3");
            content = content.replace(/(:|\s)(#808080)(;|})/g, "$1gray$3");
            content = content.replace(/(:|\s)(#808000)(;|})/g, "$1olive$3");
            content = content.replace(/(:|\s)(#800080)(;|})/g, "$1purple$3");
            content = content.replace(/(:|\s)(#c0c0c0)(;|})/g, "$1silver$3");
            content = content.replace(/(:|\s)(#008080)(;|})/g, "$1teal$3");
            content = content.replace(/(:|\s)(#ffa500)(;|})/g, "$1orange$3");
            content = content.replace(/(:|\s)(#800000)(;|})/g, "$1maroon$3");
        
            // border: none -> border:0
            pattern = /(border|border-top|border-right|border-bottom|border-left|outline|background):none(;|\})/gi;
            content = content.replace(pattern, function (ignore, f1, f2) {
                return f1.toLowerCase() + ":0" + f2;
            });
        
            // shorter opacity IE filter
            content = content.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity=");
        
            // Find a fraction that is used for Opera's -o-device-pixel-ratio query
            // Add token to add the "\" back in later
            content = content.replace(/\(([\-A-Za-z]+):([0-9]+)\/([0-9]+)\)/g, "($1:$2___QUERY_FRACTION___$3)");
        
            // remove empty rules.
            content = content.replace(/[^\};\{\/]+\{\}/g, "");
        
            // Add "\" back to fix Opera -o-device-pixel-ratio query
            content = content.replace(/___QUERY_FRACTION___/g, "/");
        
            // some source control tools don't like it when files containing lines longer
            // than, say 8000 characters, are checked in. The linebreak option is used in
            // that case to split long lines after a specific column.
            if (options.maxLineLen > 0) {
                for (i = 0, len = content.length; i < len; i += 1) {
                    c = content.charAt(i);
                    line.push(c);
                    if (c === '}' && line.length > options.maxLineLen) {
                        lines.push(line.join(''));
                        line = [];
                    }
                }
                if (line.length) {
                    lines.push(line.join(''));
                }
        
                content = lines.join('\n');
            }
        
            // replace multiple semi-colons in a row by a single one
            // see SF bug #1980989
            content = content.replace(/;;+/g, ";");
        
            // trim the final string (for any leading or trailing white spaces)
            content = content.replace(/(^\s*|\s*$)/g, "");
        
            // restore preserved tokens
            for (i = preservedTokens.length - 1; i >= 0 ; i--) {
                content = content.replace("___PRESERVED_TOKEN_" + i + "___", preservedTokens[i], "g");
            }
        
            // restore preserved newlines
            content = content.replace(/___PRESERVED_NEWLINE___/g, '\n');
        
            // return
            return content;
        }
        
        // Uglify CSS files
        
        function processFiles(filenames, options) {
        
            var nFiles = filenames.length,
                uglies = [],
                index,
                filename,
                content;
        
            // process files
            for (index = 0; index < nFiles; index += 1) {
                filename = filenames[index];
                try {
                    content = fs.readFileSync(filename, 'utf8');
                    if (content.length) {
                        uglies.push(processString(content, options));
                    }
                } catch (e) {
                    util.error('unable to process "' + filename + '" with ' + e);
                    process.exit(1);
                }
            }
        
            // return concat'd results
            return uglies.join('');
        }
        
        module.exports = {
            defaultOptions: defaultOptions,
            processString: processString,
            processFiles: processFiles
        };
    • zip.js
      • deflate.js
        /*
         Copyright (c) 2013 Gildas Lormeau. All rights reserved.
        
         Redistribution and use in source and binary forms, with or without
         modification, are permitted provided that the following conditions are met:
        
         1. Redistributions of source code must retain the above copyright notice,
         this list of conditions and the following disclaimer.
        
         2. Redistributions in binary form must reproduce the above copyright 
         notice, this list of conditions and the following disclaimer in 
         the documentation and/or other materials provided with the distribution.
        
         3. The names of the authors may not be used to endorse or promote products
         derived from this software without specific prior written permission.
        
         THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
         INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
         FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
         INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
         INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
         LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
         OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
         LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
         NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
         EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         */
        
        /*
         * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc.
         * JZlib is based on zlib-1.1.3, so all credit should go authors
         * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
         * and contributors of zlib.
         */
        
        (function(global) {
        	"use strict";
        
        	// Global
        
        	var MAX_BITS = 15;
        	var D_CODES = 30;
        	var BL_CODES = 19;
        
        	var LENGTH_CODES = 29;
        	var LITERALS = 256;
        	var L_CODES = (LITERALS + 1 + LENGTH_CODES);
        	var HEAP_SIZE = (2 * L_CODES + 1);
        
        	var END_BLOCK = 256;
        
        	// Bit length codes must not exceed MAX_BL_BITS bits
        	var MAX_BL_BITS = 7;
        
        	// repeat previous bit length 3-6 times (2 bits of repeat count)
        	var REP_3_6 = 16;
        
        	// repeat a zero length 3-10 times (3 bits of repeat count)
        	var REPZ_3_10 = 17;
        
        	// repeat a zero length 11-138 times (7 bits of repeat count)
        	var REPZ_11_138 = 18;
        
        	// The lengths of the bit length codes are sent in order of decreasing
        	// probability, to avoid transmitting the lengths for unused bit
        	// length codes.
        
        	var Buf_size = 8 * 2;
        
        	// JZlib version : "1.0.2"
        	var Z_DEFAULT_COMPRESSION = -1;
        
        	// compression strategy
        	var Z_FILTERED = 1;
        	var Z_HUFFMAN_ONLY = 2;
        	var Z_DEFAULT_STRATEGY = 0;
        
        	var Z_NO_FLUSH = 0;
        	var Z_PARTIAL_FLUSH = 1;
        	var Z_FULL_FLUSH = 3;
        	var Z_FINISH = 4;
        
        	var Z_OK = 0;
        	var Z_STREAM_END = 1;
        	var Z_NEED_DICT = 2;
        	var Z_STREAM_ERROR = -2;
        	var Z_DATA_ERROR = -3;
        	var Z_BUF_ERROR = -5;
        
        	// Tree
        
        	// see definition of array dist_code below
        	var _dist_code = [ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
        			10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
        			12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
        			13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
        			14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
        			14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
        			15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19,
        			20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
        			24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
        			26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
        			27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
        			28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29,
        			29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
        			29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 ];
        
        	function Tree() {
        		var that = this;
        
        		// dyn_tree; // the dynamic tree
        		// max_code; // largest code with non zero frequency
        		// stat_desc; // the corresponding static tree
        
        		// Compute the optimal bit lengths for a tree and update the total bit
        		// length
        		// for the current block.
        		// IN assertion: the fields freq and dad are set, heap[heap_max] and
        		// above are the tree nodes sorted by increasing frequency.
        		// OUT assertions: the field len is set to the optimal bit length, the
        		// array bl_count contains the frequencies for each bit length.
        		// The length opt_len is updated; static_len is also updated if stree is
        		// not null.
        		function gen_bitlen(s) {
        			var tree = that.dyn_tree;
        			var stree = that.stat_desc.static_tree;
        			var extra = that.stat_desc.extra_bits;
        			var base = that.stat_desc.extra_base;
        			var max_length = that.stat_desc.max_length;
        			var h; // heap index
        			var n, m; // iterate over the tree elements
        			var bits; // bit length
        			var xbits; // extra bits
        			var f; // frequency
        			var overflow = 0; // number of elements with bit length too large
        
        			for (bits = 0; bits <= MAX_BITS; bits++)
        				s.bl_count[bits] = 0;
        
        			// In a first pass, compute the optimal bit lengths (which may
        			// overflow in the case of the bit length tree).
        			tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
        
        			for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
        				n = s.heap[h];
        				bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
        				if (bits > max_length) {
        					bits = max_length;
        					overflow++;
        				}
        				tree[n * 2 + 1] = bits;
        				// We overwrite tree[n*2+1] which is no longer needed
        
        				if (n > that.max_code)
        					continue; // not a leaf node
        
        				s.bl_count[bits]++;
        				xbits = 0;
        				if (n >= base)
        					xbits = extra[n - base];
        				f = tree[n * 2];
        				s.opt_len += f * (bits + xbits);
        				if (stree)
        					s.static_len += f * (stree[n * 2 + 1] + xbits);
        			}
        			if (overflow === 0)
        				return;
        
        			// This happens for example on obj2 and pic of the Calgary corpus
        			// Find the first bit length which could increase:
        			do {
        				bits = max_length - 1;
        				while (s.bl_count[bits] === 0)
        					bits--;
        				s.bl_count[bits]--; // move one leaf down the tree
        				s.bl_count[bits + 1] += 2; // move one overflow item as its brother
        				s.bl_count[max_length]--;
        				// The brother of the overflow item also moves one step up,
        				// but this does not affect bl_count[max_length]
        				overflow -= 2;
        			} while (overflow > 0);
        
        			for (bits = max_length; bits !== 0; bits--) {
        				n = s.bl_count[bits];
        				while (n !== 0) {
        					m = s.heap[--h];
        					if (m > that.max_code)
        						continue;
        					if (tree[m * 2 + 1] != bits) {
        						s.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2];
        						tree[m * 2 + 1] = bits;
        					}
        					n--;
        				}
        			}
        		}
        
        		// Reverse the first len bits of a code, using straightforward code (a
        		// faster
        		// method would use a table)
        		// IN assertion: 1 <= len <= 15
        		function bi_reverse(code, // the value to invert
        		len // its bit length
        		) {
        			var res = 0;
        			do {
        				res |= code & 1;
        				code >>>= 1;
        				res <<= 1;
        			} while (--len > 0);
        			return res >>> 1;
        		}
        
        		// Generate the codes for a given tree and bit counts (which need not be
        		// optimal).
        		// IN assertion: the array bl_count contains the bit length statistics for
        		// the given tree and the field len is set for all tree elements.
        		// OUT assertion: the field code is set for all tree elements of non
        		// zero code length.
        		function gen_codes(tree, // the tree to decorate
        		max_code, // largest code with non zero frequency
        		bl_count // number of codes at each bit length
        		) {
        			var next_code = []; // next code value for each
        			// bit length
        			var code = 0; // running code value
        			var bits; // bit index
        			var n; // code index
        			var len;
        
        			// The distribution counts are first used to generate the code values
        			// without bit reversal.
        			for (bits = 1; bits <= MAX_BITS; bits++) {
        				next_code[bits] = code = ((code + bl_count[bits - 1]) << 1);
        			}
        
        			// Check that the bit counts in bl_count are consistent. The last code
        			// must be all ones.
        			// Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
        			// "inconsistent bit counts");
        			// Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
        
        			for (n = 0; n <= max_code; n++) {
        				len = tree[n * 2 + 1];
        				if (len === 0)
        					continue;
        				// Now reverse the bits
        				tree[n * 2] = bi_reverse(next_code[len]++, len);
        			}
        		}
        
        		// Construct one Huffman tree and assigns the code bit strings and lengths.
        		// Update the total bit length for the current block.
        		// IN assertion: the field freq is set for all tree elements.
        		// OUT assertions: the fields len and code are set to the optimal bit length
        		// and corresponding code. The length opt_len is updated; static_len is
        		// also updated if stree is not null. The field max_code is set.
        		that.build_tree = function(s) {
        			var tree = that.dyn_tree;
        			var stree = that.stat_desc.static_tree;
        			var elems = that.stat_desc.elems;
        			var n, m; // iterate over heap elements
        			var max_code = -1; // largest code with non zero frequency
        			var node; // new node being created
        
        			// Construct the initial heap, with least frequent element in
        			// heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
        			// heap[0] is not used.
        			s.heap_len = 0;
        			s.heap_max = HEAP_SIZE;
        
        			for (n = 0; n < elems; n++) {
        				if (tree[n * 2] !== 0) {
        					s.heap[++s.heap_len] = max_code = n;
        					s.depth[n] = 0;
        				} else {
        					tree[n * 2 + 1] = 0;
        				}
        			}
        
        			// The pkzip format requires that at least one distance code exists,
        			// and that at least one bit should be sent even if there is only one
        			// possible code. So to avoid special checks later on we force at least
        			// two codes of non zero frequency.
        			while (s.heap_len < 2) {
        				node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0;
        				tree[node * 2] = 1;
        				s.depth[node] = 0;
        				s.opt_len--;
        				if (stree)
        					s.static_len -= stree[node * 2 + 1];
        				// node is 0 or 1 so it does not have extra bits
        			}
        			that.max_code = max_code;
        
        			// The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
        			// establish sub-heaps of increasing lengths:
        
        			for (n = Math.floor(s.heap_len / 2); n >= 1; n--)
        				s.pqdownheap(tree, n);
        
        			// Construct the Huffman tree by repeatedly combining the least two
        			// frequent nodes.
        
        			node = elems; // next internal node of the tree
        			do {
        				// n = node of least frequency
        				n = s.heap[1];
        				s.heap[1] = s.heap[s.heap_len--];
        				s.pqdownheap(tree, 1);
        				m = s.heap[1]; // m = node of next least frequency
        
        				s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
        				s.heap[--s.heap_max] = m;
        
        				// Create a new node father of n and m
        				tree[node * 2] = (tree[n * 2] + tree[m * 2]);
        				s.depth[node] = Math.max(s.depth[n], s.depth[m]) + 1;
        				tree[n * 2 + 1] = tree[m * 2 + 1] = node;
        
        				// and insert the new node in the heap
        				s.heap[1] = node++;
        				s.pqdownheap(tree, 1);
        			} while (s.heap_len >= 2);
        
        			s.heap[--s.heap_max] = s.heap[1];
        
        			// At this point, the fields freq and dad are set. We can now
        			// generate the bit lengths.
        
        			gen_bitlen(s);
        
        			// The field len is now set, we can generate the bit codes
        			gen_codes(tree, that.max_code, s.bl_count);
        		};
        
        	}
        
        	Tree._length_code = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16,
        			16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20,
        			20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
        			22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
        			24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
        			25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
        			26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 ];
        
        	Tree.base_length = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0 ];
        
        	Tree.base_dist = [ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384,
        			24576 ];
        
        	// Mapping from a distance to a distance code. dist is the distance - 1 and
        	// must not have side effects. _dist_code[256] and _dist_code[257] are never
        	// used.
        	Tree.d_code = function(dist) {
        		return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >>> 7)]);
        	};
        
        	// extra bits for each length code
        	Tree.extra_lbits = [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 ];
        
        	// extra bits for each distance code
        	Tree.extra_dbits = [ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 ];
        
        	// extra bits for each bit length code
        	Tree.extra_blbits = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 ];
        
        	Tree.bl_order = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
        
        	// StaticTree
        
        	function StaticTree(static_tree, extra_bits, extra_base, elems, max_length) {
        		var that = this;
        		that.static_tree = static_tree;
        		that.extra_bits = extra_bits;
        		that.extra_base = extra_base;
        		that.elems = elems;
        		that.max_length = max_length;
        	}
        
        	StaticTree.static_ltree = [ 12, 8, 140, 8, 76, 8, 204, 8, 44, 8, 172, 8, 108, 8, 236, 8, 28, 8, 156, 8, 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, 252, 8, 2, 8,
        			130, 8, 66, 8, 194, 8, 34, 8, 162, 8, 98, 8, 226, 8, 18, 8, 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, 114, 8, 242, 8, 10, 8, 138, 8, 74, 8, 202, 8, 42,
        			8, 170, 8, 106, 8, 234, 8, 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, 186, 8, 122, 8, 250, 8, 6, 8, 134, 8, 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, 230, 8,
        			22, 8, 150, 8, 86, 8, 214, 8, 54, 8, 182, 8, 118, 8, 246, 8, 14, 8, 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
        			222, 8, 62, 8, 190, 8, 126, 8, 254, 8, 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, 161, 8, 97, 8, 225, 8, 17, 8, 145, 8, 81, 8, 209, 8, 49, 8, 177, 8, 113,
        			8, 241, 8, 9, 8, 137, 8, 73, 8, 201, 8, 41, 8, 169, 8, 105, 8, 233, 8, 25, 8, 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, 121, 8, 249, 8, 5, 8, 133, 8,
        			69, 8, 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, 181, 8, 117, 8, 245, 8, 13, 8, 141, 8, 77, 8, 205, 8, 45, 8,
        			173, 8, 109, 8, 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, 211, 9, 467, 9,
        			51, 9, 307, 9, 179, 9, 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, 331, 9, 203, 9, 459, 9, 43, 9, 299, 9, 171, 9,
        			427, 9, 107, 9, 363, 9, 235, 9, 491, 9, 27, 9, 283, 9, 155, 9, 411, 9, 91, 9, 347, 9, 219, 9, 475, 9, 59, 9, 315, 9, 187, 9, 443, 9, 123, 9, 379,
        			9, 251, 9, 507, 9, 7, 9, 263, 9, 135, 9, 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, 359, 9, 231, 9, 487, 9, 23,
        			9, 279, 9, 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, 471, 9, 55, 9, 311, 9, 183, 9, 439, 9, 119, 9, 375, 9, 247, 9, 503, 9, 15, 9, 271, 9, 143, 9,
        			399, 9, 79, 9, 335, 9, 207, 9, 463, 9, 47, 9, 303, 9, 175, 9, 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, 351, 9,
        			223, 9, 479, 9, 63, 9, 319, 9, 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, 511, 9, 0, 7, 64, 7, 32, 7, 96, 7, 16, 7, 80, 7, 48, 7, 112, 7, 8, 7, 72, 7,
        			40, 7, 104, 7, 24, 7, 88, 7, 56, 7, 120, 7, 4, 7, 68, 7, 36, 7, 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, 163, 8,
        			99, 8, 227, 8 ];
        
        	StaticTree.static_dtree = [ 0, 5, 16, 5, 8, 5, 24, 5, 4, 5, 20, 5, 12, 5, 28, 5, 2, 5, 18, 5, 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, 30, 5, 1, 5, 17, 5, 9, 5,
        			25, 5, 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5 ];
        
        	StaticTree.static_l_desc = new StaticTree(StaticTree.static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
        
        	StaticTree.static_d_desc = new StaticTree(StaticTree.static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS);
        
        	StaticTree.static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
        
        	// Deflate
        
        	var MAX_MEM_LEVEL = 9;
        	var DEF_MEM_LEVEL = 8;
        
        	function Config(good_length, max_lazy, nice_length, max_chain, func) {
        		var that = this;
        		that.good_length = good_length;
        		that.max_lazy = max_lazy;
        		that.nice_length = nice_length;
        		that.max_chain = max_chain;
        		that.func = func;
        	}
        
        	var STORED = 0;
        	var FAST = 1;
        	var SLOW = 2;
        	var config_table = [ new Config(0, 0, 0, 0, STORED), new Config(4, 4, 8, 4, FAST), new Config(4, 5, 16, 8, FAST), new Config(4, 6, 32, 32, FAST),
        			new Config(4, 4, 16, 16, SLOW), new Config(8, 16, 32, 32, SLOW), new Config(8, 16, 128, 128, SLOW), new Config(8, 32, 128, 256, SLOW),
        			new Config(32, 128, 258, 1024, SLOW), new Config(32, 258, 258, 4096, SLOW) ];
        
        	var z_errmsg = [ "need dictionary", // Z_NEED_DICT
        	// 2
        	"stream end", // Z_STREAM_END 1
        	"", // Z_OK 0
        	"", // Z_ERRNO (-1)
        	"stream error", // Z_STREAM_ERROR (-2)
        	"data error", // Z_DATA_ERROR (-3)
        	"", // Z_MEM_ERROR (-4)
        	"buffer error", // Z_BUF_ERROR (-5)
        	"",// Z_VERSION_ERROR (-6)
        	"" ];
        
        	// block not completed, need more input or more output
        	var NeedMore = 0;
        
        	// block flush performed
        	var BlockDone = 1;
        
        	// finish started, need only more output at next deflate
        	var FinishStarted = 2;
        
        	// finish done, accept no more input or output
        	var FinishDone = 3;
        
        	// preset dictionary flag in zlib header
        	var PRESET_DICT = 0x20;
        
        	var INIT_STATE = 42;
        	var BUSY_STATE = 113;
        	var FINISH_STATE = 666;
        
        	// The deflate compression method
        	var Z_DEFLATED = 8;
        
        	var STORED_BLOCK = 0;
        	var STATIC_TREES = 1;
        	var DYN_TREES = 2;
        
        	var MIN_MATCH = 3;
        	var MAX_MATCH = 258;
        	var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
        
        	function smaller(tree, n, m, depth) {
        		var tn2 = tree[n * 2];
        		var tm2 = tree[m * 2];
        		return (tn2 < tm2 || (tn2 == tm2 && depth[n] <= depth[m]));
        	}
        
        	function Deflate() {
        
        		var that = this;
        		var strm; // pointer back to this zlib stream
        		var status; // as the name implies
        		// pending_buf; // output still pending
        		var pending_buf_size; // size of pending_buf
        		// pending_out; // next pending byte to output to the stream
        		// pending; // nb of bytes in the pending buffer
        		var method; // STORED (for zip only) or DEFLATED
        		var last_flush; // value of flush param for previous deflate call
        
        		var w_size; // LZ77 window size (32K by default)
        		var w_bits; // log2(w_size) (8..16)
        		var w_mask; // w_size - 1
        
        		var window;
        		// Sliding window. Input bytes are read into the second half of the window,
        		// and move to the first half later to keep a dictionary of at least wSize
        		// bytes. With this organization, matches are limited to a distance of
        		// wSize-MAX_MATCH bytes, but this ensures that IO is always
        		// performed with a length multiple of the block size. Also, it limits
        		// the window size to 64K, which is quite useful on MSDOS.
        		// To do: use the user input buffer as sliding window.
        
        		var window_size;
        		// Actual size of window: 2*wSize, except when the user input buffer
        		// is directly used as sliding window.
        
        		var prev;
        		// Link to older string with same hash index. To limit the size of this
        		// array to 64K, this link is maintained only for the last 32K strings.
        		// An index in this array is thus a window index modulo 32K.
        
        		var head; // Heads of the hash chains or NIL.
        
        		var ins_h; // hash index of string to be inserted
        		var hash_size; // number of elements in hash table
        		var hash_bits; // log2(hash_size)
        		var hash_mask; // hash_size-1
        
        		// Number of bits by which ins_h must be shifted at each input
        		// step. It must be such that after MIN_MATCH steps, the oldest
        		// byte no longer takes part in the hash key, that is:
        		// hash_shift * MIN_MATCH >= hash_bits
        		var hash_shift;
        
        		// Window position at the beginning of the current output block. Gets
        		// negative when the window is moved backwards.
        
        		var block_start;
        
        		var match_length; // length of best match
        		var prev_match; // previous match
        		var match_available; // set if previous match exists
        		var strstart; // start of string to insert
        		var match_start; // start of matching string
        		var lookahead; // number of valid bytes ahead in window
        
        		// Length of the best match at previous step. Matches not greater than this
        		// are discarded. This is used in the lazy match evaluation.
        		var prev_length;
        
        		// To speed up deflation, hash chains are never searched beyond this
        		// length. A higher limit improves compression ratio but degrades the speed.
        		var max_chain_length;
        
        		// Attempt to find a better match only when the current match is strictly
        		// smaller than this value. This mechanism is used only for compression
        		// levels >= 4.
        		var max_lazy_match;
        
        		// Insert new strings in the hash table only if the match length is not
        		// greater than this length. This saves time but degrades compression.
        		// max_insert_length is used only for compression levels <= 3.
        
        		var level; // compression level (1..9)
        		var strategy; // favor or force Huffman coding
        
        		// Use a faster search when the previous match is longer than this
        		var good_match;
        
        		// Stop searching when current match exceeds this
        		var nice_match;
        
        		var dyn_ltree; // literal and length tree
        		var dyn_dtree; // distance tree
        		var bl_tree; // Huffman tree for bit lengths
        
        		var l_desc = new Tree(); // desc for literal tree
        		var d_desc = new Tree(); // desc for distance tree
        		var bl_desc = new Tree(); // desc for bit length tree
        
        		// that.heap_len; // number of elements in the heap
        		// that.heap_max; // element of largest frequency
        		// The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
        		// The same heap array is used to build all trees.
        
        		// Depth of each subtree used as tie breaker for trees of equal frequency
        		that.depth = [];
        
        		var l_buf; // index for literals or lengths */
        
        		// Size of match buffer for literals/lengths. There are 4 reasons for
        		// limiting lit_bufsize to 64K:
        		// - frequencies can be kept in 16 bit counters
        		// - if compression is not successful for the first block, all input
        		// data is still in the window so we can still emit a stored block even
        		// when input comes from standard input. (This can also be done for
        		// all blocks if lit_bufsize is not greater than 32K.)
        		// - if compression is not successful for a file smaller than 64K, we can
        		// even emit a stored file instead of a stored block (saving 5 bytes).
        		// This is applicable only for zip (not gzip or zlib).
        		// - creating new Huffman trees less frequently may not provide fast
        		// adaptation to changes in the input data statistics. (Take for
        		// example a binary file with poorly compressible code followed by
        		// a highly compressible string table.) Smaller buffer sizes give
        		// fast adaptation but have of course the overhead of transmitting
        		// trees more frequently.
        		// - I can't count above 4
        		var lit_bufsize;
        
        		var last_lit; // running index in l_buf
        
        		// Buffer for distances. To simplify the code, d_buf and l_buf have
        		// the same number of elements. To use different lengths, an extra flag
        		// array would be necessary.
        
        		var d_buf; // index of pendig_buf
        
        		// that.opt_len; // bit length of current block with optimal trees
        		// that.static_len; // bit length of current block with static trees
        		var matches; // number of string matches in current block
        		var last_eob_len; // bit length of EOB code for last block
        
        		// Output buffer. bits are inserted starting at the bottom (least
        		// significant bits).
        		var bi_buf;
        
        		// Number of valid bits in bi_buf. All bits above the last valid bit
        		// are always zero.
        		var bi_valid;
        
        		// number of codes at each bit length for an optimal tree
        		that.bl_count = [];
        
        		// heap used to build the Huffman trees
        		that.heap = [];
        
        		dyn_ltree = [];
        		dyn_dtree = [];
        		bl_tree = [];
        
        		function lm_init() {
        			var i;
        			window_size = 2 * w_size;
        
        			head[hash_size - 1] = 0;
        			for (i = 0; i < hash_size - 1; i++) {
        				head[i] = 0;
        			}
        
        			// Set the default configuration parameters:
        			max_lazy_match = config_table[level].max_lazy;
        			good_match = config_table[level].good_length;
        			nice_match = config_table[level].nice_length;
        			max_chain_length = config_table[level].max_chain;
        
        			strstart = 0;
        			block_start = 0;
        			lookahead = 0;
        			match_length = prev_length = MIN_MATCH - 1;
        			match_available = 0;
        			ins_h = 0;
        		}
        
        		function init_block() {
        			var i;
        			// Initialize the trees.
        			for (i = 0; i < L_CODES; i++)
        				dyn_ltree[i * 2] = 0;
        			for (i = 0; i < D_CODES; i++)
        				dyn_dtree[i * 2] = 0;
        			for (i = 0; i < BL_CODES; i++)
        				bl_tree[i * 2] = 0;
        
        			dyn_ltree[END_BLOCK * 2] = 1;
        			that.opt_len = that.static_len = 0;
        			last_lit = matches = 0;
        		}
        
        		// Initialize the tree data structures for a new zlib stream.
        		function tr_init() {
        
        			l_desc.dyn_tree = dyn_ltree;
        			l_desc.stat_desc = StaticTree.static_l_desc;
        
        			d_desc.dyn_tree = dyn_dtree;
        			d_desc.stat_desc = StaticTree.static_d_desc;
        
        			bl_desc.dyn_tree = bl_tree;
        			bl_desc.stat_desc = StaticTree.static_bl_desc;
        
        			bi_buf = 0;
        			bi_valid = 0;
        			last_eob_len = 8; // enough lookahead for inflate
        
        			// Initialize the first block of the first file:
        			init_block();
        		}
        
        		// Restore the heap property by moving down the tree starting at node k,
        		// exchanging a node with the smallest of its two sons if necessary,
        		// stopping
        		// when the heap property is re-established (each father smaller than its
        		// two sons).
        		that.pqdownheap = function(tree, // the tree to restore
        		k // node to move down
        		) {
        			var heap = that.heap;
        			var v = heap[k];
        			var j = k << 1; // left son of k
        			while (j <= that.heap_len) {
        				// Set j to the smallest of the two sons:
        				if (j < that.heap_len && smaller(tree, heap[j + 1], heap[j], that.depth)) {
        					j++;
        				}
        				// Exit if v is smaller than both sons
        				if (smaller(tree, v, heap[j], that.depth))
        					break;
        
        				// Exchange v with the smallest son
        				heap[k] = heap[j];
        				k = j;
        				// And continue down the tree, setting j to the left son of k
        				j <<= 1;
        			}
        			heap[k] = v;
        		};
        
        		// Scan a literal or distance tree to determine the frequencies of the codes
        		// in the bit length tree.
        		function scan_tree(tree,// the tree to be scanned
        		max_code // and its largest code of non zero frequency
        		) {
        			var n; // iterates over all tree elements
        			var prevlen = -1; // last emitted length
        			var curlen; // length of current code
        			var nextlen = tree[0 * 2 + 1]; // length of next code
        			var count = 0; // repeat count of the current code
        			var max_count = 7; // max repeat count
        			var min_count = 4; // min repeat count
        
        			if (nextlen === 0) {
        				max_count = 138;
        				min_count = 3;
        			}
        			tree[(max_code + 1) * 2 + 1] = 0xffff; // guard
        
        			for (n = 0; n <= max_code; n++) {
        				curlen = nextlen;
        				nextlen = tree[(n + 1) * 2 + 1];
        				if (++count < max_count && curlen == nextlen) {
        					continue;
        				} else if (count < min_count) {
        					bl_tree[curlen * 2] += count;
        				} else if (curlen !== 0) {
        					if (curlen != prevlen)
        						bl_tree[curlen * 2]++;
        					bl_tree[REP_3_6 * 2]++;
        				} else if (count <= 10) {
        					bl_tree[REPZ_3_10 * 2]++;
        				} else {
        					bl_tree[REPZ_11_138 * 2]++;
        				}
        				count = 0;
        				prevlen = curlen;
        				if (nextlen === 0) {
        					max_count = 138;
        					min_count = 3;
        				} else if (curlen == nextlen) {
        					max_count = 6;
        					min_count = 3;
        				} else {
        					max_count = 7;
        					min_count = 4;
        				}
        			}
        		}
        
        		// Construct the Huffman tree for the bit lengths and return the index in
        		// bl_order of the last bit length code to send.
        		function build_bl_tree() {
        			var max_blindex; // index of last bit length code of non zero freq
        
        			// Determine the bit length frequencies for literal and distance trees
        			scan_tree(dyn_ltree, l_desc.max_code);
        			scan_tree(dyn_dtree, d_desc.max_code);
        
        			// Build the bit length tree:
        			bl_desc.build_tree(that);
        			// opt_len now includes the length of the tree representations, except
        			// the lengths of the bit lengths codes and the 5+5+4 bits for the
        			// counts.
        
        			// Determine the number of bit length codes to send. The pkzip format
        			// requires that at least 4 bit length codes be sent. (appnote.txt says
        			// 3 but the actual value used is 4.)
        			for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
        				if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] !== 0)
        					break;
        			}
        			// Update opt_len to include the bit length tree and counts
        			that.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
        
        			return max_blindex;
        		}
        
        		// Output a byte on the stream.
        		// IN assertion: there is enough room in pending_buf.
        		function put_byte(p) {
        			that.pending_buf[that.pending++] = p;
        		}
        
        		function put_short(w) {
        			put_byte(w & 0xff);
        			put_byte((w >>> 8) & 0xff);
        		}
        
        		function putShortMSB(b) {
        			put_byte((b >> 8) & 0xff);
        			put_byte((b & 0xff) & 0xff);
        		}
        
        		function send_bits(value, length) {
        			var val, len = length;
        			if (bi_valid > Buf_size - len) {
        				val = value;
        				// bi_buf |= (val << bi_valid);
        				bi_buf |= ((val << bi_valid) & 0xffff);
        				put_short(bi_buf);
        				bi_buf = val >>> (Buf_size - bi_valid);
        				bi_valid += len - Buf_size;
        			} else {
        				// bi_buf |= (value) << bi_valid;
        				bi_buf |= (((value) << bi_valid) & 0xffff);
        				bi_valid += len;
        			}
        		}
        
        		function send_code(c, tree) {
        			var c2 = c * 2;
        			send_bits(tree[c2] & 0xffff, tree[c2 + 1] & 0xffff);
        		}
        
        		// Send a literal or distance tree in compressed form, using the codes in
        		// bl_tree.
        		function send_tree(tree,// the tree to be sent
        		max_code // and its largest code of non zero frequency
        		) {
        			var n; // iterates over all tree elements
        			var prevlen = -1; // last emitted length
        			var curlen; // length of current code
        			var nextlen = tree[0 * 2 + 1]; // length of next code
        			var count = 0; // repeat count of the current code
        			var max_count = 7; // max repeat count
        			var min_count = 4; // min repeat count
        
        			if (nextlen === 0) {
        				max_count = 138;
        				min_count = 3;
        			}
        
        			for (n = 0; n <= max_code; n++) {
        				curlen = nextlen;
        				nextlen = tree[(n + 1) * 2 + 1];
        				if (++count < max_count && curlen == nextlen) {
        					continue;
        				} else if (count < min_count) {
        					do {
        						send_code(curlen, bl_tree);
        					} while (--count !== 0);
        				} else if (curlen !== 0) {
        					if (curlen != prevlen) {
        						send_code(curlen, bl_tree);
        						count--;
        					}
        					send_code(REP_3_6, bl_tree);
        					send_bits(count - 3, 2);
        				} else if (count <= 10) {
        					send_code(REPZ_3_10, bl_tree);
        					send_bits(count - 3, 3);
        				} else {
        					send_code(REPZ_11_138, bl_tree);
        					send_bits(count - 11, 7);
        				}
        				count = 0;
        				prevlen = curlen;
        				if (nextlen === 0) {
        					max_count = 138;
        					min_count = 3;
        				} else if (curlen == nextlen) {
        					max_count = 6;
        					min_count = 3;
        				} else {
        					max_count = 7;
        					min_count = 4;
        				}
        			}
        		}
        
        		// Send the header for a block using dynamic Huffman trees: the counts, the
        		// lengths of the bit length codes, the literal tree and the distance tree.
        		// IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
        		function send_all_trees(lcodes, dcodes, blcodes) {
        			var rank; // index in bl_order
        
        			send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
        			send_bits(dcodes - 1, 5);
        			send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
        			for (rank = 0; rank < blcodes; rank++) {
        				send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3);
        			}
        			send_tree(dyn_ltree, lcodes - 1); // literal tree
        			send_tree(dyn_dtree, dcodes - 1); // distance tree
        		}
        
        		// Flush the bit buffer, keeping at most 7 bits in it.
        		function bi_flush() {
        			if (bi_valid == 16) {
        				put_short(bi_buf);
        				bi_buf = 0;
        				bi_valid = 0;
        			} else if (bi_valid >= 8) {
        				put_byte(bi_buf & 0xff);
        				bi_buf >>>= 8;
        				bi_valid -= 8;
        			}
        		}
        
        		// Send one empty static block to give enough lookahead for inflate.
        		// This takes 10 bits, of which 7 may remain in the bit buffer.
        		// The current inflate code requires 9 bits of lookahead. If the
        		// last two codes for the previous block (real code plus EOB) were coded
        		// on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
        		// the last real code. In this case we send two empty static blocks instead
        		// of one. (There are no problems if the previous block is stored or fixed.)
        		// To simplify the code, we assume the worst case of last real code encoded
        		// on one bit only.
        		function _tr_align() {
        			send_bits(STATIC_TREES << 1, 3);
        			send_code(END_BLOCK, StaticTree.static_ltree);
        
        			bi_flush();
        
        			// Of the 10 bits for the empty block, we have already sent
        			// (10 - bi_valid) bits. The lookahead for the last real code (before
        			// the EOB of the previous block) was thus at least one plus the length
        			// of the EOB plus what we have just sent of the empty static block.
        			if (1 + last_eob_len + 10 - bi_valid < 9) {
        				send_bits(STATIC_TREES << 1, 3);
        				send_code(END_BLOCK, StaticTree.static_ltree);
        				bi_flush();
        			}
        			last_eob_len = 7;
        		}
        
        		// Save the match info and tally the frequency counts. Return true if
        		// the current block must be flushed.
        		function _tr_tally(dist, // distance of matched string
        		lc // match length-MIN_MATCH or unmatched char (if dist==0)
        		) {
        			var out_length, in_length, dcode;
        			that.pending_buf[d_buf + last_lit * 2] = (dist >>> 8) & 0xff;
        			that.pending_buf[d_buf + last_lit * 2 + 1] = dist & 0xff;
        
        			that.pending_buf[l_buf + last_lit] = lc & 0xff;
        			last_lit++;
        
        			if (dist === 0) {
        				// lc is the unmatched char
        				dyn_ltree[lc * 2]++;
        			} else {
        				matches++;
        				// Here, lc is the match length - MIN_MATCH
        				dist--; // dist = match distance - 1
        				dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++;
        				dyn_dtree[Tree.d_code(dist) * 2]++;
        			}
        
        			if ((last_lit & 0x1fff) === 0 && level > 2) {
        				// Compute an upper bound for the compressed length
        				out_length = last_lit * 8;
        				in_length = strstart - block_start;
        				for (dcode = 0; dcode < D_CODES; dcode++) {
        					out_length += dyn_dtree[dcode * 2] * (5 + Tree.extra_dbits[dcode]);
        				}
        				out_length >>>= 3;
        				if ((matches < Math.floor(last_lit / 2)) && out_length < Math.floor(in_length / 2))
        					return true;
        			}
        
        			return (last_lit == lit_bufsize - 1);
        			// We avoid equality with lit_bufsize because of wraparound at 64K
        			// on 16 bit machines and because stored blocks are restricted to
        			// 64K-1 bytes.
        		}
        
        		// Send the block data compressed using the given Huffman trees
        		function compress_block(ltree, dtree) {
        			var dist; // distance of matched string
        			var lc; // match length or unmatched char (if dist === 0)
        			var lx = 0; // running index in l_buf
        			var code; // the code to send
        			var extra; // number of extra bits to send
        
        			if (last_lit !== 0) {
        				do {
        					dist = ((that.pending_buf[d_buf + lx * 2] << 8) & 0xff00) | (that.pending_buf[d_buf + lx * 2 + 1] & 0xff);
        					lc = (that.pending_buf[l_buf + lx]) & 0xff;
        					lx++;
        
        					if (dist === 0) {
        						send_code(lc, ltree); // send a literal byte
        					} else {
        						// Here, lc is the match length - MIN_MATCH
        						code = Tree._length_code[lc];
        
        						send_code(code + LITERALS + 1, ltree); // send the length
        						// code
        						extra = Tree.extra_lbits[code];
        						if (extra !== 0) {
        							lc -= Tree.base_length[code];
        							send_bits(lc, extra); // send the extra length bits
        						}
        						dist--; // dist is now the match distance - 1
        						code = Tree.d_code(dist);
        
        						send_code(code, dtree); // send the distance code
        						extra = Tree.extra_dbits[code];
        						if (extra !== 0) {
        							dist -= Tree.base_dist[code];
        							send_bits(dist, extra); // send the extra distance bits
        						}
        					} // literal or match pair ?
        
        					// Check that the overlay between pending_buf and d_buf+l_buf is
        					// ok:
        				} while (lx < last_lit);
        			}
        
        			send_code(END_BLOCK, ltree);
        			last_eob_len = ltree[END_BLOCK * 2 + 1];
        		}
        
        		// Flush the bit buffer and align the output on a byte boundary
        		function bi_windup() {
        			if (bi_valid > 8) {
        				put_short(bi_buf);
        			} else if (bi_valid > 0) {
        				put_byte(bi_buf & 0xff);
        			}
        			bi_buf = 0;
        			bi_valid = 0;
        		}
        
        		// Copy a stored block, storing first the length and its
        		// one's complement if requested.
        		function copy_block(buf, // the input data
        		len, // its length
        		header // true if block header must be written
        		) {
        			bi_windup(); // align on byte boundary
        			last_eob_len = 8; // enough lookahead for inflate
        
        			if (header) {
        				put_short(len);
        				put_short(~len);
        			}
        
        			that.pending_buf.set(window.subarray(buf, buf + len), that.pending);
        			that.pending += len;
        		}
        
        		// Send a stored block
        		function _tr_stored_block(buf, // input block
        		stored_len, // length of input block
        		eof // true if this is the last block for a file
        		) {
        			send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
        			copy_block(buf, stored_len, true); // with header
        		}
        
        		// Determine the best encoding for the current block: dynamic trees, static
        		// trees or store, and output the encoded block to the zip file.
        		function _tr_flush_block(buf, // input block, or NULL if too old
        		stored_len, // length of input block
        		eof // true if this is the last block for a file
        		) {
        			var opt_lenb, static_lenb;// opt_len and static_len in bytes
        			var max_blindex = 0; // index of last bit length code of non zero freq
        
        			// Build the Huffman trees unless a stored block is forced
        			if (level > 0) {
        				// Construct the literal and distance trees
        				l_desc.build_tree(that);
        
        				d_desc.build_tree(that);
        
        				// At this point, opt_len and static_len are the total bit lengths
        				// of
        				// the compressed block data, excluding the tree representations.
        
        				// Build the bit length tree for the above two trees, and get the
        				// index
        				// in bl_order of the last bit length code to send.
        				max_blindex = build_bl_tree();
        
        				// Determine the best encoding. Compute first the block length in
        				// bytes
        				opt_lenb = (that.opt_len + 3 + 7) >>> 3;
        				static_lenb = (that.static_len + 3 + 7) >>> 3;
        
        				if (static_lenb <= opt_lenb)
        					opt_lenb = static_lenb;
        			} else {
        				opt_lenb = static_lenb = stored_len + 5; // force a stored block
        			}
        
        			if ((stored_len + 4 <= opt_lenb) && buf != -1) {
        				// 4: two words for the lengths
        				// The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
        				// Otherwise we can't have processed more than WSIZE input bytes
        				// since
        				// the last block flush, because compression would have been
        				// successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
        				// transform a block into a stored block.
        				_tr_stored_block(buf, stored_len, eof);
        			} else if (static_lenb == opt_lenb) {
        				send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
        				compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
        			} else {
        				send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
        				send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1);
        				compress_block(dyn_ltree, dyn_dtree);
        			}
        
        			// The above check is made mod 2^32, for files larger than 512 MB
        			// and uLong implemented on 32 bits.
        
        			init_block();
        
        			if (eof) {
        				bi_windup();
        			}
        		}
        
        		function flush_block_only(eof) {
        			_tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof);
        			block_start = strstart;
        			strm.flush_pending();
        		}
        
        		// Fill the window when the lookahead becomes insufficient.
        		// Updates strstart and lookahead.
        		//
        		// IN assertion: lookahead < MIN_LOOKAHEAD
        		// OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
        		// At least one byte has been read, or avail_in === 0; reads are
        		// performed for at least two bytes (required for the zip translate_eol
        		// option -- not supported here).
        		function fill_window() {
        			var n, m;
        			var p;
        			var more; // Amount of free space at the end of the window.
        
        			do {
        				more = (window_size - lookahead - strstart);
        
        				// Deal with !@#$% 64K limit:
        				if (more === 0 && strstart === 0 && lookahead === 0) {
        					more = w_size;
        				} else if (more == -1) {
        					// Very unlikely, but possible on 16 bit machine if strstart ==
        					// 0
        					// and lookahead == 1 (input done one byte at time)
        					more--;
        
        					// If the window is almost full and there is insufficient
        					// lookahead,
        					// move the upper half to the lower one to make room in the
        					// upper half.
        				} else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) {
        					window.set(window.subarray(w_size, w_size + w_size), 0);
        
        					match_start -= w_size;
        					strstart -= w_size; // we now have strstart >= MAX_DIST
        					block_start -= w_size;
        
        					// Slide the hash table (could be avoided with 32 bit values
        					// at the expense of memory usage). We slide even when level ==
        					// 0
        					// to keep the hash table consistent if we switch back to level
        					// > 0
        					// later. (Using level 0 permanently is not an optimal usage of
        					// zlib, so we don't care about this pathological case.)
        
        					n = hash_size;
        					p = n;
        					do {
        						m = (head[--p] & 0xffff);
        						head[p] = (m >= w_size ? m - w_size : 0);
        					} while (--n !== 0);
        
        					n = w_size;
        					p = n;
        					do {
        						m = (prev[--p] & 0xffff);
        						prev[p] = (m >= w_size ? m - w_size : 0);
        						// If n is not on any hash chain, prev[n] is garbage but
        						// its value will never be used.
        					} while (--n !== 0);
        					more += w_size;
        				}
        
        				if (strm.avail_in === 0)
        					return;
        
        				// If there was no sliding:
        				// strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
        				// more == window_size - lookahead - strstart
        				// => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
        				// => more >= window_size - 2*WSIZE + 2
        				// In the BIG_MEM or MMAP case (not yet supported),
        				// window_size == input_size + MIN_LOOKAHEAD &&
        				// strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
        				// Otherwise, window_size == 2*WSIZE so more >= 2.
        				// If there was sliding, more >= WSIZE. So in all cases, more >= 2.
        
        				n = strm.read_buf(window, strstart + lookahead, more);
        				lookahead += n;
        
        				// Initialize the hash value now that we have some input:
        				if (lookahead >= MIN_MATCH) {
        					ins_h = window[strstart] & 0xff;
        					ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
        				}
        				// If the whole input has less than MIN_MATCH bytes, ins_h is
        				// garbage,
        				// but this is not important since only literal bytes will be
        				// emitted.
        			} while (lookahead < MIN_LOOKAHEAD && strm.avail_in !== 0);
        		}
        
        		// Copy without compression as much as possible from the input stream,
        		// return
        		// the current block state.
        		// This function does not insert new strings in the dictionary since
        		// uncompressible data is probably not useful. This function is used
        		// only for the level=0 compression option.
        		// NOTE: this function should be optimized to avoid extra copying from
        		// window to pending_buf.
        		function deflate_stored(flush) {
        			// Stored blocks are limited to 0xffff bytes, pending_buf is limited
        			// to pending_buf_size, and each stored block has a 5 byte header:
        
        			var max_block_size = 0xffff;
        			var max_start;
        
        			if (max_block_size > pending_buf_size - 5) {
        				max_block_size = pending_buf_size - 5;
        			}
        
        			// Copy as much as possible from input to output:
        			while (true) {
        				// Fill the window as much as possible:
        				if (lookahead <= 1) {
        					fill_window();
        					if (lookahead === 0 && flush == Z_NO_FLUSH)
        						return NeedMore;
        					if (lookahead === 0)
        						break; // flush the current block
        				}
        
        				strstart += lookahead;
        				lookahead = 0;
        
        				// Emit a stored block if pending_buf will be full:
        				max_start = block_start + max_block_size;
        				if (strstart === 0 || strstart >= max_start) {
        					// strstart === 0 is possible when wraparound on 16-bit machine
        					lookahead = (strstart - max_start);
        					strstart = max_start;
        
        					flush_block_only(false);
        					if (strm.avail_out === 0)
        						return NeedMore;
        
        				}
        
        				// Flush if we may have to slide, otherwise block_start may become
        				// negative and the data will be gone:
        				if (strstart - block_start >= w_size - MIN_LOOKAHEAD) {
        					flush_block_only(false);
        					if (strm.avail_out === 0)
        						return NeedMore;
        				}
        			}
        
        			flush_block_only(flush == Z_FINISH);
        			if (strm.avail_out === 0)
        				return (flush == Z_FINISH) ? FinishStarted : NeedMore;
        
        			return flush == Z_FINISH ? FinishDone : BlockDone;
        		}
        
        		function longest_match(cur_match) {
        			var chain_length = max_chain_length; // max hash chain length
        			var scan = strstart; // current string
        			var match; // matched string
        			var len; // length of current match
        			var best_len = prev_length; // best match length so far
        			var limit = strstart > (w_size - MIN_LOOKAHEAD) ? strstart - (w_size - MIN_LOOKAHEAD) : 0;
        			var _nice_match = nice_match;
        
        			// Stop when cur_match becomes <= limit. To simplify the code,
        			// we prevent matches with the string of window index 0.
        
        			var wmask = w_mask;
        
        			var strend = strstart + MAX_MATCH;
        			var scan_end1 = window[scan + best_len - 1];
        			var scan_end = window[scan + best_len];
        
        			// The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of
        			// 16.
        			// It is easy to get rid of this optimization if necessary.
        
        			// Do not waste too much time if we already have a good match:
        			if (prev_length >= good_match) {
        				chain_length >>= 2;
        			}
        
        			// Do not look for matches beyond the end of the input. This is
        			// necessary
        			// to make deflate deterministic.
        			if (_nice_match > lookahead)
        				_nice_match = lookahead;
        
        			do {
        				match = cur_match;
        
        				// Skip to next match if the match length cannot increase
        				// or if the match length is less than 2:
        				if (window[match + best_len] != scan_end || window[match + best_len - 1] != scan_end1 || window[match] != window[scan]
        						|| window[++match] != window[scan + 1])
        					continue;
        
        				// The check at best_len-1 can be removed because it will be made
        				// again later. (This heuristic is not always a win.)
        				// It is not necessary to compare scan[2] and match[2] since they
        				// are always equal when the other bytes match, given that
        				// the hash keys are equal and that HASH_BITS >= 8.
        				scan += 2;
        				match++;
        
        				// We check for insufficient lookahead only every 8th comparison;
        				// the 256th check will be made at strstart+258.
        				do {
        				} while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]
        						&& window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]
        						&& window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend);
        
        				len = MAX_MATCH - (strend - scan);
        				scan = strend - MAX_MATCH;
        
        				if (len > best_len) {
        					match_start = cur_match;
        					best_len = len;
        					if (len >= _nice_match)
        						break;
        					scan_end1 = window[scan + best_len - 1];
        					scan_end = window[scan + best_len];
        				}
        
        			} while ((cur_match = (prev[cur_match & wmask] & 0xffff)) > limit && --chain_length !== 0);
        
        			if (best_len <= lookahead)
        				return best_len;
        			return lookahead;
        		}
        
        		// Compress as much as possible from the input stream, return the current
        		// block state.
        		// This function does not perform lazy evaluation of matches and inserts
        		// new strings in the dictionary only for unmatched strings or for short
        		// matches. It is used only for the fast compression options.
        		function deflate_fast(flush) {
        			// short hash_head = 0; // head of the hash chain
        			var hash_head = 0; // head of the hash chain
        			var bflush; // set if current block must be flushed
        
        			while (true) {
        				// Make sure that we always have enough lookahead, except
        				// at the end of the input file. We need MAX_MATCH bytes
        				// for the next match, plus MIN_MATCH bytes to insert the
        				// string following the next match.
        				if (lookahead < MIN_LOOKAHEAD) {
        					fill_window();
        					if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
        						return NeedMore;
        					}
        					if (lookahead === 0)
        						break; // flush the current block
        				}
        
        				// Insert the string window[strstart .. strstart+2] in the
        				// dictionary, and set hash_head to the head of the hash chain:
        				if (lookahead >= MIN_MATCH) {
        					ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
        
        					// prev[strstart&w_mask]=hash_head=head[ins_h];
        					hash_head = (head[ins_h] & 0xffff);
        					prev[strstart & w_mask] = head[ins_h];
        					head[ins_h] = strstart;
        				}
        
        				// Find the longest match, discarding those <= prev_length.
        				// At this point we have always match_length < MIN_MATCH
        
        				if (hash_head !== 0 && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {
        					// To simplify the code, we prevent matches with the string
        					// of window index 0 (in particular we have to avoid a match
        					// of the string with itself at the start of the input file).
        					if (strategy != Z_HUFFMAN_ONLY) {
        						match_length = longest_match(hash_head);
        					}
        					// longest_match() sets match_start
        				}
        				if (match_length >= MIN_MATCH) {
        					// check_match(strstart, match_start, match_length);
        
        					bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH);
        
        					lookahead -= match_length;
        
        					// Insert new strings in the hash table only if the match length
        					// is not too large. This saves time but degrades compression.
        					if (match_length <= max_lazy_match && lookahead >= MIN_MATCH) {
        						match_length--; // string at strstart already in hash table
        						do {
        							strstart++;
        
        							ins_h = ((ins_h << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
        							// prev[strstart&w_mask]=hash_head=head[ins_h];
        							hash_head = (head[ins_h] & 0xffff);
        							prev[strstart & w_mask] = head[ins_h];
        							head[ins_h] = strstart;
        
        							// strstart never exceeds WSIZE-MAX_MATCH, so there are
        							// always MIN_MATCH bytes ahead.
        						} while (--match_length !== 0);
        						strstart++;
        					} else {
        						strstart += match_length;
        						match_length = 0;
        						ins_h = window[strstart] & 0xff;
        
        						ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
        						// If lookahead < MIN_MATCH, ins_h is garbage, but it does
        						// not
        						// matter since it will be recomputed at next deflate call.
        					}
        				} else {
        					// No match, output a literal byte
        
        					bflush = _tr_tally(0, window[strstart] & 0xff);
        					lookahead--;
        					strstart++;
        				}
        				if (bflush) {
        
        					flush_block_only(false);
        					if (strm.avail_out === 0)
        						return NeedMore;
        				}
        			}
        
        			flush_block_only(flush == Z_FINISH);
        			if (strm.avail_out === 0) {
        				if (flush == Z_FINISH)
        					return FinishStarted;
        				else
        					return NeedMore;
        			}
        			return flush == Z_FINISH ? FinishDone : BlockDone;
        		}
        
        		// Same as above, but achieves better compression. We use a lazy
        		// evaluation for matches: a match is finally adopted only if there is
        		// no better match at the next window position.
        		function deflate_slow(flush) {
        			// short hash_head = 0; // head of hash chain
        			var hash_head = 0; // head of hash chain
        			var bflush; // set if current block must be flushed
        			var max_insert;
        
        			// Process the input block.
        			while (true) {
        				// Make sure that we always have enough lookahead, except
        				// at the end of the input file. We need MAX_MATCH bytes
        				// for the next match, plus MIN_MATCH bytes to insert the
        				// string following the next match.
        
        				if (lookahead < MIN_LOOKAHEAD) {
        					fill_window();
        					if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
        						return NeedMore;
        					}
        					if (lookahead === 0)
        						break; // flush the current block
        				}
        
        				// Insert the string window[strstart .. strstart+2] in the
        				// dictionary, and set hash_head to the head of the hash chain:
        
        				if (lookahead >= MIN_MATCH) {
        					ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
        					// prev[strstart&w_mask]=hash_head=head[ins_h];
        					hash_head = (head[ins_h] & 0xffff);
        					prev[strstart & w_mask] = head[ins_h];
        					head[ins_h] = strstart;
        				}
        
        				// Find the longest match, discarding those <= prev_length.
        				prev_length = match_length;
        				prev_match = match_start;
        				match_length = MIN_MATCH - 1;
        
        				if (hash_head !== 0 && prev_length < max_lazy_match && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {
        					// To simplify the code, we prevent matches with the string
        					// of window index 0 (in particular we have to avoid a match
        					// of the string with itself at the start of the input file).
        
        					if (strategy != Z_HUFFMAN_ONLY) {
        						match_length = longest_match(hash_head);
        					}
        					// longest_match() sets match_start
        
        					if (match_length <= 5 && (strategy == Z_FILTERED || (match_length == MIN_MATCH && strstart - match_start > 4096))) {
        
        						// If prev_match is also MIN_MATCH, match_start is garbage
        						// but we will ignore the current match anyway.
        						match_length = MIN_MATCH - 1;
        					}
        				}
        
        				// If there was a match at the previous step and the current
        				// match is not better, output the previous match:
        				if (prev_length >= MIN_MATCH && match_length <= prev_length) {
        					max_insert = strstart + lookahead - MIN_MATCH;
        					// Do not insert strings in hash table beyond this.
        
        					// check_match(strstart-1, prev_match, prev_length);
        
        					bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
        
        					// Insert in hash table all strings up to the end of the match.
        					// strstart-1 and strstart are already inserted. If there is not
        					// enough lookahead, the last two strings are not inserted in
        					// the hash table.
        					lookahead -= prev_length - 1;
        					prev_length -= 2;
        					do {
        						if (++strstart <= max_insert) {
        							ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
        							// prev[strstart&w_mask]=hash_head=head[ins_h];
        							hash_head = (head[ins_h] & 0xffff);
        							prev[strstart & w_mask] = head[ins_h];
        							head[ins_h] = strstart;
        						}
        					} while (--prev_length !== 0);
        					match_available = 0;
        					match_length = MIN_MATCH - 1;
        					strstart++;
        
        					if (bflush) {
        						flush_block_only(false);
        						if (strm.avail_out === 0)
        							return NeedMore;
        					}
        				} else if (match_available !== 0) {
        
        					// If there was no match at the previous position, output a
        					// single literal. If there was a match but the current match
        					// is longer, truncate the previous match to a single literal.
        
        					bflush = _tr_tally(0, window[strstart - 1] & 0xff);
        
        					if (bflush) {
        						flush_block_only(false);
        					}
        					strstart++;
        					lookahead--;
        					if (strm.avail_out === 0)
        						return NeedMore;
        				} else {
        					// There is no previous match to compare with, wait for
        					// the next step to decide.
        
        					match_available = 1;
        					strstart++;
        					lookahead--;
        				}
        			}
        
        			if (match_available !== 0) {
        				bflush = _tr_tally(0, window[strstart - 1] & 0xff);
        				match_available = 0;
        			}
        			flush_block_only(flush == Z_FINISH);
        
        			if (strm.avail_out === 0) {
        				if (flush == Z_FINISH)
        					return FinishStarted;
        				else
        					return NeedMore;
        			}
        
        			return flush == Z_FINISH ? FinishDone : BlockDone;
        		}
        
        		function deflateReset(strm) {
        			strm.total_in = strm.total_out = 0;
        			strm.msg = null; //
        			
        			that.pending = 0;
        			that.pending_out = 0;
        
        			status = BUSY_STATE;
        
        			last_flush = Z_NO_FLUSH;
        
        			tr_init();
        			lm_init();
        			return Z_OK;
        		}
        
        		that.deflateInit = function(strm, _level, bits, _method, memLevel, _strategy) {
        			if (!_method)
        				_method = Z_DEFLATED;
        			if (!memLevel)
        				memLevel = DEF_MEM_LEVEL;
        			if (!_strategy)
        				_strategy = Z_DEFAULT_STRATEGY;
        
        			// byte[] my_version=ZLIB_VERSION;
        
        			//
        			// if (!version || version[0] != my_version[0]
        			// || stream_size != sizeof(z_stream)) {
        			// return Z_VERSION_ERROR;
        			// }
        
        			strm.msg = null;
        
        			if (_level == Z_DEFAULT_COMPRESSION)
        				_level = 6;
        
        			if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || _method != Z_DEFLATED || bits < 9 || bits > 15 || _level < 0 || _level > 9 || _strategy < 0
        					|| _strategy > Z_HUFFMAN_ONLY) {
        				return Z_STREAM_ERROR;
        			}
        
        			strm.dstate = that;
        
        			w_bits = bits;
        			w_size = 1 << w_bits;
        			w_mask = w_size - 1;
        
        			hash_bits = memLevel + 7;
        			hash_size = 1 << hash_bits;
        			hash_mask = hash_size - 1;
        			hash_shift = Math.floor((hash_bits + MIN_MATCH - 1) / MIN_MATCH);
        
        			window = new Uint8Array(w_size * 2);
        			prev = [];
        			head = [];
        
        			lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
        
        			// We overlay pending_buf and d_buf+l_buf. This works since the average
        			// output size for (length,distance) codes is <= 24 bits.
        			that.pending_buf = new Uint8Array(lit_bufsize * 4);
        			pending_buf_size = lit_bufsize * 4;
        
        			d_buf = Math.floor(lit_bufsize / 2);
        			l_buf = (1 + 2) * lit_bufsize;
        
        			level = _level;
        
        			strategy = _strategy;
        			method = _method & 0xff;
        
        			return deflateReset(strm);
        		};
        
        		that.deflateEnd = function() {
        			if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) {
        				return Z_STREAM_ERROR;
        			}
        			// Deallocate in reverse order of allocations:
        			that.pending_buf = null;
        			head = null;
        			prev = null;
        			window = null;
        			// free
        			that.dstate = null;
        			return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
        		};
        
        		that.deflateParams = function(strm, _level, _strategy) {
        			var err = Z_OK;
        
        			if (_level == Z_DEFAULT_COMPRESSION) {
        				_level = 6;
        			}
        			if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
        				return Z_STREAM_ERROR;
        			}
        
        			if (config_table[level].func != config_table[_level].func && strm.total_in !== 0) {
        				// Flush the last buffer:
        				err = strm.deflate(Z_PARTIAL_FLUSH);
        			}
        
        			if (level != _level) {
        				level = _level;
        				max_lazy_match = config_table[level].max_lazy;
        				good_match = config_table[level].good_length;
        				nice_match = config_table[level].nice_length;
        				max_chain_length = config_table[level].max_chain;
        			}
        			strategy = _strategy;
        			return err;
        		};
        
        		that.deflateSetDictionary = function(strm, dictionary, dictLength) {
        			var length = dictLength;
        			var n, index = 0;
        
        			if (!dictionary || status != INIT_STATE)
        				return Z_STREAM_ERROR;
        
        			if (length < MIN_MATCH)
        				return Z_OK;
        			if (length > w_size - MIN_LOOKAHEAD) {
        				length = w_size - MIN_LOOKAHEAD;
        				index = dictLength - length; // use the tail of the dictionary
        			}
        			window.set(dictionary.subarray(index, index + length), 0);
        
        			strstart = length;
        			block_start = length;
        
        			// Insert all strings in the hash table (except for the last two bytes).
        			// s->lookahead stays null, so s->ins_h will be recomputed at the next
        			// call of fill_window.
        
        			ins_h = window[0] & 0xff;
        			ins_h = (((ins_h) << hash_shift) ^ (window[1] & 0xff)) & hash_mask;
        
        			for (n = 0; n <= length - MIN_MATCH; n++) {
        				ins_h = (((ins_h) << hash_shift) ^ (window[(n) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
        				prev[n & w_mask] = head[ins_h];
        				head[ins_h] = n;
        			}
        			return Z_OK;
        		};
        
        		that.deflate = function(_strm, flush) {
        			var i, header, level_flags, old_flush, bstate;
        
        			if (flush > Z_FINISH || flush < 0) {
        				return Z_STREAM_ERROR;
        			}
        
        			if (!_strm.next_out || (!_strm.next_in && _strm.avail_in !== 0) || (status == FINISH_STATE && flush != Z_FINISH)) {
        				_strm.msg = z_errmsg[Z_NEED_DICT - (Z_STREAM_ERROR)];
        				return Z_STREAM_ERROR;
        			}
        			if (_strm.avail_out === 0) {
        				_strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
        				return Z_BUF_ERROR;
        			}
        
        			strm = _strm; // just in case
        			old_flush = last_flush;
        			last_flush = flush;
        
        			// Write the zlib header
        			if (status == INIT_STATE) {
        				header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8;
        				level_flags = ((level - 1) & 0xff) >> 1;
        
        				if (level_flags > 3)
        					level_flags = 3;
        				header |= (level_flags << 6);
        				if (strstart !== 0)
        					header |= PRESET_DICT;
        				header += 31 - (header % 31);
        
        				status = BUSY_STATE;
        				putShortMSB(header);
        			}
        
        			// Flush as much pending output as possible
        			if (that.pending !== 0) {
        				strm.flush_pending();
        				if (strm.avail_out === 0) {
        					// console.log(" avail_out==0");
        					// Since avail_out is 0, deflate will be called again with
        					// more output space, but possibly with both pending and
        					// avail_in equal to zero. There won't be anything to do,
        					// but this is not an error situation so make sure we
        					// return OK instead of BUF_ERROR at next call of deflate:
        					last_flush = -1;
        					return Z_OK;
        				}
        
        				// Make sure there is something to do and avoid duplicate
        				// consecutive
        				// flushes. For repeated and useless calls with Z_FINISH, we keep
        				// returning Z_STREAM_END instead of Z_BUFF_ERROR.
        			} else if (strm.avail_in === 0 && flush <= old_flush && flush != Z_FINISH) {
        				strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
        				return Z_BUF_ERROR;
        			}
        
        			// User must not provide more input after the first FINISH:
        			if (status == FINISH_STATE && strm.avail_in !== 0) {
        				_strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
        				return Z_BUF_ERROR;
        			}
        
        			// Start a new block or continue the current one.
        			if (strm.avail_in !== 0 || lookahead !== 0 || (flush != Z_NO_FLUSH && status != FINISH_STATE)) {
        				bstate = -1;
        				switch (config_table[level].func) {
        				case STORED:
        					bstate = deflate_stored(flush);
        					break;
        				case FAST:
        					bstate = deflate_fast(flush);
        					break;
        				case SLOW:
        					bstate = deflate_slow(flush);
        					break;
        				default:
        				}
        
        				if (bstate == FinishStarted || bstate == FinishDone) {
        					status = FINISH_STATE;
        				}
        				if (bstate == NeedMore || bstate == FinishStarted) {
        					if (strm.avail_out === 0) {
        						last_flush = -1; // avoid BUF_ERROR next call, see above
        					}
        					return Z_OK;
        					// If flush != Z_NO_FLUSH && avail_out === 0, the next call
        					// of deflate should use the same flush parameter to make sure
        					// that the flush is complete. So we don't have to output an
        					// empty block here, this will be done at next call. This also
        					// ensures that for a very small output buffer, we emit at most
        					// one empty block.
        				}
        
        				if (bstate == BlockDone) {
        					if (flush == Z_PARTIAL_FLUSH) {
        						_tr_align();
        					} else { // FULL_FLUSH or SYNC_FLUSH
        						_tr_stored_block(0, 0, false);
        						// For a full flush, this empty block will be recognized
        						// as a special marker by inflate_sync().
        						if (flush == Z_FULL_FLUSH) {
        							// state.head[s.hash_size-1]=0;
        							for (i = 0; i < hash_size/*-1*/; i++)
        								// forget history
        								head[i] = 0;
        						}
        					}
        					strm.flush_pending();
        					if (strm.avail_out === 0) {
        						last_flush = -1; // avoid BUF_ERROR at next call, see above
        						return Z_OK;
        					}
        				}
        			}
        
        			if (flush != Z_FINISH)
        				return Z_OK;
        			return Z_STREAM_END;
        		};
        	}
        
        	// ZStream
        
        	function ZStream() {
        		var that = this;
        		that.next_in_index = 0;
        		that.next_out_index = 0;
        		// that.next_in; // next input byte
        		that.avail_in = 0; // number of bytes available at next_in
        		that.total_in = 0; // total nb of input bytes read so far
        		// that.next_out; // next output byte should be put there
        		that.avail_out = 0; // remaining free space at next_out
        		that.total_out = 0; // total nb of bytes output so far
        		// that.msg;
        		// that.dstate;
        	}
        
        	ZStream.prototype = {
        		deflateInit : function(level, bits) {
        			var that = this;
        			that.dstate = new Deflate();
        			if (!bits)
        				bits = MAX_BITS;
        			return that.dstate.deflateInit(that, level, bits);
        		},
        
        		deflate : function(flush) {
        			var that = this;
        			if (!that.dstate) {
        				return Z_STREAM_ERROR;
        			}
        			return that.dstate.deflate(that, flush);
        		},
        
        		deflateEnd : function() {
        			var that = this;
        			if (!that.dstate)
        				return Z_STREAM_ERROR;
        			var ret = that.dstate.deflateEnd();
        			that.dstate = null;
        			return ret;
        		},
        
        		deflateParams : function(level, strategy) {
        			var that = this;
        			if (!that.dstate)
        				return Z_STREAM_ERROR;
        			return that.dstate.deflateParams(that, level, strategy);
        		},
        
        		deflateSetDictionary : function(dictionary, dictLength) {
        			var that = this;
        			if (!that.dstate)
        				return Z_STREAM_ERROR;
        			return that.dstate.deflateSetDictionary(that, dictionary, dictLength);
        		},
        
        		// Read a new buffer from the current input stream, update the
        		// total number of bytes read. All deflate() input goes through
        		// this function so some applications may wish to modify it to avoid
        		// allocating a large strm->next_in buffer and copying from it.
        		// (See also flush_pending()).
        		read_buf : function(buf, start, size) {
        			var that = this;
        			var len = that.avail_in;
        			if (len > size)
        				len = size;
        			if (len === 0)
        				return 0;
        			that.avail_in -= len;
        			buf.set(that.next_in.subarray(that.next_in_index, that.next_in_index + len), start);
        			that.next_in_index += len;
        			that.total_in += len;
        			return len;
        		},
        
        		// Flush as much pending output as possible. All deflate() output goes
        		// through this function so some applications may wish to modify it
        		// to avoid allocating a large strm->next_out buffer and copying into it.
        		// (See also read_buf()).
        		flush_pending : function() {
        			var that = this;
        			var len = that.dstate.pending;
        
        			if (len > that.avail_out)
        				len = that.avail_out;
        			if (len === 0)
        				return;
        
        			// if (that.dstate.pending_buf.length <= that.dstate.pending_out || that.next_out.length <= that.next_out_index
        			// || that.dstate.pending_buf.length < (that.dstate.pending_out + len) || that.next_out.length < (that.next_out_index +
        			// len)) {
        			// console.log(that.dstate.pending_buf.length + ", " + that.dstate.pending_out + ", " + that.next_out.length + ", " +
        			// that.next_out_index + ", " + len);
        			// console.log("avail_out=" + that.avail_out);
        			// }
        
        			that.next_out.set(that.dstate.pending_buf.subarray(that.dstate.pending_out, that.dstate.pending_out + len), that.next_out_index);
        
        			that.next_out_index += len;
        			that.dstate.pending_out += len;
        			that.total_out += len;
        			that.avail_out -= len;
        			that.dstate.pending -= len;
        			if (that.dstate.pending === 0) {
        				that.dstate.pending_out = 0;
        			}
        		}
        	};
        
        	// Deflater
        
        	function Deflater(options) {
        		var that = this;
        		var z = new ZStream();
        		var bufsize = 512;
        		var flush = Z_NO_FLUSH;
        		var buf = new Uint8Array(bufsize);
        		var level = options ? options.level : Z_DEFAULT_COMPRESSION;
        		if (typeof level == "undefined")
        			level = Z_DEFAULT_COMPRESSION;
        		z.deflateInit(level);
        		z.next_out = buf;
        
        		that.append = function(data, onprogress) {
        			var err, buffers = [], lastIndex = 0, bufferIndex = 0, bufferSize = 0, array;
        			if (!data.length)
        				return;
        			z.next_in_index = 0;
        			z.next_in = data;
        			z.avail_in = data.length;
        			do {
        				z.next_out_index = 0;
        				z.avail_out = bufsize;
        				err = z.deflate(flush);
        				if (err != Z_OK)
        					throw new Error("deflating: " + z.msg);
        				if (z.next_out_index)
        					if (z.next_out_index == bufsize)
        						buffers.push(new Uint8Array(buf));
        					else
        						buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
        				bufferSize += z.next_out_index;
        				if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
        					onprogress(z.next_in_index);
        					lastIndex = z.next_in_index;
        				}
        			} while (z.avail_in > 0 || z.avail_out === 0);
        			array = new Uint8Array(bufferSize);
        			buffers.forEach(function(chunk) {
        				array.set(chunk, bufferIndex);
        				bufferIndex += chunk.length;
        			});
        			return array;
        		};
        		that.flush = function() {
        			var err, buffers = [], bufferIndex = 0, bufferSize = 0, array;
        			do {
        				z.next_out_index = 0;
        				z.avail_out = bufsize;
        				err = z.deflate(Z_FINISH);
        				if (err != Z_STREAM_END && err != Z_OK)
        					throw new Error("deflating: " + z.msg);
        				if (bufsize - z.avail_out > 0)
        					buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
        				bufferSize += z.next_out_index;
        			} while (z.avail_in > 0 || z.avail_out === 0);
        			z.deflateEnd();
        			array = new Uint8Array(bufferSize);
        			buffers.forEach(function(chunk) {
        				array.set(chunk, bufferIndex);
        				bufferIndex += chunk.length;
        			});
        			return array;
        		};
        	}
        
        	// 'zip' may not be defined in z-worker and some tests
        	var env = global.zip || global;
        	env.Deflater = env._jzlib_Deflater = Deflater;
        })(this);
      • inflate.js
        /*
         Copyright (c) 2013 Gildas Lormeau. All rights reserved.
        
         Redistribution and use in source and binary forms, with or without
         modification, are permitted provided that the following conditions are met:
        
         1. Redistributions of source code must retain the above copyright notice,
         this list of conditions and the following disclaimer.
        
         2. Redistributions in binary form must reproduce the above copyright 
         notice, this list of conditions and the following disclaimer in 
         the documentation and/or other materials provided with the distribution.
        
         3. The names of the authors may not be used to endorse or promote products
         derived from this software without specific prior written permission.
        
         THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
         INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
         FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
         INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
         INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
         LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
         OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
         LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
         NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
         EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         */
        
        /*
         * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc.
         * JZlib is based on zlib-1.1.3, so all credit should go authors
         * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
         * and contributors of zlib.
         */
        
        (function(global) {
        	"use strict";
        
        	// Global
        	var MAX_BITS = 15;
        
        	var Z_OK = 0;
        	var Z_STREAM_END = 1;
        	var Z_NEED_DICT = 2;
        	var Z_STREAM_ERROR = -2;
        	var Z_DATA_ERROR = -3;
        	var Z_MEM_ERROR = -4;
        	var Z_BUF_ERROR = -5;
        
        	var inflate_mask = [ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff,
        			0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff ];
        
        	var MANY = 1440;
        
        	// JZlib version : "1.0.2"
        	var Z_NO_FLUSH = 0;
        	var Z_FINISH = 4;
        
        	// InfTree
        	var fixed_bl = 9;
        	var fixed_bd = 5;
        
        	var fixed_tl = [ 96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 192, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 160, 0, 8, 0,
        			0, 8, 128, 0, 8, 64, 0, 9, 224, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 144, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 208, 81, 7, 17, 0, 8, 104, 0, 8, 40,
        			0, 9, 176, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 240, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 200, 81, 7, 13,
        			0, 8, 100, 0, 8, 36, 0, 9, 168, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 232, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 152, 84, 7, 83, 0, 8, 124, 0, 8, 60,
        			0, 9, 216, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 184, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 248, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7,
        			35, 0, 8, 114, 0, 8, 50, 0, 9, 196, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 164, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 228, 80, 7, 7, 0, 8, 90, 0, 8,
        			26, 0, 9, 148, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 212, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 180, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 244, 80,
        			7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 204, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 172, 0, 8, 6, 0, 8, 134, 0,
        			8, 70, 0, 9, 236, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 156, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 220, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 188, 0,
        			8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 252, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 194, 80, 7, 10, 0, 8, 97,
        			0, 8, 33, 0, 9, 162, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 226, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 146, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 210,
        			81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 178, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 242, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117,
        			0, 8, 53, 0, 9, 202, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 170, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 234, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 154,
        			84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 218, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 186, 0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 250, 80, 7, 3, 0, 8, 83,
        			0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 198, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 166, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 230,
        			80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 150, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 214, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 182, 0, 8, 11, 0, 8, 139,
        			0, 8, 75, 0, 9, 246, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 206, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 174,
        			0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 238, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 158, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 222, 82, 7, 27, 0, 8, 111,
        			0, 8, 47, 0, 9, 190, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 254, 96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9,
        			193, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 161, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 225, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 145, 83, 7, 59, 0, 8,
        			120, 0, 8, 56, 0, 9, 209, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 177, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 241, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8,
        			227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 201, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 169, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 233, 80, 7, 8, 0, 8,
        			92, 0, 8, 28, 0, 9, 153, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 217, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 185, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9,
        			249, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 197, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 165, 0, 8, 2, 0, 8,
        			130, 0, 8, 66, 0, 9, 229, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 149, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 213, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9,
        			181, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 245, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 205, 81, 7, 15, 0, 8,
        			102, 0, 8, 38, 0, 9, 173, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 237, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 157, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9,
        			221, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 189, 0, 8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 253, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0,
        			8, 113, 0, 8, 49, 0, 9, 195, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 163, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 227, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9,
        			147, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 211, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 179, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 243, 80, 7, 4, 0, 8,
        			85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 203, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 171, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9,
        			235, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 155, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 219, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 187, 0, 8, 13, 0, 8,
        			141, 0, 8, 77, 0, 9, 251, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 199, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9,
        			167, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 231, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 151, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 215, 82, 7, 19, 0, 8,
        			107, 0, 8, 43, 0, 9, 183, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 247, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9,
        			207, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 175, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 239, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 159, 84, 7, 99, 0, 8,
        			127, 0, 8, 63, 0, 9, 223, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 191, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 255 ];
        	var fixed_td = [ 80, 5, 1, 87, 5, 257, 83, 5, 17, 91, 5, 4097, 81, 5, 5, 89, 5, 1025, 85, 5, 65, 93, 5, 16385, 80, 5, 3, 88, 5, 513, 84, 5, 33, 92, 5,
        			8193, 82, 5, 9, 90, 5, 2049, 86, 5, 129, 192, 5, 24577, 80, 5, 2, 87, 5, 385, 83, 5, 25, 91, 5, 6145, 81, 5, 7, 89, 5, 1537, 85, 5, 97, 93, 5,
        			24577, 80, 5, 4, 88, 5, 769, 84, 5, 49, 92, 5, 12289, 82, 5, 13, 90, 5, 3073, 86, 5, 193, 192, 5, 24577 ];
        
        	// Tables for deflate from PKZIP's appnote.txt.
        	var cplens = [ // Copy lengths for literal codes 257..285
        	3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 ];
        
        	// see note #13 above about 258
        	var cplext = [ // Extra bits for literal codes 257..285
        	0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
        	];
        
        	var cpdist = [ // Copy offsets for distance codes 0..29
        	1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 ];
        
        	var cpdext = [ // Extra bits for distance codes
        	0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 ];
        
        	// If BMAX needs to be larger than 16, then h and x[] should be uLong.
        	var BMAX = 15; // maximum bit length of any code
        
        	function InfTree() {
        		var that = this;
        
        		var hn; // hufts used in space
        		var v; // work area for huft_build
        		var c; // bit length count table
        		var r; // table entry for structure assignment
        		var u; // table stack
        		var x; // bit offsets, then code stack
        
        		function huft_build(b, // code lengths in bits (all assumed <=
        		// BMAX)
        		bindex, n, // number of codes (assumed <= 288)
        		s, // number of simple-valued codes (0..s-1)
        		d, // list of base values for non-simple codes
        		e, // list of extra bits for non-simple codes
        		t, // result: starting table
        		m, // maximum lookup bits, returns actual
        		hp,// space for trees
        		hn,// hufts used in space
        		v // working area: values in order of bit length
        		) {
        			// Given a list of code lengths and a maximum table size, make a set of
        			// tables to decode that set of codes. Return Z_OK on success,
        			// Z_BUF_ERROR
        			// if the given code set is incomplete (the tables are still built in
        			// this
        			// case), Z_DATA_ERROR if the input is invalid (an over-subscribed set
        			// of
        			// lengths), or Z_MEM_ERROR if not enough memory.
        
        			var a; // counter for codes of length k
        			var f; // i repeats in table every f entries
        			var g; // maximum code length
        			var h; // table level
        			var i; // counter, current code
        			var j; // counter
        			var k; // number of bits in current code
        			var l; // bits per table (returned in m)
        			var mask; // (1 << w) - 1, to avoid cc -O bug on HP
        			var p; // pointer into c[], b[], or v[]
        			var q; // points to current table
        			var w; // bits before this table == (l * h)
        			var xp; // pointer into x
        			var y; // number of dummy codes added
        			var z; // number of entries in current table
        
        			// Generate counts for each bit length
        
        			p = 0;
        			i = n;
        			do {
        				c[b[bindex + p]]++;
        				p++;
        				i--; // assume all entries <= BMAX
        			} while (i !== 0);
        
        			if (c[0] == n) { // null input--all zero length codes
        				t[0] = -1;
        				m[0] = 0;
        				return Z_OK;
        			}
        
        			// Find minimum and maximum length, bound *m by those
        			l = m[0];
        			for (j = 1; j <= BMAX; j++)
        				if (c[j] !== 0)
        					break;
        			k = j; // minimum code length
        			if (l < j) {
        				l = j;
        			}
        			for (i = BMAX; i !== 0; i--) {
        				if (c[i] !== 0)
        					break;
        			}
        			g = i; // maximum code length
        			if (l > i) {
        				l = i;
        			}
        			m[0] = l;
        
        			// Adjust last length count to fill out codes, if needed
        			for (y = 1 << j; j < i; j++, y <<= 1) {
        				if ((y -= c[j]) < 0) {
        					return Z_DATA_ERROR;
        				}
        			}
        			if ((y -= c[i]) < 0) {
        				return Z_DATA_ERROR;
        			}
        			c[i] += y;
        
        			// Generate starting offsets into the value table for each length
        			x[1] = j = 0;
        			p = 1;
        			xp = 2;
        			while (--i !== 0) { // note that i == g from above
        				x[xp] = (j += c[p]);
        				xp++;
        				p++;
        			}
        
        			// Make a table of values in order of bit lengths
        			i = 0;
        			p = 0;
        			do {
        				if ((j = b[bindex + p]) !== 0) {
        					v[x[j]++] = i;
        				}
        				p++;
        			} while (++i < n);
        			n = x[g]; // set n to length of v
        
        			// Generate the Huffman codes and for each, make the table entries
        			x[0] = i = 0; // first Huffman code is zero
        			p = 0; // grab values in bit order
        			h = -1; // no tables yet--level -1
        			w = -l; // bits decoded == (l * h)
        			u[0] = 0; // just to keep compilers happy
        			q = 0; // ditto
        			z = 0; // ditto
        
        			// go through the bit lengths (k already is bits in shortest code)
        			for (; k <= g; k++) {
        				a = c[k];
        				while (a-- !== 0) {
        					// here i is the Huffman code of length k bits for value *p
        					// make tables up to required level
        					while (k > w + l) {
        						h++;
        						w += l; // previous table always l bits
        						// compute minimum size table less than or equal to l bits
        						z = g - w;
        						z = (z > l) ? l : z; // table size upper limit
        						if ((f = 1 << (j = k - w)) > a + 1) { // try a k-w bit table
        							// too few codes for
        							// k-w bit table
        							f -= a + 1; // deduct codes from patterns left
        							xp = k;
        							if (j < z) {
        								while (++j < z) { // try smaller tables up to z bits
        									if ((f <<= 1) <= c[++xp])
        										break; // enough codes to use up j bits
        									f -= c[xp]; // else deduct codes from patterns
        								}
        							}
        						}
        						z = 1 << j; // table entries for j-bit table
        
        						// allocate new table
        						if (hn[0] + z > MANY) { // (note: doesn't matter for fixed)
        							return Z_DATA_ERROR; // overflow of MANY
        						}
        						u[h] = q = /* hp+ */hn[0]; // DEBUG
        						hn[0] += z;
        
        						// connect to last table, if there is one
        						if (h !== 0) {
        							x[h] = i; // save pattern for backing up
        							r[0] = /* (byte) */j; // bits in this table
        							r[1] = /* (byte) */l; // bits to dump before this table
        							j = i >>> (w - l);
        							r[2] = /* (int) */(q - u[h - 1] - j); // offset to this table
        							hp.set(r, (u[h - 1] + j) * 3);
        							// to
        							// last
        							// table
        						} else {
        							t[0] = q; // first table is returned result
        						}
        					}
        
        					// set up table entry in r
        					r[1] = /* (byte) */(k - w);
        					if (p >= n) {
        						r[0] = 128 + 64; // out of values--invalid code
        					} else if (v[p] < s) {
        						r[0] = /* (byte) */(v[p] < 256 ? 0 : 32 + 64); // 256 is
        						// end-of-block
        						r[2] = v[p++]; // simple code is just the value
        					} else {
        						r[0] = /* (byte) */(e[v[p] - s] + 16 + 64); // non-simple--look
        						// up in lists
        						r[2] = d[v[p++] - s];
        					}
        
        					// fill code-like entries with r
        					f = 1 << (k - w);
        					for (j = i >>> w; j < z; j += f) {
        						hp.set(r, (q + j) * 3);
        					}
        
        					// backwards increment the k-bit code i
        					for (j = 1 << (k - 1); (i & j) !== 0; j >>>= 1) {
        						i ^= j;
        					}
        					i ^= j;
        
        					// backup over finished tables
        					mask = (1 << w) - 1; // needed on HP, cc -O bug
        					while ((i & mask) != x[h]) {
        						h--; // don't need to update q
        						w -= l;
        						mask = (1 << w) - 1;
        					}
        				}
        			}
        			// Return Z_BUF_ERROR if we were given an incomplete table
        			return y !== 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
        		}
        
        		function initWorkArea(vsize) {
        			var i;
        			if (!hn) {
        				hn = []; // []; //new Array(1);
        				v = []; // new Array(vsize);
        				c = new Int32Array(BMAX + 1); // new Array(BMAX + 1);
        				r = []; // new Array(3);
        				u = new Int32Array(BMAX); // new Array(BMAX);
        				x = new Int32Array(BMAX + 1); // new Array(BMAX + 1);
        			}
        			if (v.length < vsize) {
        				v = []; // new Array(vsize);
        			}
        			for (i = 0; i < vsize; i++) {
        				v[i] = 0;
        			}
        			for (i = 0; i < BMAX + 1; i++) {
        				c[i] = 0;
        			}
        			for (i = 0; i < 3; i++) {
        				r[i] = 0;
        			}
        			// for(int i=0; i<BMAX; i++){u[i]=0;}
        			u.set(c.subarray(0, BMAX), 0);
        			// for(int i=0; i<BMAX+1; i++){x[i]=0;}
        			x.set(c.subarray(0, BMAX + 1), 0);
        		}
        
        		that.inflate_trees_bits = function(c, // 19 code lengths
        		bb, // bits tree desired/actual depth
        		tb, // bits tree result
        		hp, // space for trees
        		z // for messages
        		) {
        			var result;
        			initWorkArea(19);
        			hn[0] = 0;
        			result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
        
        			if (result == Z_DATA_ERROR) {
        				z.msg = "oversubscribed dynamic bit lengths tree";
        			} else if (result == Z_BUF_ERROR || bb[0] === 0) {
        				z.msg = "incomplete dynamic bit lengths tree";
        				result = Z_DATA_ERROR;
        			}
        			return result;
        		};
        
        		that.inflate_trees_dynamic = function(nl, // number of literal/length codes
        		nd, // number of distance codes
        		c, // that many (total) code lengths
        		bl, // literal desired/actual bit depth
        		bd, // distance desired/actual bit depth
        		tl, // literal/length tree result
        		td, // distance tree result
        		hp, // space for trees
        		z // for messages
        		) {
        			var result;
        
        			// build literal/length tree
        			initWorkArea(288);
        			hn[0] = 0;
        			result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
        			if (result != Z_OK || bl[0] === 0) {
        				if (result == Z_DATA_ERROR) {
        					z.msg = "oversubscribed literal/length tree";
        				} else if (result != Z_MEM_ERROR) {
        					z.msg = "incomplete literal/length tree";
        					result = Z_DATA_ERROR;
        				}
        				return result;
        			}
        
        			// build distance tree
        			initWorkArea(288);
        			result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
        
        			if (result != Z_OK || (bd[0] === 0 && nl > 257)) {
        				if (result == Z_DATA_ERROR) {
        					z.msg = "oversubscribed distance tree";
        				} else if (result == Z_BUF_ERROR) {
        					z.msg = "incomplete distance tree";
        					result = Z_DATA_ERROR;
        				} else if (result != Z_MEM_ERROR) {
        					z.msg = "empty distance tree with lengths";
        					result = Z_DATA_ERROR;
        				}
        				return result;
        			}
        
        			return Z_OK;
        		};
        
        	}
        
        	InfTree.inflate_trees_fixed = function(bl, // literal desired/actual bit depth
        	bd, // distance desired/actual bit depth
        	tl,// literal/length tree result
        	td// distance tree result
        	) {
        		bl[0] = fixed_bl;
        		bd[0] = fixed_bd;
        		tl[0] = fixed_tl;
        		td[0] = fixed_td;
        		return Z_OK;
        	};
        
        	// InfCodes
        
        	// waiting for "i:"=input,
        	// "o:"=output,
        	// "x:"=nothing
        	var START = 0; // x: set up for LEN
        	var LEN = 1; // i: get length/literal/eob next
        	var LENEXT = 2; // i: getting length extra (have base)
        	var DIST = 3; // i: get distance next
        	var DISTEXT = 4;// i: getting distance extra
        	var COPY = 5; // o: copying bytes in window, waiting
        	// for space
        	var LIT = 6; // o: got literal, waiting for output
        	// space
        	var WASH = 7; // o: got eob, possibly still output
        	// waiting
        	var END = 8; // x: got eob and all data flushed
        	var BADCODE = 9;// x: got error
        
        	function InfCodes() {
        		var that = this;
        
        		var mode; // current inflate_codes mode
        
        		// mode dependent information
        		var len = 0;
        
        		var tree; // pointer into tree
        		var tree_index = 0;
        		var need = 0; // bits needed
        
        		var lit = 0;
        
        		// if EXT or COPY, where and how much
        		var get = 0; // bits to get for extra
        		var dist = 0; // distance back to copy from
        
        		var lbits = 0; // ltree bits decoded per branch
        		var dbits = 0; // dtree bits decoder per branch
        		var ltree; // literal/length/eob tree
        		var ltree_index = 0; // literal/length/eob tree
        		var dtree; // distance tree
        		var dtree_index = 0; // distance tree
        
        		// Called with number of bytes left to write in window at least 258
        		// (the maximum string length) and number of input bytes available
        		// at least ten. The ten bytes are six bytes for the longest length/
        		// distance pair plus four bytes for overloading the bit buffer.
        
        		function inflate_fast(bl, bd, tl, tl_index, td, td_index, s, z) {
        			var t; // temporary pointer
        			var tp; // temporary pointer
        			var tp_index; // temporary pointer
        			var e; // extra bits or operation
        			var b; // bit buffer
        			var k; // bits in bit buffer
        			var p; // input data pointer
        			var n; // bytes available there
        			var q; // output window write pointer
        			var m; // bytes to end of window or read pointer
        			var ml; // mask for literal/length tree
        			var md; // mask for distance tree
        			var c; // bytes to copy
        			var d; // distance back to copy from
        			var r; // copy source pointer
        
        			var tp_index_t_3; // (tp_index+t)*3
        
        			// load input, output, bit values
        			p = z.next_in_index;
        			n = z.avail_in;
        			b = s.bitb;
        			k = s.bitk;
        			q = s.write;
        			m = q < s.read ? s.read - q - 1 : s.end - q;
        
        			// initialize masks
        			ml = inflate_mask[bl];
        			md = inflate_mask[bd];
        
        			// do until not enough input or output space for fast loop
        			do { // assume called with m >= 258 && n >= 10
        				// get literal/length code
        				while (k < (20)) { // max bits for literal/length code
        					n--;
        					b |= (z.read_byte(p++) & 0xff) << k;
        					k += 8;
        				}
        
        				t = b & ml;
        				tp = tl;
        				tp_index = tl_index;
        				tp_index_t_3 = (tp_index + t) * 3;
        				if ((e = tp[tp_index_t_3]) === 0) {
        					b >>= (tp[tp_index_t_3 + 1]);
        					k -= (tp[tp_index_t_3 + 1]);
        
        					s.window[q++] = /* (byte) */tp[tp_index_t_3 + 2];
        					m--;
        					continue;
        				}
        				do {
        
        					b >>= (tp[tp_index_t_3 + 1]);
        					k -= (tp[tp_index_t_3 + 1]);
        
        					if ((e & 16) !== 0) {
        						e &= 15;
        						c = tp[tp_index_t_3 + 2] + (/* (int) */b & inflate_mask[e]);
        
        						b >>= e;
        						k -= e;
        
        						// decode distance base of block to copy
        						while (k < (15)) { // max bits for distance code
        							n--;
        							b |= (z.read_byte(p++) & 0xff) << k;
        							k += 8;
        						}
        
        						t = b & md;
        						tp = td;
        						tp_index = td_index;
        						tp_index_t_3 = (tp_index + t) * 3;
        						e = tp[tp_index_t_3];
        
        						do {
        
        							b >>= (tp[tp_index_t_3 + 1]);
        							k -= (tp[tp_index_t_3 + 1]);
        
        							if ((e & 16) !== 0) {
        								// get extra bits to add to distance base
        								e &= 15;
        								while (k < (e)) { // get extra bits (up to 13)
        									n--;
        									b |= (z.read_byte(p++) & 0xff) << k;
        									k += 8;
        								}
        
        								d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
        
        								b >>= (e);
        								k -= (e);
        
        								// do the copy
        								m -= c;
        								if (q >= d) { // offset before dest
        									// just copy
        									r = q - d;
        									if (q - r > 0 && 2 > (q - r)) {
        										s.window[q++] = s.window[r++]; // minimum
        										// count is
        										// three,
        										s.window[q++] = s.window[r++]; // so unroll
        										// loop a
        										// little
        										c -= 2;
        									} else {
        										s.window.set(s.window.subarray(r, r + 2), q);
        										q += 2;
        										r += 2;
        										c -= 2;
        									}
        								} else { // else offset after destination
        									r = q - d;
        									do {
        										r += s.end; // force pointer in window
        									} while (r < 0); // covers invalid distances
        									e = s.end - r;
        									if (c > e) { // if source crosses,
        										c -= e; // wrapped copy
        										if (q - r > 0 && e > (q - r)) {
        											do {
        												s.window[q++] = s.window[r++];
        											} while (--e !== 0);
        										} else {
        											s.window.set(s.window.subarray(r, r + e), q);
        											q += e;
        											r += e;
        											e = 0;
        										}
        										r = 0; // copy rest from start of window
        									}
        
        								}
        
        								// copy all or what's left
        								if (q - r > 0 && c > (q - r)) {
        									do {
        										s.window[q++] = s.window[r++];
        									} while (--c !== 0);
        								} else {
        									s.window.set(s.window.subarray(r, r + c), q);
        									q += c;
        									r += c;
        									c = 0;
        								}
        								break;
        							} else if ((e & 64) === 0) {
        								t += tp[tp_index_t_3 + 2];
        								t += (b & inflate_mask[e]);
        								tp_index_t_3 = (tp_index + t) * 3;
        								e = tp[tp_index_t_3];
        							} else {
        								z.msg = "invalid distance code";
        
        								c = z.avail_in - n;
        								c = (k >> 3) < c ? k >> 3 : c;
        								n += c;
        								p -= c;
        								k -= c << 3;
        
        								s.bitb = b;
        								s.bitk = k;
        								z.avail_in = n;
        								z.total_in += p - z.next_in_index;
        								z.next_in_index = p;
        								s.write = q;
        
        								return Z_DATA_ERROR;
        							}
        						} while (true);
        						break;
        					}
        
        					if ((e & 64) === 0) {
        						t += tp[tp_index_t_3 + 2];
        						t += (b & inflate_mask[e]);
        						tp_index_t_3 = (tp_index + t) * 3;
        						if ((e = tp[tp_index_t_3]) === 0) {
        
        							b >>= (tp[tp_index_t_3 + 1]);
        							k -= (tp[tp_index_t_3 + 1]);
        
        							s.window[q++] = /* (byte) */tp[tp_index_t_3 + 2];
        							m--;
        							break;
        						}
        					} else if ((e & 32) !== 0) {
        
        						c = z.avail_in - n;
        						c = (k >> 3) < c ? k >> 3 : c;
        						n += c;
        						p -= c;
        						k -= c << 3;
        
        						s.bitb = b;
        						s.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						s.write = q;
        
        						return Z_STREAM_END;
        					} else {
        						z.msg = "invalid literal/length code";
        
        						c = z.avail_in - n;
        						c = (k >> 3) < c ? k >> 3 : c;
        						n += c;
        						p -= c;
        						k -= c << 3;
        
        						s.bitb = b;
        						s.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						s.write = q;
        
        						return Z_DATA_ERROR;
        					}
        				} while (true);
        			} while (m >= 258 && n >= 10);
        
        			// not enough input or output--restore pointers and return
        			c = z.avail_in - n;
        			c = (k >> 3) < c ? k >> 3 : c;
        			n += c;
        			p -= c;
        			k -= c << 3;
        
        			s.bitb = b;
        			s.bitk = k;
        			z.avail_in = n;
        			z.total_in += p - z.next_in_index;
        			z.next_in_index = p;
        			s.write = q;
        
        			return Z_OK;
        		}
        
        		that.init = function(bl, bd, tl, tl_index, td, td_index) {
        			mode = START;
        			lbits = /* (byte) */bl;
        			dbits = /* (byte) */bd;
        			ltree = tl;
        			ltree_index = tl_index;
        			dtree = td;
        			dtree_index = td_index;
        			tree = null;
        		};
        
        		that.proc = function(s, z, r) {
        			var j; // temporary storage
        			var tindex; // temporary pointer
        			var e; // extra bits or operation
        			var b = 0; // bit buffer
        			var k = 0; // bits in bit buffer
        			var p = 0; // input data pointer
        			var n; // bytes available there
        			var q; // output window write pointer
        			var m; // bytes to end of window or read pointer
        			var f; // pointer to copy strings from
        
        			// copy input/output information to locals (UPDATE macro restores)
        			p = z.next_in_index;
        			n = z.avail_in;
        			b = s.bitb;
        			k = s.bitk;
        			q = s.write;
        			m = q < s.read ? s.read - q - 1 : s.end - q;
        
        			// process input and output based on current state
        			while (true) {
        				switch (mode) {
        				// waiting for "i:"=input, "o:"=output, "x:"=nothing
        				case START: // x: set up for LEN
        					if (m >= 258 && n >= 10) {
        
        						s.bitb = b;
        						s.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						s.write = q;
        						r = inflate_fast(lbits, dbits, ltree, ltree_index, dtree, dtree_index, s, z);
        
        						p = z.next_in_index;
        						n = z.avail_in;
        						b = s.bitb;
        						k = s.bitk;
        						q = s.write;
        						m = q < s.read ? s.read - q - 1 : s.end - q;
        
        						if (r != Z_OK) {
        							mode = r == Z_STREAM_END ? WASH : BADCODE;
        							break;
        						}
        					}
        					need = lbits;
        					tree = ltree;
        					tree_index = ltree_index;
        
        					mode = LEN;
        					/* falls through */
        				case LEN: // i: get length/literal/eob next
        					j = need;
        
        					while (k < (j)) {
        						if (n !== 0)
        							r = Z_OK;
        						else {
        
        							s.bitb = b;
        							s.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							s.write = q;
        							return s.inflate_flush(z, r);
        						}
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        
        					tindex = (tree_index + (b & inflate_mask[j])) * 3;
        
        					b >>>= (tree[tindex + 1]);
        					k -= (tree[tindex + 1]);
        
        					e = tree[tindex];
        
        					if (e === 0) { // literal
        						lit = tree[tindex + 2];
        						mode = LIT;
        						break;
        					}
        					if ((e & 16) !== 0) { // length
        						get = e & 15;
        						len = tree[tindex + 2];
        						mode = LENEXT;
        						break;
        					}
        					if ((e & 64) === 0) { // next table
        						need = e;
        						tree_index = tindex / 3 + tree[tindex + 2];
        						break;
        					}
        					if ((e & 32) !== 0) { // end of block
        						mode = WASH;
        						break;
        					}
        					mode = BADCODE; // invalid code
        					z.msg = "invalid literal/length code";
        					r = Z_DATA_ERROR;
        
        					s.bitb = b;
        					s.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					s.write = q;
        					return s.inflate_flush(z, r);
        
        				case LENEXT: // i: getting length extra (have base)
        					j = get;
        
        					while (k < (j)) {
        						if (n !== 0)
        							r = Z_OK;
        						else {
        
        							s.bitb = b;
        							s.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							s.write = q;
        							return s.inflate_flush(z, r);
        						}
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        
        					len += (b & inflate_mask[j]);
        
        					b >>= j;
        					k -= j;
        
        					need = dbits;
        					tree = dtree;
        					tree_index = dtree_index;
        					mode = DIST;
        					/* falls through */
        				case DIST: // i: get distance next
        					j = need;
        
        					while (k < (j)) {
        						if (n !== 0)
        							r = Z_OK;
        						else {
        
        							s.bitb = b;
        							s.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							s.write = q;
        							return s.inflate_flush(z, r);
        						}
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        
        					tindex = (tree_index + (b & inflate_mask[j])) * 3;
        
        					b >>= tree[tindex + 1];
        					k -= tree[tindex + 1];
        
        					e = (tree[tindex]);
        					if ((e & 16) !== 0) { // distance
        						get = e & 15;
        						dist = tree[tindex + 2];
        						mode = DISTEXT;
        						break;
        					}
        					if ((e & 64) === 0) { // next table
        						need = e;
        						tree_index = tindex / 3 + tree[tindex + 2];
        						break;
        					}
        					mode = BADCODE; // invalid code
        					z.msg = "invalid distance code";
        					r = Z_DATA_ERROR;
        
        					s.bitb = b;
        					s.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					s.write = q;
        					return s.inflate_flush(z, r);
        
        				case DISTEXT: // i: getting distance extra
        					j = get;
        
        					while (k < (j)) {
        						if (n !== 0)
        							r = Z_OK;
        						else {
        
        							s.bitb = b;
        							s.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							s.write = q;
        							return s.inflate_flush(z, r);
        						}
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        
        					dist += (b & inflate_mask[j]);
        
        					b >>= j;
        					k -= j;
        
        					mode = COPY;
        					/* falls through */
        				case COPY: // o: copying bytes in window, waiting for space
        					f = q - dist;
        					while (f < 0) { // modulo window size-"while" instead
        						f += s.end; // of "if" handles invalid distances
        					}
        					while (len !== 0) {
        
        						if (m === 0) {
        							if (q == s.end && s.read !== 0) {
        								q = 0;
        								m = q < s.read ? s.read - q - 1 : s.end - q;
        							}
        							if (m === 0) {
        								s.write = q;
        								r = s.inflate_flush(z, r);
        								q = s.write;
        								m = q < s.read ? s.read - q - 1 : s.end - q;
        
        								if (q == s.end && s.read !== 0) {
        									q = 0;
        									m = q < s.read ? s.read - q - 1 : s.end - q;
        								}
        
        								if (m === 0) {
        									s.bitb = b;
        									s.bitk = k;
        									z.avail_in = n;
        									z.total_in += p - z.next_in_index;
        									z.next_in_index = p;
        									s.write = q;
        									return s.inflate_flush(z, r);
        								}
        							}
        						}
        
        						s.window[q++] = s.window[f++];
        						m--;
        
        						if (f == s.end)
        							f = 0;
        						len--;
        					}
        					mode = START;
        					break;
        				case LIT: // o: got literal, waiting for output space
        					if (m === 0) {
        						if (q == s.end && s.read !== 0) {
        							q = 0;
        							m = q < s.read ? s.read - q - 1 : s.end - q;
        						}
        						if (m === 0) {
        							s.write = q;
        							r = s.inflate_flush(z, r);
        							q = s.write;
        							m = q < s.read ? s.read - q - 1 : s.end - q;
        
        							if (q == s.end && s.read !== 0) {
        								q = 0;
        								m = q < s.read ? s.read - q - 1 : s.end - q;
        							}
        							if (m === 0) {
        								s.bitb = b;
        								s.bitk = k;
        								z.avail_in = n;
        								z.total_in += p - z.next_in_index;
        								z.next_in_index = p;
        								s.write = q;
        								return s.inflate_flush(z, r);
        							}
        						}
        					}
        					r = Z_OK;
        
        					s.window[q++] = /* (byte) */lit;
        					m--;
        
        					mode = START;
        					break;
        				case WASH: // o: got eob, possibly more output
        					if (k > 7) { // return unused byte, if any
        						k -= 8;
        						n++;
        						p--; // can always return one
        					}
        
        					s.write = q;
        					r = s.inflate_flush(z, r);
        					q = s.write;
        					m = q < s.read ? s.read - q - 1 : s.end - q;
        
        					if (s.read != s.write) {
        						s.bitb = b;
        						s.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						s.write = q;
        						return s.inflate_flush(z, r);
        					}
        					mode = END;
        					/* falls through */
        				case END:
        					r = Z_STREAM_END;
        					s.bitb = b;
        					s.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					s.write = q;
        					return s.inflate_flush(z, r);
        
        				case BADCODE: // x: got error
        
        					r = Z_DATA_ERROR;
        
        					s.bitb = b;
        					s.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					s.write = q;
        					return s.inflate_flush(z, r);
        
        				default:
        					r = Z_STREAM_ERROR;
        
        					s.bitb = b;
        					s.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					s.write = q;
        					return s.inflate_flush(z, r);
        				}
        			}
        		};
        
        		that.free = function() {
        			// ZFREE(z, c);
        		};
        
        	}
        
        	// InfBlocks
        
        	// Table for deflate from PKZIP's appnote.txt.
        	var border = [ // Order of the bit length code lengths
        	16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
        
        	var TYPE = 0; // get type bits (3, including end bit)
        	var LENS = 1; // get lengths for stored
        	var STORED = 2;// processing stored block
        	var TABLE = 3; // get table lengths
        	var BTREE = 4; // get bit lengths tree for a dynamic
        	// block
        	var DTREE = 5; // get length, distance trees for a
        	// dynamic block
        	var CODES = 6; // processing fixed or dynamic block
        	var DRY = 7; // output remaining window bytes
        	var DONELOCKS = 8; // finished last block, done
        	var BADBLOCKS = 9; // ot a data error--stuck here
        
        	function InfBlocks(z, w) {
        		var that = this;
        
        		var mode = TYPE; // current inflate_block mode
        
        		var left = 0; // if STORED, bytes left to copy
        
        		var table = 0; // table lengths (14 bits)
        		var index = 0; // index into blens (or border)
        		var blens; // bit lengths of codes
        		var bb = [ 0 ]; // bit length tree depth
        		var tb = [ 0 ]; // bit length decoding tree
        
        		var codes = new InfCodes(); // if CODES, current state
        
        		var last = 0; // true if this block is the last block
        
        		var hufts = new Int32Array(MANY * 3); // single malloc for tree space
        		var check = 0; // check on output
        		var inftree = new InfTree();
        
        		that.bitk = 0; // bits in bit buffer
        		that.bitb = 0; // bit buffer
        		that.window = new Uint8Array(w); // sliding window
        		that.end = w; // one byte after sliding window
        		that.read = 0; // window read pointer
        		that.write = 0; // window write pointer
        
        		that.reset = function(z, c) {
        			if (c)
        				c[0] = check;
        			// if (mode == BTREE || mode == DTREE) {
        			// }
        			if (mode == CODES) {
        				codes.free(z);
        			}
        			mode = TYPE;
        			that.bitk = 0;
        			that.bitb = 0;
        			that.read = that.write = 0;
        		};
        
        		that.reset(z, null);
        
        		// copy as much as possible from the sliding window to the output area
        		that.inflate_flush = function(z, r) {
        			var n;
        			var p;
        			var q;
        
        			// local copies of source and destination pointers
        			p = z.next_out_index;
        			q = that.read;
        
        			// compute number of bytes to copy as far as end of window
        			n = /* (int) */((q <= that.write ? that.write : that.end) - q);
        			if (n > z.avail_out)
        				n = z.avail_out;
        			if (n !== 0 && r == Z_BUF_ERROR)
        				r = Z_OK;
        
        			// update counters
        			z.avail_out -= n;
        			z.total_out += n;
        
        			// copy as far as end of window
        			z.next_out.set(that.window.subarray(q, q + n), p);
        			p += n;
        			q += n;
        
        			// see if more to copy at beginning of window
        			if (q == that.end) {
        				// wrap pointers
        				q = 0;
        				if (that.write == that.end)
        					that.write = 0;
        
        				// compute bytes to copy
        				n = that.write - q;
        				if (n > z.avail_out)
        					n = z.avail_out;
        				if (n !== 0 && r == Z_BUF_ERROR)
        					r = Z_OK;
        
        				// update counters
        				z.avail_out -= n;
        				z.total_out += n;
        
        				// copy
        				z.next_out.set(that.window.subarray(q, q + n), p);
        				p += n;
        				q += n;
        			}
        
        			// update pointers
        			z.next_out_index = p;
        			that.read = q;
        
        			// done
        			return r;
        		};
        
        		that.proc = function(z, r) {
        			var t; // temporary storage
        			var b; // bit buffer
        			var k; // bits in bit buffer
        			var p; // input data pointer
        			var n; // bytes available there
        			var q; // output window write pointer
        			var m; // bytes to end of window or read pointer
        
        			var i;
        
        			// copy input/output information to locals (UPDATE macro restores)
        			// {
        			p = z.next_in_index;
        			n = z.avail_in;
        			b = that.bitb;
        			k = that.bitk;
        			// }
        			// {
        			q = that.write;
        			m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
        			// }
        
        			// process input based on current state
        			// DEBUG dtree
        			while (true) {
        				switch (mode) {
        				case TYPE:
        
        					while (k < (3)) {
        						if (n !== 0) {
        							r = Z_OK;
        						} else {
        							that.bitb = b;
        							that.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							that.write = q;
        							return that.inflate_flush(z, r);
        						}
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        					t = /* (int) */(b & 7);
        					last = t & 1;
        
        					switch (t >>> 1) {
        					case 0: // stored
        						// {
        						b >>>= (3);
        						k -= (3);
        						// }
        						t = k & 7; // go to byte boundary
        
        						// {
        						b >>>= (t);
        						k -= (t);
        						// }
        						mode = LENS; // get length of stored block
        						break;
        					case 1: // fixed
        						// {
        						var bl = []; // new Array(1);
        						var bd = []; // new Array(1);
        						var tl = [ [] ]; // new Array(1);
        						var td = [ [] ]; // new Array(1);
        
        						InfTree.inflate_trees_fixed(bl, bd, tl, td);
        						codes.init(bl[0], bd[0], tl[0], 0, td[0], 0);
        						// }
        
        						// {
        						b >>>= (3);
        						k -= (3);
        						// }
        
        						mode = CODES;
        						break;
        					case 2: // dynamic
        
        						// {
        						b >>>= (3);
        						k -= (3);
        						// }
        
        						mode = TABLE;
        						break;
        					case 3: // illegal
        
        						// {
        						b >>>= (3);
        						k -= (3);
        						// }
        						mode = BADBLOCKS;
        						z.msg = "invalid block type";
        						r = Z_DATA_ERROR;
        
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        					break;
        				case LENS:
        
        					while (k < (32)) {
        						if (n !== 0) {
        							r = Z_OK;
        						} else {
        							that.bitb = b;
        							that.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							that.write = q;
        							return that.inflate_flush(z, r);
        						}
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        
        					if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)) {
        						mode = BADBLOCKS;
        						z.msg = "invalid stored block lengths";
        						r = Z_DATA_ERROR;
        
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        					left = (b & 0xffff);
        					b = k = 0; // dump bits
        					mode = left !== 0 ? STORED : (last !== 0 ? DRY : TYPE);
        					break;
        				case STORED:
        					if (n === 0) {
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        
        					if (m === 0) {
        						if (q == that.end && that.read !== 0) {
        							q = 0;
        							m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
        						}
        						if (m === 0) {
        							that.write = q;
        							r = that.inflate_flush(z, r);
        							q = that.write;
        							m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
        							if (q == that.end && that.read !== 0) {
        								q = 0;
        								m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
        							}
        							if (m === 0) {
        								that.bitb = b;
        								that.bitk = k;
        								z.avail_in = n;
        								z.total_in += p - z.next_in_index;
        								z.next_in_index = p;
        								that.write = q;
        								return that.inflate_flush(z, r);
        							}
        						}
        					}
        					r = Z_OK;
        
        					t = left;
        					if (t > n)
        						t = n;
        					if (t > m)
        						t = m;
        					that.window.set(z.read_buf(p, t), q);
        					p += t;
        					n -= t;
        					q += t;
        					m -= t;
        					if ((left -= t) !== 0)
        						break;
        					mode = last !== 0 ? DRY : TYPE;
        					break;
        				case TABLE:
        
        					while (k < (14)) {
        						if (n !== 0) {
        							r = Z_OK;
        						} else {
        							that.bitb = b;
        							that.bitk = k;
        							z.avail_in = n;
        							z.total_in += p - z.next_in_index;
        							z.next_in_index = p;
        							that.write = q;
        							return that.inflate_flush(z, r);
        						}
        
        						n--;
        						b |= (z.read_byte(p++) & 0xff) << k;
        						k += 8;
        					}
        
        					table = t = (b & 0x3fff);
        					if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) {
        						mode = BADBLOCKS;
        						z.msg = "too many length or distance symbols";
        						r = Z_DATA_ERROR;
        
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        					t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
        					if (!blens || blens.length < t) {
        						blens = []; // new Array(t);
        					} else {
        						for (i = 0; i < t; i++) {
        							blens[i] = 0;
        						}
        					}
        
        					// {
        					b >>>= (14);
        					k -= (14);
        					// }
        
        					index = 0;
        					mode = BTREE;
        					/* falls through */
        				case BTREE:
        					while (index < 4 + (table >>> 10)) {
        						while (k < (3)) {
        							if (n !== 0) {
        								r = Z_OK;
        							} else {
        								that.bitb = b;
        								that.bitk = k;
        								z.avail_in = n;
        								z.total_in += p - z.next_in_index;
        								z.next_in_index = p;
        								that.write = q;
        								return that.inflate_flush(z, r);
        							}
        							n--;
        							b |= (z.read_byte(p++) & 0xff) << k;
        							k += 8;
        						}
        
        						blens[border[index++]] = b & 7;
        
        						// {
        						b >>>= (3);
        						k -= (3);
        						// }
        					}
        
        					while (index < 19) {
        						blens[border[index++]] = 0;
        					}
        
        					bb[0] = 7;
        					t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);
        					if (t != Z_OK) {
        						r = t;
        						if (r == Z_DATA_ERROR) {
        							blens = null;
        							mode = BADBLOCKS;
        						}
        
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        
        					index = 0;
        					mode = DTREE;
        					/* falls through */
        				case DTREE:
        					while (true) {
        						t = table;
        						if (index >= 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) {
        							break;
        						}
        
        						var j, c;
        
        						t = bb[0];
        
        						while (k < (t)) {
        							if (n !== 0) {
        								r = Z_OK;
        							} else {
        								that.bitb = b;
        								that.bitk = k;
        								z.avail_in = n;
        								z.total_in += p - z.next_in_index;
        								z.next_in_index = p;
        								that.write = q;
        								return that.inflate_flush(z, r);
        							}
        							n--;
        							b |= (z.read_byte(p++) & 0xff) << k;
        							k += 8;
        						}
        
        						// if (tb[0] == -1) {
        						// System.err.println("null...");
        						// }
        
        						t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
        						c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
        
        						if (c < 16) {
        							b >>>= (t);
        							k -= (t);
        							blens[index++] = c;
        						} else { // c == 16..18
        							i = c == 18 ? 7 : c - 14;
        							j = c == 18 ? 11 : 3;
        
        							while (k < (t + i)) {
        								if (n !== 0) {
        									r = Z_OK;
        								} else {
        									that.bitb = b;
        									that.bitk = k;
        									z.avail_in = n;
        									z.total_in += p - z.next_in_index;
        									z.next_in_index = p;
        									that.write = q;
        									return that.inflate_flush(z, r);
        								}
        								n--;
        								b |= (z.read_byte(p++) & 0xff) << k;
        								k += 8;
        							}
        
        							b >>>= (t);
        							k -= (t);
        
        							j += (b & inflate_mask[i]);
        
        							b >>>= (i);
        							k -= (i);
        
        							i = index;
        							t = table;
        							if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1)) {
        								blens = null;
        								mode = BADBLOCKS;
        								z.msg = "invalid bit length repeat";
        								r = Z_DATA_ERROR;
        
        								that.bitb = b;
        								that.bitk = k;
        								z.avail_in = n;
        								z.total_in += p - z.next_in_index;
        								z.next_in_index = p;
        								that.write = q;
        								return that.inflate_flush(z, r);
        							}
        
        							c = c == 16 ? blens[i - 1] : 0;
        							do {
        								blens[i++] = c;
        							} while (--j !== 0);
        							index = i;
        						}
        					}
        
        					tb[0] = -1;
        					// {
        					var bl_ = []; // new Array(1);
        					var bd_ = []; // new Array(1);
        					var tl_ = []; // new Array(1);
        					var td_ = []; // new Array(1);
        					bl_[0] = 9; // must be <= 9 for lookahead assumptions
        					bd_[0] = 6; // must be <= 9 for lookahead assumptions
        
        					t = table;
        					t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl_, bd_, tl_, td_, hufts, z);
        
        					if (t != Z_OK) {
        						if (t == Z_DATA_ERROR) {
        							blens = null;
        							mode = BADBLOCKS;
        						}
        						r = t;
        
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        					codes.init(bl_[0], bd_[0], hufts, tl_[0], hufts, td_[0]);
        					// }
        					mode = CODES;
        					/* falls through */
        				case CODES:
        					that.bitb = b;
        					that.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					that.write = q;
        
        					if ((r = codes.proc(that, z, r)) != Z_STREAM_END) {
        						return that.inflate_flush(z, r);
        					}
        					r = Z_OK;
        					codes.free(z);
        
        					p = z.next_in_index;
        					n = z.avail_in;
        					b = that.bitb;
        					k = that.bitk;
        					q = that.write;
        					m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
        
        					if (last === 0) {
        						mode = TYPE;
        						break;
        					}
        					mode = DRY;
        					/* falls through */
        				case DRY:
        					that.write = q;
        					r = that.inflate_flush(z, r);
        					q = that.write;
        					m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
        					if (that.read != that.write) {
        						that.bitb = b;
        						that.bitk = k;
        						z.avail_in = n;
        						z.total_in += p - z.next_in_index;
        						z.next_in_index = p;
        						that.write = q;
        						return that.inflate_flush(z, r);
        					}
        					mode = DONELOCKS;
        					/* falls through */
        				case DONELOCKS:
        					r = Z_STREAM_END;
        
        					that.bitb = b;
        					that.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					that.write = q;
        					return that.inflate_flush(z, r);
        				case BADBLOCKS:
        					r = Z_DATA_ERROR;
        
        					that.bitb = b;
        					that.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					that.write = q;
        					return that.inflate_flush(z, r);
        
        				default:
        					r = Z_STREAM_ERROR;
        
        					that.bitb = b;
        					that.bitk = k;
        					z.avail_in = n;
        					z.total_in += p - z.next_in_index;
        					z.next_in_index = p;
        					that.write = q;
        					return that.inflate_flush(z, r);
        				}
        			}
        		};
        
        		that.free = function(z) {
        			that.reset(z, null);
        			that.window = null;
        			hufts = null;
        			// ZFREE(z, s);
        		};
        
        		that.set_dictionary = function(d, start, n) {
        			that.window.set(d.subarray(start, start + n), 0);
        			that.read = that.write = n;
        		};
        
        		// Returns true if inflate is currently at the end of a block generated
        		// by Z_SYNC_FLUSH or Z_FULL_FLUSH.
        		that.sync_point = function() {
        			return mode == LENS ? 1 : 0;
        		};
        
        	}
        
        	// Inflate
        
        	// preset dictionary flag in zlib header
        	var PRESET_DICT = 0x20;
        
        	var Z_DEFLATED = 8;
        
        	var METHOD = 0; // waiting for method byte
        	var FLAG = 1; // waiting for flag byte
        	var DICT4 = 2; // four dictionary check bytes to go
        	var DICT3 = 3; // three dictionary check bytes to go
        	var DICT2 = 4; // two dictionary check bytes to go
        	var DICT1 = 5; // one dictionary check byte to go
        	var DICT0 = 6; // waiting for inflateSetDictionary
        	var BLOCKS = 7; // decompressing blocks
        	var DONE = 12; // finished check, done
        	var BAD = 13; // got an error--stay here
        
        	var mark = [ 0, 0, 0xff, 0xff ];
        
        	function Inflate() {
        		var that = this;
        
        		that.mode = 0; // current inflate mode
        
        		// mode dependent information
        		that.method = 0; // if FLAGS, method byte
        
        		// if CHECK, check values to compare
        		that.was = [ 0 ]; // new Array(1); // computed check value
        		that.need = 0; // stream check value
        
        		// if BAD, inflateSync's marker bytes count
        		that.marker = 0;
        
        		// mode independent information
        		that.wbits = 0; // log2(window size) (8..15, defaults to 15)
        
        		// this.blocks; // current inflate_blocks state
        
        		function inflateReset(z) {
        			if (!z || !z.istate)
        				return Z_STREAM_ERROR;
        
        			z.total_in = z.total_out = 0;
        			z.msg = null;
        			z.istate.mode = BLOCKS;
        			z.istate.blocks.reset(z, null);
        			return Z_OK;
        		}
        
        		that.inflateEnd = function(z) {
        			if (that.blocks)
        				that.blocks.free(z);
        			that.blocks = null;
        			// ZFREE(z, z->state);
        			return Z_OK;
        		};
        
        		that.inflateInit = function(z, w) {
        			z.msg = null;
        			that.blocks = null;
        
        			// set window size
        			if (w < 8 || w > 15) {
        				that.inflateEnd(z);
        				return Z_STREAM_ERROR;
        			}
        			that.wbits = w;
        
        			z.istate.blocks = new InfBlocks(z, 1 << w);
        
        			// reset state
        			inflateReset(z);
        			return Z_OK;
        		};
        
        		that.inflate = function(z, f) {
        			var r;
        			var b;
        
        			if (!z || !z.istate || !z.next_in)
        				return Z_STREAM_ERROR;
        			f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
        			r = Z_BUF_ERROR;
        			while (true) {
        				// System.out.println("mode: "+z.istate.mode);
        				switch (z.istate.mode) {
        				case METHOD:
        
        					if (z.avail_in === 0)
        						return r;
        					r = f;
        
        					z.avail_in--;
        					z.total_in++;
        					if (((z.istate.method = z.read_byte(z.next_in_index++)) & 0xf) != Z_DEFLATED) {
        						z.istate.mode = BAD;
        						z.msg = "unknown compression method";
        						z.istate.marker = 5; // can't try inflateSync
        						break;
        					}
        					if ((z.istate.method >> 4) + 8 > z.istate.wbits) {
        						z.istate.mode = BAD;
        						z.msg = "invalid window size";
        						z.istate.marker = 5; // can't try inflateSync
        						break;
        					}
        					z.istate.mode = FLAG;
        					/* falls through */
        				case FLAG:
        
        					if (z.avail_in === 0)
        						return r;
        					r = f;
        
        					z.avail_in--;
        					z.total_in++;
        					b = (z.read_byte(z.next_in_index++)) & 0xff;
        
        					if ((((z.istate.method << 8) + b) % 31) !== 0) {
        						z.istate.mode = BAD;
        						z.msg = "incorrect header check";
        						z.istate.marker = 5; // can't try inflateSync
        						break;
        					}
        
        					if ((b & PRESET_DICT) === 0) {
        						z.istate.mode = BLOCKS;
        						break;
        					}
        					z.istate.mode = DICT4;
        					/* falls through */
        				case DICT4:
        
        					if (z.avail_in === 0)
        						return r;
        					r = f;
        
        					z.avail_in--;
        					z.total_in++;
        					z.istate.need = ((z.read_byte(z.next_in_index++) & 0xff) << 24) & 0xff000000;
        					z.istate.mode = DICT3;
        					/* falls through */
        				case DICT3:
        
        					if (z.avail_in === 0)
        						return r;
        					r = f;
        
        					z.avail_in--;
        					z.total_in++;
        					z.istate.need += ((z.read_byte(z.next_in_index++) & 0xff) << 16) & 0xff0000;
        					z.istate.mode = DICT2;
        					/* falls through */
        				case DICT2:
        
        					if (z.avail_in === 0)
        						return r;
        					r = f;
        
        					z.avail_in--;
        					z.total_in++;
        					z.istate.need += ((z.read_byte(z.next_in_index++) & 0xff) << 8) & 0xff00;
        					z.istate.mode = DICT1;
        					/* falls through */
        				case DICT1:
        
        					if (z.avail_in === 0)
        						return r;
        					r = f;
        
        					z.avail_in--;
        					z.total_in++;
        					z.istate.need += (z.read_byte(z.next_in_index++) & 0xff);
        					z.istate.mode = DICT0;
        					return Z_NEED_DICT;
        				case DICT0:
        					z.istate.mode = BAD;
        					z.msg = "need dictionary";
        					z.istate.marker = 0; // can try inflateSync
        					return Z_STREAM_ERROR;
        				case BLOCKS:
        
        					r = z.istate.blocks.proc(z, r);
        					if (r == Z_DATA_ERROR) {
        						z.istate.mode = BAD;
        						z.istate.marker = 0; // can try inflateSync
        						break;
        					}
        					if (r == Z_OK) {
        						r = f;
        					}
        					if (r != Z_STREAM_END) {
        						return r;
        					}
        					r = f;
        					z.istate.blocks.reset(z, z.istate.was);
        					z.istate.mode = DONE;
        					/* falls through */
        				case DONE:
        					return Z_STREAM_END;
        				case BAD:
        					return Z_DATA_ERROR;
        				default:
        					return Z_STREAM_ERROR;
        				}
        			}
        		};
        
        		that.inflateSetDictionary = function(z, dictionary, dictLength) {
        			var index = 0;
        			var length = dictLength;
        			if (!z || !z.istate || z.istate.mode != DICT0)
        				return Z_STREAM_ERROR;
        
        			if (length >= (1 << z.istate.wbits)) {
        				length = (1 << z.istate.wbits) - 1;
        				index = dictLength - length;
        			}
        			z.istate.blocks.set_dictionary(dictionary, index, length);
        			z.istate.mode = BLOCKS;
        			return Z_OK;
        		};
        
        		that.inflateSync = function(z) {
        			var n; // number of bytes to look at
        			var p; // pointer to bytes
        			var m; // number of marker bytes found in a row
        			var r, w; // temporaries to save total_in and total_out
        
        			// set up
        			if (!z || !z.istate)
        				return Z_STREAM_ERROR;
        			if (z.istate.mode != BAD) {
        				z.istate.mode = BAD;
        				z.istate.marker = 0;
        			}
        			if ((n = z.avail_in) === 0)
        				return Z_BUF_ERROR;
        			p = z.next_in_index;
        			m = z.istate.marker;
        
        			// search
        			while (n !== 0 && m < 4) {
        				if (z.read_byte(p) == mark[m]) {
        					m++;
        				} else if (z.read_byte(p) !== 0) {
        					m = 0;
        				} else {
        					m = 4 - m;
        				}
        				p++;
        				n--;
        			}
        
        			// restore
        			z.total_in += p - z.next_in_index;
        			z.next_in_index = p;
        			z.avail_in = n;
        			z.istate.marker = m;
        
        			// return no joy or set up to restart on a new block
        			if (m != 4) {
        				return Z_DATA_ERROR;
        			}
        			r = z.total_in;
        			w = z.total_out;
        			inflateReset(z);
        			z.total_in = r;
        			z.total_out = w;
        			z.istate.mode = BLOCKS;
        			return Z_OK;
        		};
        
        		// Returns true if inflate is currently at the end of a block generated
        		// by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
        		// implementation to provide an additional safety check. PPP uses
        		// Z_SYNC_FLUSH
        		// but removes the length bytes of the resulting empty stored block. When
        		// decompressing, PPP checks that at the end of input packet, inflate is
        		// waiting for these length bytes.
        		that.inflateSyncPoint = function(z) {
        			if (!z || !z.istate || !z.istate.blocks)
        				return Z_STREAM_ERROR;
        			return z.istate.blocks.sync_point();
        		};
        	}
        
        	// ZStream
        
        	function ZStream() {
        	}
        
        	ZStream.prototype = {
        		inflateInit : function(bits) {
        			var that = this;
        			that.istate = new Inflate();
        			if (!bits)
        				bits = MAX_BITS;
        			return that.istate.inflateInit(that, bits);
        		},
        
        		inflate : function(f) {
        			var that = this;
        			if (!that.istate)
        				return Z_STREAM_ERROR;
        			return that.istate.inflate(that, f);
        		},
        
        		inflateEnd : function() {
        			var that = this;
        			if (!that.istate)
        				return Z_STREAM_ERROR;
        			var ret = that.istate.inflateEnd(that);
        			that.istate = null;
        			return ret;
        		},
        
        		inflateSync : function() {
        			var that = this;
        			if (!that.istate)
        				return Z_STREAM_ERROR;
        			return that.istate.inflateSync(that);
        		},
        		inflateSetDictionary : function(dictionary, dictLength) {
        			var that = this;
        			if (!that.istate)
        				return Z_STREAM_ERROR;
        			return that.istate.inflateSetDictionary(that, dictionary, dictLength);
        		},
        		read_byte : function(start) {
        			var that = this;
        			return that.next_in.subarray(start, start + 1)[0];
        		},
        		read_buf : function(start, size) {
        			var that = this;
        			return that.next_in.subarray(start, start + size);
        		}
        	};
        
        	// Inflater
        
        	function Inflater() {
        		var that = this;
        		var z = new ZStream();
        		var bufsize = 512;
        		var flush = Z_NO_FLUSH;
        		var buf = new Uint8Array(bufsize);
        		var nomoreinput = false;
        
        		z.inflateInit();
        		z.next_out = buf;
        
        		that.append = function(data, onprogress) {
        			var err, buffers = [], lastIndex = 0, bufferIndex = 0, bufferSize = 0, array;
        			if (data.length === 0)
        				return;
        			z.next_in_index = 0;
        			z.next_in = data;
        			z.avail_in = data.length;
        			do {
        				z.next_out_index = 0;
        				z.avail_out = bufsize;
        				if ((z.avail_in === 0) && (!nomoreinput)) { // if buffer is empty and more input is available, refill it
        					z.next_in_index = 0;
        					nomoreinput = true;
        				}
        				err = z.inflate(flush);
        				if (nomoreinput && (err === Z_BUF_ERROR)) {
        					if (z.avail_in !== 0)
        						throw new Error("inflating: bad input");
        				} else if (err !== Z_OK && err !== Z_STREAM_END)
        					throw new Error("inflating: " + z.msg);
        				if ((nomoreinput || err === Z_STREAM_END) && (z.avail_in === data.length))
        					throw new Error("inflating: bad input");
        				if (z.next_out_index)
        					if (z.next_out_index === bufsize)
        						buffers.push(new Uint8Array(buf));
        					else
        						buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
        				bufferSize += z.next_out_index;
        				if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
        					onprogress(z.next_in_index);
        					lastIndex = z.next_in_index;
        				}
        			} while (z.avail_in > 0 || z.avail_out === 0);
        			array = new Uint8Array(bufferSize);
        			buffers.forEach(function(chunk) {
        				array.set(chunk, bufferIndex);
        				bufferIndex += chunk.length;
        			});
        			return array;
        		};
        		that.flush = function() {
        			z.inflateEnd();
        		};
        	}
        
        	// 'zip' may not be defined in z-worker and some tests
        	var env = global.zip || global;
        	env.Inflater = env._jzlib_Inflater = Inflater;
        })(this);
      • zip.js
        /*
         Copyright (c) 2013 Gildas Lormeau. All rights reserved.
        
         Redistribution and use in source and binary forms, with or without
         modification, are permitted provided that the following conditions are met:
        
         1. Redistributions of source code must retain the above copyright notice,
         this list of conditions and the following disclaimer.
        
         2. Redistributions in binary form must reproduce the above copyright
         notice, this list of conditions and the following disclaimer in
         the documentation and/or other materials provided with the distribution.
        
         3. The names of the authors may not be used to endorse or promote products
         derived from this software without specific prior written permission.
        
         THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
         INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
         FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
         INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
         INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
         LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
         OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
         LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
         NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
         EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         */
        
        (function(obj) {
        	"use strict";
        
        	var ERR_BAD_FORMAT = "File format is not recognized.";
        	var ERR_CRC = "CRC failed.";
        	var ERR_ENCRYPTED = "File contains encrypted entry.";
        	var ERR_ZIP64 = "File is using Zip64 (4gb+ file size).";
        	var ERR_READ = "Error while reading zip file.";
        	var ERR_WRITE = "Error while writing zip file.";
        	var ERR_WRITE_DATA = "Error while writing file data.";
        	var ERR_READ_DATA = "Error while reading file data.";
        	var ERR_DUPLICATED_NAME = "File already exists.";
        	var CHUNK_SIZE = 512 * 1024;
        	
        	var TEXT_PLAIN = "text/plain";
        
        	var appendABViewSupported;
        	try {
        		appendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0;
        	} catch (e) {
        	}
        
        	function Crc32() {
        		this.crc = -1;
        	}
        	Crc32.prototype.append = function append(data) {
        		var crc = this.crc | 0, table = this.table;
        		for (var offset = 0, len = data.length | 0; offset < len; offset++)
        			crc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xFF];
        		this.crc = crc;
        	};
        	Crc32.prototype.get = function get() {
        		return ~this.crc;
        	};
        	Crc32.prototype.table = (function() {
        		var i, j, t, table = []; // Uint32Array is actually slower than []
        		for (i = 0; i < 256; i++) {
        			t = i;
        			for (j = 0; j < 8; j++)
        				if (t & 1)
        					t = (t >>> 1) ^ 0xEDB88320;
        				else
        					t = t >>> 1;
        			table[i] = t;
        		}
        		return table;
        	})();
        	
        	// "no-op" codec
        	function NOOP() {}
        	NOOP.prototype.append = function append(bytes, onprogress) {
        		return bytes;
        	};
        	NOOP.prototype.flush = function flush() {};
        
        	function blobSlice(blob, index, length) {
        		if (index < 0 || length < 0 || index + length > blob.size)
        			throw new RangeError('offset:' + index + ', length:' + length + ', size:' + blob.size);
        		if (blob.slice)
        			return blob.slice(index, index + length);
        		else if (blob.webkitSlice)
        			return blob.webkitSlice(index, index + length);
        		else if (blob.mozSlice)
        			return blob.mozSlice(index, index + length);
        		else if (blob.msSlice)
        			return blob.msSlice(index, index + length);
        	}
        
        	function getDataHelper(byteLength, bytes) {
        		var dataBuffer, dataArray;
        		dataBuffer = new ArrayBuffer(byteLength);
        		dataArray = new Uint8Array(dataBuffer);
        		if (bytes)
        			dataArray.set(bytes, 0);
        		return {
        			buffer : dataBuffer,
        			array : dataArray,
        			view : new DataView(dataBuffer)
        		};
        	}
        
        	// Readers
        	function Reader() {
        	}
        
        	function TextReader(text) {
        		var that = this, blobReader;
        
        		function init(callback, onerror) {
        			var blob = new Blob([ text ], {
        				type : TEXT_PLAIN
        			});
        			blobReader = new BlobReader(blob);
        			blobReader.init(function() {
        				that.size = blobReader.size;
        				callback();
        			}, onerror);
        		}
        
        		function readUint8Array(index, length, callback, onerror) {
        			blobReader.readUint8Array(index, length, callback, onerror);
        		}
        
        		that.size = 0;
        		that.init = init;
        		that.readUint8Array = readUint8Array;
        	}
        	TextReader.prototype = new Reader();
        	TextReader.prototype.constructor = TextReader;
        
        	function Data64URIReader(dataURI) {
        		var that = this, dataStart;
        
        		function init(callback) {
        			var dataEnd = dataURI.length;
        			while (dataURI.charAt(dataEnd - 1) == "=")
        				dataEnd--;
        			dataStart = dataURI.indexOf(",") + 1;
        			that.size = Math.floor((dataEnd - dataStart) * 0.75);
        			callback();
        		}
        
        		function readUint8Array(index, length, callback) {
        			var i, data = getDataHelper(length);
        			var start = Math.floor(index / 3) * 4;
        			var end = Math.ceil((index + length) / 3) * 4;
        			var bytes = obj.atob(dataURI.substring(start + dataStart, end + dataStart));
        			var delta = index - Math.floor(start / 4) * 3;
        			for (i = delta; i < delta + length; i++)
        				data.array[i - delta] = bytes.charCodeAt(i);
        			callback(data.array);
        		}
        
        		that.size = 0;
        		that.init = init;
        		that.readUint8Array = readUint8Array;
        	}
        	Data64URIReader.prototype = new Reader();
        	Data64URIReader.prototype.constructor = Data64URIReader;
        
        	function BlobReader(blob) {
        		var that = this;
        
        		function init(callback) {
        			that.size = blob.size;
        			callback();
        		}
        
        		function readUint8Array(index, length, callback, onerror) {
        			var reader = new FileReader();
        			reader.onload = function(e) {
        				callback(new Uint8Array(e.target.result));
        			};
        			reader.onerror = onerror;
        			try {
        				reader.readAsArrayBuffer(blobSlice(blob, index, length));
        			} catch (e) {
        				onerror(e);
        			}
        		}
        
        		that.size = 0;
        		that.init = init;
        		that.readUint8Array = readUint8Array;
        	}
        	BlobReader.prototype = new Reader();
        	BlobReader.prototype.constructor = BlobReader;
        
        	// Writers
        
        	function Writer() {
        	}
        	Writer.prototype.getData = function(callback) {
        		callback(this.data);
        	};
        
        	function TextWriter(encoding) {
        		var that = this, blob;
        
        		function init(callback) {
        			blob = new Blob([], {
        				type : TEXT_PLAIN
        			});
        			callback();
        		}
        
        		function writeUint8Array(array, callback) {
        			blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
        				type : TEXT_PLAIN
        			});
        			callback();
        		}
        
        		function getData(callback, onerror) {
        			var reader = new FileReader();
        			reader.onload = function(e) {
        				callback(e.target.result);
        			};
        			reader.onerror = onerror;
        			reader.readAsText(blob, encoding);
        		}
        
        		that.init = init;
        		that.writeUint8Array = writeUint8Array;
        		that.getData = getData;
        	}
        	TextWriter.prototype = new Writer();
        	TextWriter.prototype.constructor = TextWriter;
        
        	function Data64URIWriter(contentType) {
        		var that = this, data = "", pending = "";
        
        		function init(callback) {
        			data += "data:" + (contentType || "") + ";base64,";
        			callback();
        		}
        
        		function writeUint8Array(array, callback) {
        			var i, delta = pending.length, dataString = pending;
        			pending = "";
        			for (i = 0; i < (Math.floor((delta + array.length) / 3) * 3) - delta; i++)
        				dataString += String.fromCharCode(array[i]);
        			for (; i < array.length; i++)
        				pending += String.fromCharCode(array[i]);
        			if (dataString.length > 2)
        				data += obj.btoa(dataString);
        			else
        				pending = dataString;
        			callback();
        		}
        
        		function getData(callback) {
        			callback(data + obj.btoa(pending));
        		}
        
        		that.init = init;
        		that.writeUint8Array = writeUint8Array;
        		that.getData = getData;
        	}
        	Data64URIWriter.prototype = new Writer();
        	Data64URIWriter.prototype.constructor = Data64URIWriter;
        
        	function BlobWriter(contentType) {
        		var blob, that = this;
        
        		function init(callback) {
        			blob = new Blob([], {
        				type : contentType
        			});
        			callback();
        		}
        
        		function writeUint8Array(array, callback) {
        			blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
        				type : contentType
        			});
        			callback();
        		}
        
        		function getData(callback) {
        			callback(blob);
        		}
        
        		that.init = init;
        		that.writeUint8Array = writeUint8Array;
        		that.getData = getData;
        	}
        	BlobWriter.prototype = new Writer();
        	BlobWriter.prototype.constructor = BlobWriter;
        
        	/** 
        	 * inflate/deflate core functions
        	 * @param worker {Worker} web worker for the task.
        	 * @param initialMessage {Object} initial message to be sent to the worker. should contain
        	 *   sn(serial number for distinguishing multiple tasks sent to the worker), and codecClass.
        	 *   This function may add more properties before sending.
        	 */
        	function launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror) {
        		var chunkIndex = 0, index, outputSize, sn = initialMessage.sn, crc;
        
        		function onflush() {
        			worker.removeEventListener('message', onmessage, false);
        			onend(outputSize, crc);
        		}
        
        		function onmessage(event) {
        			var message = event.data, data = message.data, err = message.error;
        			if (err) {
        				err.toString = function () { return 'Error: ' + this.message; };
        				onreaderror(err);
        				return;
        			}
        			if (message.sn !== sn)
        				return;
        			if (typeof message.codecTime === 'number')
        				worker.codecTime += message.codecTime; // should be before onflush()
        			if (typeof message.crcTime === 'number')
        				worker.crcTime += message.crcTime;
        
        			switch (message.type) {
        				case 'append':
        					if (data) {
        						outputSize += data.length;
        						writer.writeUint8Array(data, function() {
        							step();
        						}, onwriteerror);
        					} else
        						step();
        					break;
        				case 'flush':
        					crc = message.crc;
        					if (data) {
        						outputSize += data.length;
        						writer.writeUint8Array(data, function() {
        							onflush();
        						}, onwriteerror);
        					} else
        						onflush();
        					break;
        				case 'progress':
        					if (onprogress)
        						onprogress(index + message.loaded, size);
        					break;
        				case 'importScripts': //no need to handle here
        				case 'newTask':
        				case 'echo':
        					break;
        				default:
        					console.warn('zip.js:launchWorkerProcess: unknown message: ', message);
        			}
        		}
        
        		function step() {
        			index = chunkIndex * CHUNK_SIZE;
        			if (index < size) {
        				reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(array) {
        					if (onprogress)
        						onprogress(index, size);
        					var msg = index === 0 ? initialMessage : {sn : sn};
        					msg.type = 'append';
        					msg.data = array;
        					worker.postMessage(msg, [array.buffer]);
        					chunkIndex++;
        				}, onreaderror);
        			} else {
        				worker.postMessage({
        					sn: sn,
        					type: 'flush'
        				});
        			}
        		}
        
        		outputSize = 0;
        		worker.addEventListener('message', onmessage, false);
        		step();
        	}
        
        	function launchProcess(process, reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror) {
        		var chunkIndex = 0, index, outputSize = 0,
        			crcInput = crcType === 'input',
        			crcOutput = crcType === 'output',
        			crc = new Crc32();
        		function step() {
        			var outputData;
        			index = chunkIndex * CHUNK_SIZE;
        			if (index < size)
        				reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(inputData) {
        					var outputData;
        					try {
        						outputData = process.append(inputData, function(loaded) {
        							if (onprogress)
        								onprogress(index + loaded, size);
        						});
        					} catch (e) {
        						onreaderror(e);
        						return;
        					}
        					if (outputData) {
        						outputSize += outputData.length;
        						writer.writeUint8Array(outputData, function() {
        							chunkIndex++;
        							setTimeout(step, 1);
        						}, onwriteerror);
        						if (crcOutput)
        							crc.append(outputData);
        					} else {
        						chunkIndex++;
        						setTimeout(step, 1);
        					}
        					if (crcInput)
        						crc.append(inputData);
        					if (onprogress)
        						onprogress(index, size);
        				}, onreaderror);
        			else {
        				try {
        					outputData = process.flush();
        				} catch (e) {
        					onreaderror(e);
        					return;
        				}
        				if (outputData) {
        					if (crcOutput)
        						crc.append(outputData);
        					outputSize += outputData.length;
        					writer.writeUint8Array(outputData, function() {
        						onend(outputSize, crc.get());
        					}, onwriteerror);
        				} else
        					onend(outputSize, crc.get());
        			}
        		}
        
        		step();
        	}
        
        	function inflate(worker, sn, reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {
        		var crcType = computeCrc32 ? 'output' : 'none';
        		if (obj.zip.useWebWorkers) {
        			var initialMessage = {
        				sn: sn,
        				codecClass: 'Inflater',
        				crcType: crcType,
        			};
        			launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror);
        		} else
        			launchProcess(new obj.zip.Inflater(), reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror);
        	}
        
        	function deflate(worker, sn, reader, writer, level, onend, onprogress, onreaderror, onwriteerror) {
        		var crcType = 'input';
        		if (obj.zip.useWebWorkers) {
        			var initialMessage = {
        				sn: sn,
        				options: {level: level},
        				codecClass: 'Deflater',
        				crcType: crcType,
        			};
        			launchWorkerProcess(worker, initialMessage, reader, writer, 0, reader.size, onprogress, onend, onreaderror, onwriteerror);
        		} else
        			launchProcess(new obj.zip.Deflater(), reader, writer, 0, reader.size, crcType, onprogress, onend, onreaderror, onwriteerror);
        	}
        
        	function copy(worker, sn, reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {
        		var crcType = 'input';
        		if (obj.zip.useWebWorkers && computeCrc32) {
        			var initialMessage = {
        				sn: sn,
        				codecClass: 'NOOP',
        				crcType: crcType,
        			};
        			launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror);
        		} else
        			launchProcess(new NOOP(), reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror);
        	}
        
        	// ZipReader
        
        	function decodeASCII(str) {
        		var i, out = "", charCode, extendedASCII = [ '\u00C7', '\u00FC', '\u00E9', '\u00E2', '\u00E4', '\u00E0', '\u00E5', '\u00E7', '\u00EA', '\u00EB',
        				'\u00E8', '\u00EF', '\u00EE', '\u00EC', '\u00C4', '\u00C5', '\u00C9', '\u00E6', '\u00C6', '\u00F4', '\u00F6', '\u00F2', '\u00FB', '\u00F9',
        				'\u00FF', '\u00D6', '\u00DC', '\u00F8', '\u00A3', '\u00D8', '\u00D7', '\u0192', '\u00E1', '\u00ED', '\u00F3', '\u00FA', '\u00F1', '\u00D1',
        				'\u00AA', '\u00BA', '\u00BF', '\u00AE', '\u00AC', '\u00BD', '\u00BC', '\u00A1', '\u00AB', '\u00BB', '_', '_', '_', '\u00A6', '\u00A6',
        				'\u00C1', '\u00C2', '\u00C0', '\u00A9', '\u00A6', '\u00A6', '+', '+', '\u00A2', '\u00A5', '+', '+', '-', '-', '+', '-', '+', '\u00E3',
        				'\u00C3', '+', '+', '-', '-', '\u00A6', '-', '+', '\u00A4', '\u00F0', '\u00D0', '\u00CA', '\u00CB', '\u00C8', 'i', '\u00CD', '\u00CE',
        				'\u00CF', '+', '+', '_', '_', '\u00A6', '\u00CC', '_', '\u00D3', '\u00DF', '\u00D4', '\u00D2', '\u00F5', '\u00D5', '\u00B5', '\u00FE',
        				'\u00DE', '\u00DA', '\u00DB', '\u00D9', '\u00FD', '\u00DD', '\u00AF', '\u00B4', '\u00AD', '\u00B1', '_', '\u00BE', '\u00B6', '\u00A7',
        				'\u00F7', '\u00B8', '\u00B0', '\u00A8', '\u00B7', '\u00B9', '\u00B3', '\u00B2', '_', ' ' ];
        		for (i = 0; i < str.length; i++) {
        			charCode = str.charCodeAt(i) & 0xFF;
        			if (charCode > 127)
        				out += extendedASCII[charCode - 128];
        			else
        				out += String.fromCharCode(charCode);
        		}
        		return out;
        	}
        
        	function decodeUTF8(string) {
        		return decodeURIComponent(escape(string));
        	}
        
        	function getString(bytes) {
        		var i, str = "";
        		for (i = 0; i < bytes.length; i++)
        			str += String.fromCharCode(bytes[i]);
        		return str;
        	}
        
        	function getDate(timeRaw) {
        		var date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & 0x0000ffff;
        		try {
        			return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5,
        					(time & 0x001F) * 2, 0);
        		} catch (e) {
        		}
        	}
        
        	function readCommonHeader(entry, data, index, centralDirectory, onerror) {
        		entry.version = data.view.getUint16(index, true);
        		entry.bitFlag = data.view.getUint16(index + 2, true);
        		entry.compressionMethod = data.view.getUint16(index + 4, true);
        		entry.lastModDateRaw = data.view.getUint32(index + 6, true);
        		entry.lastModDate = getDate(entry.lastModDateRaw);
        		if ((entry.bitFlag & 0x01) === 0x01) {
        			onerror(ERR_ENCRYPTED);
        			return;
        		}
        		if (centralDirectory || (entry.bitFlag & 0x0008) != 0x0008) {
        			entry.crc32 = data.view.getUint32(index + 10, true);
        			entry.compressedSize = data.view.getUint32(index + 14, true);
        			entry.uncompressedSize = data.view.getUint32(index + 18, true);
        		}
        		if (entry.compressedSize === 0xFFFFFFFF || entry.uncompressedSize === 0xFFFFFFFF) {
        			onerror(ERR_ZIP64);
        			return;
        		}
        		entry.filenameLength = data.view.getUint16(index + 22, true);
        		entry.extraFieldLength = data.view.getUint16(index + 24, true);
        	}
        
        	function createZipReader(reader, callback, onerror) {
        		var inflateSN = 0;
        
        		function Entry() {
        		}
        
        		Entry.prototype.getData = function(writer, onend, onprogress, checkCrc32) {
        			var that = this;
        
        			function testCrc32(crc32) {
        				var dataCrc32 = getDataHelper(4);
        				dataCrc32.view.setUint32(0, crc32);
        				return that.crc32 == dataCrc32.view.getUint32(0);
        			}
        
        			function getWriterData(uncompressedSize, crc32) {
        				if (checkCrc32 && !testCrc32(crc32))
        					onerror(ERR_CRC);
        				else
        					writer.getData(function(data) {
        						onend(data);
        					});
        			}
        
        			function onreaderror(err) {
        				onerror(err || ERR_READ_DATA);
        			}
        
        			function onwriteerror(err) {
        				onerror(err || ERR_WRITE_DATA);
        			}
        
        			reader.readUint8Array(that.offset, 30, function(bytes) {
        				var data = getDataHelper(bytes.length, bytes), dataOffset;
        				if (data.view.getUint32(0) != 0x504b0304) {
        					onerror(ERR_BAD_FORMAT);
        					return;
        				}
        				readCommonHeader(that, data, 4, false, onerror);
        				dataOffset = that.offset + 30 + that.filenameLength + that.extraFieldLength;
        				writer.init(function() {
        					if (that.compressionMethod === 0)
        						copy(that._worker, inflateSN++, reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);
        					else
        						inflate(that._worker, inflateSN++, reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);
        				}, onwriteerror);
        			}, onreaderror);
        		};
        
        		function seekEOCDR(eocdrCallback) {
        			// "End of central directory record" is the last part of a zip archive, and is at least 22 bytes long.
        			// Zip file comment is the last part of EOCDR and has max length of 64KB,
        			// so we only have to search the last 64K + 22 bytes of a archive for EOCDR signature (0x06054b50).
        			var EOCDR_MIN = 22;
        			if (reader.size < EOCDR_MIN) {
        				onerror(ERR_BAD_FORMAT);
        				return;
        			}
        			var ZIP_COMMENT_MAX = 256 * 256, EOCDR_MAX = EOCDR_MIN + ZIP_COMMENT_MAX;
        
        			// In most cases, the EOCDR is EOCDR_MIN bytes long
        			doSeek(EOCDR_MIN, function() {
        				// If not found, try within EOCDR_MAX bytes
        				doSeek(Math.min(EOCDR_MAX, reader.size), function() {
        					onerror(ERR_BAD_FORMAT);
        				});
        			});
        
        			// seek last length bytes of file for EOCDR
        			function doSeek(length, eocdrNotFoundCallback) {
        				reader.readUint8Array(reader.size - length, length, function(bytes) {
        					for (var i = bytes.length - EOCDR_MIN; i >= 0; i--) {
        						if (bytes[i] === 0x50 && bytes[i + 1] === 0x4b && bytes[i + 2] === 0x05 && bytes[i + 3] === 0x06) {
        							eocdrCallback(new DataView(bytes.buffer, i, EOCDR_MIN));
        							return;
        						}
        					}
        					eocdrNotFoundCallback();
        				}, function() {
        					onerror(ERR_READ);
        				});
        			}
        		}
        
        		var zipReader = {
        			getEntries : function(callback) {
        				var worker = this._worker;
        				// look for End of central directory record
        				seekEOCDR(function(dataView) {
        					var datalength, fileslength;
        					datalength = dataView.getUint32(16, true);
        					fileslength = dataView.getUint16(8, true);
        					if (datalength < 0 || datalength >= reader.size) {
        						onerror(ERR_BAD_FORMAT);
        						return;
        					}
        					reader.readUint8Array(datalength, reader.size - datalength, function(bytes) {
        						var i, index = 0, entries = [], entry, filename, comment, data = getDataHelper(bytes.length, bytes);
        						for (i = 0; i < fileslength; i++) {
        							entry = new Entry();
        							entry._worker = worker;
        							if (data.view.getUint32(index) != 0x504b0102) {
        								onerror(ERR_BAD_FORMAT);
        								return;
        							}
        							readCommonHeader(entry, data, index + 6, true, onerror);
        							entry.commentLength = data.view.getUint16(index + 32, true);
        							entry.directory = ((data.view.getUint8(index + 38) & 0x10) == 0x10);
        							entry.offset = data.view.getUint32(index + 42, true);
        							filename = getString(data.array.subarray(index + 46, index + 46 + entry.filenameLength));
        							entry.filename = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(filename) : decodeASCII(filename);
        							if (!entry.directory && entry.filename.charAt(entry.filename.length - 1) == "/")
        								entry.directory = true;
        							comment = getString(data.array.subarray(index + 46 + entry.filenameLength + entry.extraFieldLength, index + 46
        									+ entry.filenameLength + entry.extraFieldLength + entry.commentLength));
        							entry.comment = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(comment) : decodeASCII(comment);
        							entries.push(entry);
        							index += 46 + entry.filenameLength + entry.extraFieldLength + entry.commentLength;
        						}
        						callback(entries);
        					}, function() {
        						onerror(ERR_READ);
        					});
        				});
        			},
        			close : function(callback) {
        				if (this._worker) {
        					this._worker.terminate();
        					this._worker = null;
        				}
        				if (callback)
        					callback();
        			},
        			_worker: null
        		};
        
        		if (!obj.zip.useWebWorkers)
        			callback(zipReader);
        		else {
        			createWorker('inflater',
        				function(worker) {
        					zipReader._worker = worker;
        					callback(zipReader);
        				},
        				function(err) {
        					onerror(err);
        				}
        			);
        		}
        	}
        
        	// ZipWriter
        
        	function encodeUTF8(string) {
        		return unescape(encodeURIComponent(string));
        	}
        
        	function getBytes(str) {
        		var i, array = [];
        		for (i = 0; i < str.length; i++)
        			array.push(str.charCodeAt(i));
        		return array;
        	}
        
        	function createZipWriter(writer, callback, onerror, dontDeflate) {
        		var files = {}, filenames = [], datalength = 0;
        		var deflateSN = 0;
        
        		function onwriteerror(err) {
        			onerror(err || ERR_WRITE);
        		}
        
        		function onreaderror(err) {
        			onerror(err || ERR_READ_DATA);
        		}
        
        		var zipWriter = {
        			add : function(name, reader, onend, onprogress, options) {
        				var header, filename, date;
        				var worker = this._worker;
        
        				function writeHeader(callback) {
        					var data;
        					date = options.lastModDate || new Date();
        					header = getDataHelper(26);
        					files[name] = {
        						headerArray : header.array,
        						directory : options.directory,
        						filename : filename,
        						offset : datalength,
        						comment : getBytes(encodeUTF8(options.comment || ""))
        					};
        					header.view.setUint32(0, 0x14000808);
        					if (options.version)
        						header.view.setUint8(0, options.version);
        					if (!dontDeflate && options.level !== 0 && !options.directory)
        						header.view.setUint16(4, 0x0800);
        					header.view.setUint16(6, (((date.getHours() << 6) | date.getMinutes()) << 5) | date.getSeconds() / 2, true);
        					header.view.setUint16(8, ((((date.getFullYear() - 1980) << 4) | (date.getMonth() + 1)) << 5) | date.getDate(), true);
        					header.view.setUint16(22, filename.length, true);
        					data = getDataHelper(30 + filename.length);
        					data.view.setUint32(0, 0x504b0304);
        					data.array.set(header.array, 4);
        					data.array.set(filename, 30);
        					datalength += data.array.length;
        					writer.writeUint8Array(data.array, callback, onwriteerror);
        				}
        
        				function writeFooter(compressedLength, crc32) {
        					var footer = getDataHelper(16);
        					datalength += compressedLength || 0;
        					footer.view.setUint32(0, 0x504b0708);
        					if (typeof crc32 != "undefined") {
        						header.view.setUint32(10, crc32, true);
        						footer.view.setUint32(4, crc32, true);
        					}
        					if (reader) {
        						footer.view.setUint32(8, compressedLength, true);
        						header.view.setUint32(14, compressedLength, true);
        						footer.view.setUint32(12, reader.size, true);
        						header.view.setUint32(18, reader.size, true);
        					}
        					writer.writeUint8Array(footer.array, function() {
        						datalength += 16;
        						onend();
        					}, onwriteerror);
        				}
        
        				function writeFile() {
        					options = options || {};
        					name = name.trim();
        					if (options.directory && name.charAt(name.length - 1) != "/")
        						name += "/";
        					if (files.hasOwnProperty(name)) {
        						onerror(ERR_DUPLICATED_NAME);
        						return;
        					}
        					filename = getBytes(encodeUTF8(name));
        					filenames.push(name);
        					writeHeader(function() {
        						if (reader)
        							if (dontDeflate || options.level === 0)
        								copy(worker, deflateSN++, reader, writer, 0, reader.size, true, writeFooter, onprogress, onreaderror, onwriteerror);
        							else
        								deflate(worker, deflateSN++, reader, writer, options.level, writeFooter, onprogress, onreaderror, onwriteerror);
        						else
        							writeFooter();
        					}, onwriteerror);
        				}
        
        				if (reader)
        					reader.init(writeFile, onreaderror);
        				else
        					writeFile();
        			},
        			close : function(callback) {
        				if (this._worker) {
        					this._worker.terminate();
        					this._worker = null;
        				}
        
        				var data, length = 0, index = 0, indexFilename, file;
        				for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
        					file = files[filenames[indexFilename]];
        					length += 46 + file.filename.length + file.comment.length;
        				}
        				data = getDataHelper(length + 22);
        				for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
        					file = files[filenames[indexFilename]];
        					data.view.setUint32(index, 0x504b0102);
        					data.view.setUint16(index + 4, 0x1400);
        					data.array.set(file.headerArray, index + 6);
        					data.view.setUint16(index + 32, file.comment.length, true);
        					if (file.directory)
        						data.view.setUint8(index + 38, 0x10);
        					data.view.setUint32(index + 42, file.offset, true);
        					data.array.set(file.filename, index + 46);
        					data.array.set(file.comment, index + 46 + file.filename.length);
        					index += 46 + file.filename.length + file.comment.length;
        				}
        				data.view.setUint32(index, 0x504b0506);
        				data.view.setUint16(index + 8, filenames.length, true);
        				data.view.setUint16(index + 10, filenames.length, true);
        				data.view.setUint32(index + 12, length, true);
        				data.view.setUint32(index + 16, datalength, true);
        				writer.writeUint8Array(data.array, function() {
        					writer.getData(callback);
        				}, onwriteerror);
        			},
        			_worker: null
        		};
        
        		if (!obj.zip.useWebWorkers)
        			callback(zipWriter);
        		else {
        			createWorker('deflater',
        				function(worker) {
        					zipWriter._worker = worker;
        					callback(zipWriter);
        				},
        				function(err) {
        					onerror(err);
        				}
        			);
        		}
        	}
        
        	function resolveURLs(urls) {
        		var a = document.createElement('a');
        		return urls.map(function(url) {
        			a.href = url;
        			return a.href;
        		});
        	}
        
        	var DEFAULT_WORKER_SCRIPTS = {
        		deflater: ['z-worker.js', 'deflate.js'],
        		inflater: ['z-worker.js', 'inflate.js']
        	};
        	function createWorker(type, callback, onerror) {
        		if (obj.zip.workerScripts !== null && obj.zip.workerScriptsPath !== null) {
        			onerror(new Error('Either zip.workerScripts or zip.workerScriptsPath may be set, not both.'));
        			return;
        		}
        		var scripts;
        		if (obj.zip.workerScripts) {
        			scripts = obj.zip.workerScripts[type];
        			if (!Array.isArray(scripts)) {
        				onerror(new Error('zip.workerScripts.' + type + ' is not an array!'));
        				return;
        			}
        			scripts = resolveURLs(scripts);
        		} else {
        			scripts = DEFAULT_WORKER_SCRIPTS[type].slice(0);
        			scripts[0] = (obj.zip.workerScriptsPath || '') + scripts[0];
        		}
        		var worker = new Worker(scripts[0]);
        		// record total consumed time by inflater/deflater/crc32 in this worker
        		worker.codecTime = worker.crcTime = 0;
        		worker.postMessage({ type: 'importScripts', scripts: scripts.slice(1) });
        		worker.addEventListener('message', onmessage);
        		function onmessage(ev) {
        			var msg = ev.data;
        			if (msg.error) {
        				worker.terminate(); // should before onerror(), because onerror() may throw.
        				onerror(msg.error);
        				return;
        			}
        			if (msg.type === 'importScripts') {
        				worker.removeEventListener('message', onmessage);
        				worker.removeEventListener('error', errorHandler);
        				callback(worker);
        			}
        		}
        		// catch entry script loading error and other unhandled errors
        		worker.addEventListener('error', errorHandler);
        		function errorHandler(err) {
        			worker.terminate();
        			onerror(err);
        		}
        	}
        
        	function onerror_default(error) {
        		console.error(error);
        	}
        	obj.zip = {
        		Reader : Reader,
        		Writer : Writer,
        		BlobReader : BlobReader,
        		Data64URIReader : Data64URIReader,
        		TextReader : TextReader,
        		BlobWriter : BlobWriter,
        		Data64URIWriter : Data64URIWriter,
        		TextWriter : TextWriter,
        		createReader : function(reader, callback, onerror) {
        			onerror = onerror || onerror_default;
        
        			reader.init(function() {
        				createZipReader(reader, callback, onerror);
        			}, onerror);
        		},
        		createWriter : function(writer, callback, onerror, dontDeflate) {
        			onerror = onerror || onerror_default;
        			dontDeflate = !!dontDeflate;
        
        			writer.init(function() {
        				createZipWriter(writer, callback, onerror, dontDeflate);
        			}, onerror);
        		},
        		useWebWorkers : true,
        		/**
        		 * Directory containing the default worker scripts (z-worker.js, deflate.js, and inflate.js), relative to current base url.
        		 * E.g.: zip.workerScripts = './';
        		 */
        		workerScriptsPath : null,
        		/**
        		 * Advanced option to control which scripts are loaded in the Web worker. If this option is specified, then workerScriptsPath must not be set.
        		 * workerScripts.deflater/workerScripts.inflater should be arrays of urls to scripts for deflater/inflater, respectively.
        		 * Scripts in the array are executed in order, and the first one should be z-worker.js, which is used to start the worker.
        		 * All urls are relative to current base url.
        		 * E.g.:
        		 * zip.workerScripts = {
        		 *   deflater: ['z-worker.js', 'deflate.js'],
        		 *   inflater: ['z-worker.js', 'inflate.js']
        		 * };
        		 */
        		workerScripts : null,
        	};
        
        })(this);
  • nodeAPI
    • modules
      • fs.ts
        module portabled.nodeAPI.modules.fs {
        
          export class fsModule {
        
            constructor(private _drive: persistence.Drive) {
            }
        
            rename: (oldPath: string, newPath: string, callback: (error: Error) => void) => void;
            renameSync(oldPath: string, newPath: string) {
              var content = this._drive.read(oldPath);
              if (content === null) throw new Error('File cannot be found.');
        
              this._drive.timestamp = dateNow();
              this._drive.write(newPath, content);
              this._drive.write(oldPath, null);
            }
        
          	ftruncate: (fd: any, len: number, callback: (error: Error) => void) => void;
          	ftruncateSync(fd: any, len: number) {
              var content = this._drive.read(fd);
              if (content === null) throw new Error('File cannot be found.');
        
              this._drive.timestamp = dateNow();
              this._drive.write(fd, content.slice(0, len));
            }
          }
        
        }
  • persistence
    • Drive.ts
      module portabled.persistence {
      
        export interface Drive {
      
          timestamp: number;
      
          files(): string[];
      
          read(file: string): string;
      
          write(file: string, content: string);
      
        }
      
        export module Drive {
      
          export interface Shadow {
      
            timestamp: number;
      
            write(file: string, content: string): void;
      
          }
      
          export interface Optional {
      
            detect(uniqueKey: string, callback: (detached: Detached) => void): void;
      
          }
      
          export interface Detached {
      
            timestamp: number;
      
            applyTo(mainDrive: Drive, callback: Detached.CallbackWithShadow): void;
      
            purge(callback: Detached.CallbackWithShadow): void;
      
          }
      
          export module Detached {
            export interface CallbackWithShadow {
      
              (loaded: Shadow): void;
              progress?: (current: number, total: number) => void;
      
            }
          }
      
        }
      
      }
    • indexedDB.ts
      module portabled {
      
        function getIndexedDB() {
          try {
          	return typeof indexedDB === 'undefined' || typeof indexedDB.open !== 'function' ? null : indexedDB;
          }
          catch (error) {
            return null;
          }
        }
      
        export module persistence.indexedDB {
      
          export function detect(uniqueKey: string, callback: (detached: Drive.Detached) => void): void {
            try {
              detectCore(uniqueKey, callback);
            }
            catch (error) {
              callback(null);
            }
          }
      
          function detectCore(uniqueKey: string, callback: (detached: Drive.Detached) => void): void {
      
            var indexedDBInstance = getIndexedDB();
            if (!indexedDBInstance) {
              callback(null);
              return;
            }
      
            var dbName = uniqueKey || 'portabled';
      
            var openRequest = indexedDBInstance.open(dbName, 1);
            openRequest.onerror = (errorEvent) => callback(null);
      
            openRequest.onupgradeneeded = createDBAndTables;
      
            openRequest.onsuccess = (event) => {
              var db: IDBDatabase = openRequest.result;
      
              try {
                var transaction = db.transaction(['files', 'metadata']);
                // files mentioned here, but not really used to detect
                // broken multi-store transaction implementation in Safari
      
                transaction.onerror = (errorEvent) => callback(null);
              
                var metadataStore = transaction.objectStore('metadata');
                var filesStore = transaction.objectStore('files');
                var editedUTCRequest = metadataStore.get('editedUTC');
              }
              catch (getStoreError) {
                callback(null);
                return;
              }
      
              if (!editedUTCRequest) {
                callback(null);
                return;
              }
      
              editedUTCRequest.onerror = (errorEvent) => {
                var detached = new IndexedDBDetached(db, null);
                callback(detached);
              };
      
              editedUTCRequest.onsuccess = (event) => {
                var result: MetadataData = editedUTCRequest.result;
                var detached = new IndexedDBDetached(db, result && typeof result.value === 'number' ? result.value : null);
                callback(detached);
              };
      
            };
            
            function createDBAndTables() {
              var db: IDBDatabase = openRequest.result;
              var filesStore = db.createObjectStore('files', { keyPath: 'path' });
              var metadataStore = db.createObjectStore('metadata', { keyPath: 'property' });
            }
          }
      
          class IndexedDBDetached implements Drive.Detached {
      
            constructor(
              private _db: IDBDatabase,
              public timestamp: number) {
            }
      
            applyTo(mainDrive: Drive, callback: Drive.Detached.CallbackWithShadow): void {
              var transaction = this._db.transaction(['files', 'metadata'], 'readwrite');
              var metadataStore = transaction.objectStore('metadata');
              var filesStore = transaction.objectStore('files');
      
              var countRequest = filesStore.count();
              countRequest.onerror = (errorEvent) => {
                console.error('Could not count files store.');
                callback(null);
              };
      
              countRequest.onsuccess = (event) => {
      
                var storeCount: number = countRequest.result;
      
                var cursorRequest = filesStore.openCursor();
                cursorRequest.onerror = (errorEvent) => callback(null);
      
                // to cleanup any files which content is the same on the main drive
                var deleteList: string[] = [];
                var anyLeft = false;
      
                var processedCount = 0;
      
                cursorRequest.onsuccess = (event) => {
                  var cursor: IDBCursor = cursorRequest.result;
      
                  if (!cursor) {
      
                    // cleaning up files whose content is duplicating the main drive
                    if (anyLeft) {
                      for (var i = 0; i < deleteList.length; i++) {
                        filesStore['delete'](deleteList[i]);
                      }
                    }
                    else {
                      filesStore.clear();
                      metadataStore.clear();
                    }
      
                    callback(new IndexedDBShadow(this._db, this.timestamp));
                    return;
                  }
      
                  if (callback.progress)
                    callback.progress(processedCount, storeCount);
                  processedCount++;
      
                  var result: FileData = (<any>cursor).value;
                  if (result && result.path) {
      
                    var existingContent = mainDrive.read(result.path);
                    if (existingContent === result.content) {
                      deleteList.push(result.path);
                    }
                    else {
                      mainDrive.timestamp = this.timestamp;
                      mainDrive.write(result.path, result.content);
                      anyLeft = true;
                    }
                  }
      
                  cursor['continue']();
                }; // cursorRequest.onsuccess
      
              }; // countRequest.onsuccess
      
            }
      
            purge(callback: Drive.Detached.CallbackWithShadow): void {
              var transaction = this._db.transaction(['files', 'metadata'], 'readwrite');
      
              var filesStore = transaction.objectStore('files');
              filesStore.clear();
      
              var metadataStore = transaction.objectStore('metadata');
              metadataStore.clear();
      
              callback(new IndexedDBShadow(this._db, -1));
            }
      
          }
      
          class IndexedDBShadow implements Drive.Shadow {
      
            constructor(private _db: IDBDatabase, public timestamp: number) {
            }
      
            write(file: string, content: string) {
              var transaction = this._db.transaction(['files', 'metadata'], 'readwrite');
              var filesStore = transaction.objectStore('files');
              var metadataStore = transaction.objectStore('metadata');
      
              // no file deletion here: we need to keep account of deletions too!
              var fileData: FileData = {
                path: file,
                content: content,
                state: null
              };
      
              var putFile = filesStore.put(fileData);
      
              var md: MetadataData = {
                property: 'editedUTC',
                value: Date.now()
              };
      
              metadataStore.put(md);
      
            }
          }
      
      
          interface FileData {
            path: string;
            content: string;
            state: string;
          }
      
          interface MetadataData {
            property: string;
            value: any;
          }
      
      
        }
      
      }
    • localStorage.ts
      module portabled {
        
        function getLocalStorage() {
          return typeof localStorage === 'undefined' || typeof localStorage.length !== 'number' ? null : localStorage;
        }
      
        // is it OK&
        export module persistence.localStorage {
      
          export function detect(uniqueKey: string, callback: (detached: Drive.Detached) => void): void {
            var localStorageInstance = getLocalStorage();
            if (!localStorageInstance) {
              callback(null);
              return;
            }
      
            var access = new LocalStorageAccess(localStorageInstance, uniqueKey);
            var dt = new LocalStorageDetached(access);
            callback(dt);
          }
          
          class LocalStorageAccess {
            private _cache: { [key: string]: string; } = {};
      
            constructor(private _localStorage: Storage, private _prefix: string) {
            }
      
            get (key: string): string {
              var k = this._expandKey(key);
              var r = this._localStorage.getItem(k);
              return r;
            }
          
          	set(key: string, value: string): void {
              var k = this._expandKey(key);
              return this._localStorage.setItem(k, value);
            }
      
            remove(key: string): void {
              var k = this._expandKey(key);
              return this._localStorage.removeItem(k);
            }
      
            keys(): string[] {
              var result: string[] = [];
              var len = this._localStorage.length;
              for (var i = 0; i < len; i++) {
                var str = this._localStorage.key(i);
                if (str.length > this._prefix.length && str.slice(0, this._prefix.length) === this._prefix)
                  result.push(str.slice(this._prefix.length));
              }
              return result;
            }
      
            private _expandKey(key: string): string {
              var k: string;
      
              if (!key) {
                k = this._prefix;
              }
              else {
                k = this._cache[key];
                if (!k)
                  this._cache[key] = k = this._prefix + key;
              }
              
              return k;
            }
        	}
      
      
          class LocalStorageDetached implements Drive.Detached {
      
            timestamp: number = 0;
      
            constructor(private _access: LocalStorageAccess) {
              var timestampStr = this._access.get('*timestamp');
              if (timestampStr && timestampStr.charAt(0)>='0' && timestampStr.charAt(0)<='9') {
                try {
                  this.timestamp = parseInt(timestampStr);
                }
                catch (parseError) {
                }
              }
            }
      
            applyTo(mainDrive: Drive, callback: Drive.Detached.CallbackWithShadow): void {
              var keys = this._access.keys();
              for (var i = 0; i < keys.length; i++) {
                var k = keys[i];
                if (k.charAt(0)==='/') {
                  var value = this._access.get(k);
                  mainDrive.write(k, value);
                }
              }
              
              var shadow = new LocalStorageShadow(this._access, mainDrive.timestamp);
              callback(shadow);
            }
      
            purge(callback: Drive.Detached.CallbackWithShadow): void {
              var keys = this._access.keys();
              for (var i = 0; i < keys.length; i++) {
                var k = keys[i];
                if (k.charAt(0)==='/') {
                  var value = this._access.remove(k);
                }
              }
      
              var shadow = new LocalStorageShadow(this._access, this.timestamp);
              callback(shadow);
            }
      
          }
          
          class LocalStorageShadow implements Drive.Shadow {
      
            constructor(private _access: LocalStorageAccess, public timestamp: number) {
            }
      
            write(file: string, content: string) {
              this._access.set(file, content);
              this._access.set('*timestamp', <any>this.timestamp);
            }
      
          }
      
        }
        
      }
      
    • mountDrive.ts
      module portabled.persistence {
      
        export function defaultPersistenceModules() {
          return [
            persistence.indexedDB,
            persistence.webSQL,
            persistence.localStorage
          ];
        }
      
        export function mountDrive(
          dom: Drive,
          uniqueKey: string,
          domTimestamp: number,
          optionalModules: Drive.Optional[],
          callback: mountDrive.Callback): void {
      
          var driveIndex = 0;
      
          loadNextOptional();
      
          function loadNextOptional() {
      
            while (driveIndex < optionalModules.length &&
              (!optionalModules[driveIndex] || typeof optionalModules[driveIndex].detect !== 'function')) {
              driveIndex++;
            }
      
            if (driveIndex >= optionalModules.length) {
              callback(new MountedDrive(dom, null));
              return;
            }
      
            var op = optionalModules[driveIndex];
            op.detect(
              uniqueKey,
              detached => {
                if (!detached) {
                  driveIndex++;
                  loadNextOptional();
                  return;
                }
      
                if (detached.timestamp > domTimestamp) {
                  var callbackWithShadow: Drive.Detached.CallbackWithShadow = loadedDrive => {
                    dom.timestamp = detached.timestamp;
                    callback(new MountedDrive(dom, loadedDrive));
                  };
                  if (callback.progress)
                    callbackWithShadow.progress = callback.progress;
                  detached.applyTo(dom, callbackWithShadow);
                }
                else {
                  var callbackWithShadow: Drive.Detached.CallbackWithShadow = loadedDrive => {
                    callback(new MountedDrive(dom, loadedDrive));
                  };
                  if (callback.progress)
                    callbackWithShadow.progress = callback.progress;
                  detached.purge(callbackWithShadow);
                }
              });
          }
      
        }
        
        export module mountDrive {
          
          export interface Callback {
      
            (drive: Drive): void;
      
            progress?: (current: number, total: number) => void;
      
          }
          
        }
        
        class MountedDrive implements Drive {
      
          timestamp: number = 0;
      
          constructor (private _dom: Drive, private _shadow: Drive.Shadow) {
            this.timestamp = this._dom.timestamp;
          }
          
          files(): string[] {
            return this._dom.files();
          }
      
          read(file: string): string {
            return this._dom.read(file);
          }
      
          write(file: string, content: string) {
            this._dom.timestamp = this.timestamp;
            this._dom.write(file, content);
            if (this._shadow) {
              this._shadow.timestamp = this.timestamp;
              this._shadow.write(file, content);
            }
          }
        }
        
      }
    • webSQL.ts
      module portabled {
      
        function getOpenDatabase() {
          return typeof openDatabase !== 'function' ? null : openDatabase;
        }
      
        export module persistence.webSQL {
      
          export function detect(uniqueKey: string, callback: (detached: Drive.Detached) => void): void {
      
            var openDatabaseInstance = getOpenDatabase();
            if (!openDatabaseInstance) {
              callback(null);
              return;
            }
      
            var dbName = uniqueKey || 'portabled';
      
            var db = openDatabase(
              dbName, // name
              1, // version
              'Portabled virtual filesystem data', // displayName
              1024 * 1024); // size
              // upgradeCallback?
      
      
            db.readTransaction(
              transaction => {
                transaction.executeSql(
                  'SELECT value from "*metadata" WHERE name=\'editedUTC\'',
                  [],
                  (transaction, result) => {
                    var editedValue: number = null;
                    if (result.rows && result.rows.length === 1) {
                      var editedValueStr = result.rows.item(0).value;
                      if (typeof editedValueStr === 'string') {
                        try {
                          editedValue = parseInt(editedValueStr);
                        }
                        catch (error) {
                          // unexpected value for the timestamp, continue as if no value found
                        }
                      }
                      else if (typeof editedValueStr === 'number') {
                        editedValue = editedValueStr;
                      }
                    }
      
                    callback(new WebSQLDetached(db, editedValue || 0, true));
                  },
                  (transaction, sqlError) => {
                    // no data
                    callback(new WebSQLDetached(db, 0, false));
                  });
              },
              sqlError=> {
                // failed to load
                callback(null);
              });
      
          }
      
          class WebSQLDetached implements Drive.Detached {
      
            constructor(
              private _db: Database,
              public timestamp: number,
            	private _metadataTableIsValid: boolean) {
            }
      
            applyTo(mainDrive: Drive, callback: Drive.Detached.CallbackWithShadow): void {
              this._db.readTransaction(
                transaction => listAllTables(
                  transaction,
                  tables => {
                    
                    var ftab = getFilenamesFromTables(tables);
      
                    this._applyToWithFiles(transaction, ftab, mainDrive, callback);
                  },
                  sqlError => {
                    reportSQLError('Failed to list tables for the webSQL database.', sqlError);
                    callback(new WebSQLShadow(this._db, this.timestamp, this._metadataTableIsValid));
                  }),
                sqlError => {
                  reportSQLError('Failed to open read transaction for the webSQL database.', sqlError);
                  callback(new WebSQLShadow(this._db, this.timestamp, this._metadataTableIsValid));
                });
            }
      
            purge(callback: Drive.Detached.CallbackWithShadow): void {
              this._db.transaction(
                transaction => listAllTables(
                  transaction,
                  tables => {
                    this._purgeWithTables(transaction, tables, callback);
                  },
                  sqlError => {
                  	reportSQLError('Failed to list tables for the webSQL database.', sqlError);
                    callback(new WebSQLShadow(this._db, 0, false));
                  }),
                sqlError => {
                  reportSQLError('Failed to open read-write transaction for the webSQL database.', sqlError);
                  callback(new WebSQLShadow(this._db, 0, false));
              });
          	}
            
            private _applyToWithFiles(transaction: SQLTransaction, ftab: { file: string; table: string; }[], mainDrive: Drive, callback: Drive.Detached.CallbackWithShadow): void {
      
              if (!ftab.length) {
                callback(new WebSQLShadow(this._db, this.timestamp, this._metadataTableIsValid));
                return;
              }
      
              var reportedFileCount = 0;
              
              var completeOne = () => {
                reportedFileCount++;
                if (reportedFileCount===ftab.length) {
                  callback(new WebSQLShadow(this._db, this.timestamp, this._metadataTableIsValid));
                }
              };
            
              var applyFile = (file: string, table: string) => {
                transaction.executeSql(
                  'SELECT * FROM "' + table + '"',
                  [],
                  (transaction, result) => {
                    if (result.rows.length) {
                      var row = result.rows.item(0);
                      if (row.value === null)
                        mainDrive.write(file, null);
                      else if (typeof row.value === 'string')
                        mainDrive.write(file, fromSqlText(row.value));
                    }
                    completeOne();
                  },
                  sqlError => {
                    completeOne();
                  });
              };
              
              for (var i = 0; i < ftab.length; i++) {
                applyFile(ftab[i].file, ftab[i].table);
              }
      
            }
            
            private _purgeWithTables(transaction: SQLTransaction, tables: string[], callback: Drive.Detached.CallbackWithShadow) {
              if (!tables.length) {
                callback(new WebSQLShadow(this._db, 0, false));
                return;
              }
      
              var droppedCount = 0;
      
              var completeOne = () => {
                droppedCount++;
                if(droppedCount === tables.length){
                  callback(new WebSQLShadow(this._db, 0, false));
                }
              };
      
              for (var i = 0; i < tables.length; i++) {
                transaction.executeSql(
                  'DROP TABLE "' + tables[i] + '"',
                  [],
                  (transaction, result) => {
                    completeOne();
                  },
                  (transaction, sqlError) => {
                    reportSQLError('Failed to drop table for the webSQL database.', sqlError);
                    completeOne();
                  });
              }
            }
      
          }
      
          class WebSQLShadow implements Drive.Shadow {
      
            private _cachedUpdateStatementsByFile: { [name: string]: string; } = {};
            private _closures = {
              updateMetadata: (transaction: SQLTransaction) => this._updateMetadata(transaction)
            };
      
            constructor(private _db: Database, public timestamp: number, private _metadataTableIsValid: boolean) {
            }
      
            write(file: string, content: string) {
              
              if (content || typeof content === 'string') {
                this._updateCore(file, content);
              }
              else {
                this._dropFileTable(file);
              }
            }
            
            private _updateCore(file: string, content: string) {
                var updateSQL = this._cachedUpdateStatementsByFile[file];
                if (!updateSQL) {
                  var tableName = mangleDatabaseObjectName(file);
                  updateSQL = this._createUpdateStatement(file, tableName);
                }
                this._db.transaction(
                  transaction => {
                    transaction.executeSql(
                      updateSQL,
                      ['content', content],
                      this._closures.updateMetadata,
                      (transaction, sqlError) => this._createTableAndUpdate(transaction, file, tableName, updateSQL, content));
                  },
                  sqlError => {
                    reportSQLError('Transaction failure updating file "' + file + '".', sqlError);
                  });
            }
            
            private _createTableAndUpdate(transaction: SQLTransaction, file: string, tableName: string, updateSQL: string, content: string) {
              if (!tableName)
                tableName = mangleDatabaseObjectName(file);
      
              transaction.executeSql(
                'CREATE TABLE "' + tableName + '" (name PRIMARY KEY, value)',
                [],
                (transaction, result) => {
                  transaction.executeSql(
                    updateSQL,
                    ['content', content],
                    this._closures.updateMetadata,
                    (transaction, sqlError) => {
                      reportSQLError('Failed to update table "' + tableName + '" for file "' + file + '" after creation.', sqlError);
                    });
                },
                (transaction, sqlError) => {
                  reportSQLError('Failed to create a table "' + tableName + '" for file "' + file + '".', sqlError);
                });
            }
            
            private _dropFileTable(file: string) {
              var tableName = mangleDatabaseObjectName(file);
              this._db.transaction(
                transaction => {
                  transaction.executeSql(
                    'DROP TABLE "' + tableName + '"',
                    [],
                    this._closures.updateMetadata,
                    (transaction, sqlError) => {
                      reportSQLError('Failed to drop table "' + tableName + '" for file "' + file + '".', sqlError);
                    });
                },
                sqlError => {
                  reportSQLError('Transaction failure dropping table "' + tableName + '" for file "' + file + '".', sqlError);
                });
            }
            
            private _updateMetadata(transaction: SQLTransaction) {
              var updateMetadataSQL = 'INSERT OR REPLACE INTO "*metadata" VALUES (?,?)';
              transaction.executeSql(
                updateMetadataSQL,
                ['editedUTC', this.timestamp],
                (transaction, result) => { }, // TODO: generate closure statically
                (transaction, error) => {
                  transaction.executeSql(
                    'CREATE TABLE "*metadata" (name PRIMARY KEY, value)',
                    [],
                    (transaction, result) => {
                      transaction.executeSql(updateMetadataSQL, [],() => { },() => { });
                    },
                    (transaction, sqlError) => {
                      reportSQLError('Failed to update metadata table after creation.', sqlError);
                    });
                });
                
            }
            
            private _createUpdateStatement(file: string, tableName: string): string {
              return this._cachedUpdateStatementsByFile[file] =
                'INSERT OR REPLACE INTO "' + tableName + '" VALUES (?,?)';
            }
          }
          
          
          function mangleDatabaseObjectName(name: string): string {
            // no need to polyfill btoa, if webSQL exists
            if (name.toLowerCase() === name)
              return name;
            else
              return '='+btoa(name);
          }
      
          function unmangleDatabaseObjectName(name: string): string {
            if (!name || name.charAt(0) === '*') return null;
            
            if (name.charAt(0) !== '=') return name;
      
            try {
              return atob(name.slice(1));
            }
            catch (error) {
              return name;
            }
          }
      
          export function listAllTables(
            transaction: SQLTransaction,
            callback: (tables: string[]) => void,
            errorCallback: (sqlError: SQLError)=>void) {
            transaction.executeSql(
              'SELECT tbl_name  from sqlite_master WHERE type=\'table\'',
              [],
              (transaction, result) => {
                var tables: string[] = [];
                for (var i = 0; i < result.rows.length; i++) {
                  var row = result.rows.item(i);
                  var table = row.tbl_name;
                  if(!table || (table[0] !== '*' && table.charAt(0) !== '=' && table.charAt(0) !== '/')) continue;
                  tables.push(row.tbl_name);
                }
                callback(tables);
              },
              (transaction, sqlError) => errorCallback(sqlError));
          }
          
          function getFilenamesFromTables(tables: string[]) {
            var filenames: { table: string; file: string; }[] = [];
            for (var i = 0; i < tables.length; i++) {
              var file = unmangleDatabaseObjectName(tables[i]);
              if (file)
              	filenames.push({ table: tables[i], file: file });
            }
            return filenames;
          }
      
          function toSqlText(text: string) {
            if (text.indexOf('\u00FF') < 0 && text.indexOf('\u0000') < 0) return text;
      
            return text.replace(/\u00FF/g, '\u00FFf').replace(/\u0000/g, '\u00FF0');
          }
      
          function fromSqlText(sqlText: string) { 
            if (sqlText.indexOf('\u00FF') < 0 && sqlText.indexOf('\u0000') < 0) return sqlText;
      
            return sqlText.replace(/\u00FFf/g, '\u00FF').replace(/\u00FF0/g, '\u0000');
          }
          
          function reportSQLError(message: string, sqlError: SQLError);
          function reportSQLError(sqlError: SQLError);
          function reportSQLError(message, sqlError?) {
            if (typeof console !== 'undefined' && typeof console.error === 'function') {
              if (sqlError)
                console.error(message, sqlError);
              else
                console.error(sqlError);
            }
          }
      
      
        }
      
      }
  • shell
    • consoleUI
      • ConsoleUI.ts
        module portabled.shell.consoleUI {
        
          export class ConsoleUI {
        
            cm: CodeMirror;
            doc: CodeMirror.Doc;
        
            constructor(private _host: HTMLElement) {
        
              this.cm = new CodeMirror(element => {
                element.style.position = 'absolute';
                element.style.height = '100%';
                element.style.width = '100%';
                this._host.appendChild(element);
              }, {
                lineNumbers: true,
                theme: '3024-night'
              });
              this.doc = this.cm.getDoc();
              
              setTimeout(() => this.cm.focus(), 100);
        
            }
        
            log(message: any, ...optionalParameters: any[]) {
              this.doc.replaceSelection(message);
            }
        
          }
        }
    • extensions
      • ExtensionHost.ts
        module portabled.shell.extensions {
        
          
        
        }
    • panels
      • Panels.ts
        module portabled.shell.panels {
        
          export class Panels {
        
            private _leftHost = element('div', {
              position: 'fixed',
              width: '49.9%',
              top: '0px', bottom: '3em',
              padding: '0.25em',
              background: 'cornflowerBlue',
              opacity: '0.5',
              zIndex: 100
            }, this._host);
        
            private _leftPanel = element('div', {
              width: '100%', height: '100%',
              border: 'solid 1px white',
              padding: '0.25em'
            }, this._leftHost);
        
            private _rightHost = element('div', {
              position: 'fixed',
              left: '50.2%',
              width: '49.9%',
              top: '0px', bottom: '3em',
              padding: '0.25em',
              background: 'cornflowerBlue',
              opacity: '0.5',
              zIndex: 100
            }, this._host);
        
            private _rightPanel = element('div', {
              width: '100%', height: '100%',
              border: 'solid 1px white',
              padding: '0.25em'
            }, this._rightHost);  
            
            constructor(private _host: HTMLElement) {
              setTextContent(this._rightPanel, 'one two');
            }
        
          }
        
        }
    • basic-html-body.css
      html {
        box-sizing: border-box;
        background: black;
        color: silver;
      }
      
      *, *:before, *:after {
        box-sizing: inherit;
      }
      
      html {
        height: 100%;
        margin: 0px;
        padding: 0px;
        border: none;
        overflow: hidden;
      }
      
      body {
        height: 100%;
        margin: 0px;
        padding: 0px;
        border: none;
        overflow: hidden;
      }
      
    • boot-initial.css
      body {
        opacity: 0.3;
      
      	filter: blur(2px);
      
        filter: url("#boot_gaussian_blur");
        -webkit-filter: blur(2px);
        -o-filter: blur(3px);
      }
    • boot-loaded.css
      body {
        opacity: 1;
        filter: none;
        -webkit-filter: none;
        -o-filter: none;
      }
    • index.html
      <!doctype html>
      <html>
        <head>
      		<meta charset="utf-8">
          <title> portable shell </title>
      
          <!-- main and boot time CSS -->
          <svg style="display: none;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
            <defs><filter id="boot_gaussian_blur"><feGaussianBlur in="SourceGraphic" stdDeviation="2" /></filter></defs>
        	</svg>
          <style>
      <%=uglifyCSS('shell/basic-html-body.css', 'shell/boot-initial.css')%>
          </style>
      
          <!-- CodeMiror CSS -->
          <style>
            <%=uglifyCSS(
              'imports/codemirror/lib/codemirror.css',
            	'imports/codemirror/theme/3024-night.css',
              'imports/codemirror/addon/hint/show-hint.css',
              'imports/codemirror/addon/dialog/dialog.css',
              'imports/codemirror/addon/merge/merge.css')%>
          </style>
      
        </head>
        <body>
      
          <!-- Error handling script -->
          <script data-legit=portabled><%=embedFile('errors.js')%></script>
      
          <!-- ES5 shim/sham, JSON3 -->
          <script data-legit=portabled>
            <%=embedFile('imports/es5-shim/es5-shim.min.js','imports/es5-shim/es5-sham.min.js', 'imports/json3/json3.min.js')%>
          </script>
      
      
          <!-- CodeMirror -->
          <script data-legit=portabled>
            <%=uglifyJS([
              'imports/codemirror/lib/codemirror.js',
              'imports/codemirror/addon/dialog/dialog.js',
              'imports/codemirror/addon/search/search.js',
              'imports/codemirror/addon/search/searchcursor.js',
              'imports/codemirror/addon/hint/show-hint.js',
              'imports/codemirror/mode/javascript/javascript.js',
              'imports/codemirror/addon/tern/tern.js',
              'imports/codemirror/addon/hint/javascript-hint.js',
              'imports/codemirror/mode/css/css.js',
              'imports/codemirror/addon/hint/css-hint.js',
              'imports/codemirror/mode/sass/sass.js',
              'imports/codemirror/mode/xml/xml.js',
              'imports/codemirror/addon/hint/xml-hint.js',
              'imports/codemirror/mode/htmlmixed/htmlmixed.js',
              'imports/codemirror/mode/htmlembedded/htmlembedded.js',
              'imports/codemirror/addon/hint/html-hint.js',
              'imports/codemirror/mode/markdown/markdown.js',
              'imports/codemirror/addon/edit/matchbrackets.js',
              'imports/codemirror/addon/selection/active-line.js'])%>
          </script>
      
      
          <!-- Main portabled JS code -->
          <script data-legit=portabled><%=typescriptBuild()%></script>
      
          <script data-legit=portabled> if (typeof portabled !== 'undefined') portabled.shell.start(); </script>
      
      
      
          <!-- finished loaded CSS -->
          <style><%=uglifyCSS('shell/boot-loaded.css')%></style>
      
        </body>
      </html>
    • start.ts
      module portabled.shell {
      
        export function start() {
      
          addEventListener(window, 'load', () => {
            var co = new consoleUI.ConsoleUI(document.body);
            var pan = new panels.Panels(document.body);
          });
        }
      
      }
  • typescript
    • ExternalDocument.ts
      module portabled.typescript {
      
        export interface ExternalDocument {
      
          text(): string;
          changes(): ts.TextChangeRange[];
      
        }
      
      }
    • ScriptDocumentSnapshot.ts
      module portabled.typescript {
      
        export class ScriptDocumentSnapshot implements ts.IScriptSnapshot {
      
          changes: ts.TextChangeRange[];
      
          private _text: string;
          private _lineStartPositions: number[] = null;
      
          constructor(doc: ExternalDocument) {
            this._text = doc.text();
            this.changes = doc.changes().slice(0);
          }
      
          getText(start: number, end: number): string {
            if (!this._text)
              return '';
            return this._text.slice(start, end);
          }
      
          getLength(): number {
            if (!this._text)
              return 0;
            return this._text.length;
          }
      
          getChangeRange(oldSnapshot: ts.IScriptSnapshot): ts.TextChangeRange {
      
            if (!this.changes.length)
              return ts.unchangedTextChangeRange;
      
            var typedOldSnapshot = <ScriptDocumentSnapshot>oldSnapshot;
            var chunk = typedOldSnapshot.changes ?
              this.changes.slice(typedOldSnapshot.changes.length) :
              this.changes;
      
            var result = ts.collapseTextChangeRangesAcrossMultipleVersions(chunk);
      
            return result;
      
          }
      
      
        }
        
      }
    • ScriptDocumentState.ts
      module portabled.typescript {
        
        export class ScriptDocumentState {
      
          private _snapshot: ScriptDocumentSnapshot = null;
      
          constructor(public doc: ExternalDocument) {
          }
      
          getScriptSnapshot() {
            if (!this._snapshot || this._snapshot.changes.length != this.doc.changes().length)
              this._snapshot = new ScriptDocumentSnapshot(this.doc);
            return this._snapshot;
          }
      
          getScriptVersion() {
            var changes = this.doc.changes();
            return changes.length;
          }
      
        }
        
      }
    • TypeScriptService.ts
      module portabled.typescript {
      
        export class TypeScriptService {
      
          private _service: ts.LanguageService;
      
          compilerOptions: ts.CompilerOptions;
          cancellation: ts.CancellationToken = null;
          currentDirectory = '/';
          defaultLibFilenames = ['#core.d.ts', '#extensions.d.ts', '#dom.generated.d.ts'];
      
          log: (text: string) => void = null;
      
          host: ts.LanguageServiceHost;
      
          private _scriptFileNames: string[] = null;
          private _scripts: { [fullPath: string]: ScriptDocumentState; } = {};
          private _defaultLibSnapshots: { [file: string]: ts.IScriptSnapshot; } = {};
      
          private _preloadScriptFileNames: string[] = [];
          private _preloadPendingScriptFileNames: string[] = [];
          private _preloadTimeout = 0;
      
          constructor(public registry = ts.createDocumentRegistry()) {
            this.compilerOptions = ts.getDefaultCompilerOptions();
            this.compilerOptions.target = ts.ScriptTarget.ES5;
            this.host = this._createHost();
            this._service = ts.createLanguageService(
              this.host,
              this.registry);
          }
      
          withSubset(predicate: (file: string) => boolean): TypeScriptService {
            var subs = new TypeScriptService(/*this.registry*/);
      
            this.service();
            subs.service();
      
            var allFiles = this.host.getScriptFileNames();
            subs._scriptFileNames = null;
      
            for (var i = 0; i < allFiles.length; i++) {
              var keep = allFiles[i].charAt(0) === '#' || predicate(allFiles[i]);
              if (!keep) continue;
      
              if (this._scripts.hasOwnProperty(allFiles[i]))
              	subs._scripts[allFiles[i]] = this._scripts[allFiles[i]];
              if (this._defaultLibSnapshots.hasOwnProperty(allFiles[i]))
                subs._defaultLibSnapshots[allFiles[i]] = this._defaultLibSnapshots[allFiles[i]];
            }
      
            return subs;
          }
      
          stopPreloading() {
            if (this._preloadScriptFileNames) {
      
              // from now on stop pretending only a subset of files exists, report all of them in host.getScriptFileNames()
              this._preloadScriptFileNames = null;
              this._preloadPendingScriptFileNames = null;
            }
          }
      
          service() {
            this.stopPreloading();
      
            return this._service;
          }
      
          addFile(file: string, doc: ExternalDocument) {
            var script = new ScriptDocumentState(doc);
            this._scripts[file] = script;
            this._scriptFileNames = null;
      
            if (this._preloadPendingScriptFileNames) {
              this._preloadPendingScriptFileNames.push(file);
              if (this._preloadTimeout)
                clearTimeout(this._preloadTimeout);
              this._preloadTimeout = setTimeout(() => {
                if (this._preloadPendingScriptFileNames)
                  this._preloadPendingScriptFileNames.sort();
                this._continuePreload();
              }, 2000);
            }
          }
      
          removeFile(file: string) {
            delete this._scripts[file];
            this._scriptFileNames = null;
      
            if (this._preloadScriptFileNames) {
              for (var i = 0; i < this._preloadPendingScriptFileNames.length; i++) {
                if (this._preloadPendingScriptFileNames[i] === file) {
                  delete this._preloadPendingScriptFileNames[i];
                  break;
                }
              }
            }
            if (this._preloadScriptFileNames) {
              for (var i = 0; i < this._preloadScriptFileNames.length; i++) {
                if (this._preloadScriptFileNames[i] === file) {
                  delete this._preloadScriptFileNames[i];
                  break;
                }
              }
            }
          }
      
          private _continuePreload() {
      
            this._preloadTimeout = 0;
      
            if (!this._preloadScriptFileNames || !this._preloadPendingScriptFileNames)
              return;
      
            var reportErrors: (errors: ts.Diagnostic[]) => void;
            if (this._preloadScriptFileNames.length < this.defaultLibFilenames.length) {
              // first work through the default libs
              var nextFile = this._preloadScriptFileNames[this._preloadScriptFileNames.length] = this.defaultLibFilenames[this._preloadScriptFileNames.length];
              reportErrors = errors => {
                if (console && typeof console.error == 'function') {
                  console.error(nextFile + ' ' + errors.length + ' errors:');
                  for (var i = 0; i < errors.length; i++) {
                    var err = errors[i];
                    console.error(err.file.getLineAndCharacterOfPosition(err.start), ' ', err.messageText);
                  }
                }
                else {
                  var all = [];
                  for (var i = 0; i < errors.length; i++) {
                    var err = errors[i];
                    var pos = err.file.getLineAndCharacterOfPosition(err.start); 
                    all.push(pos.line + ':' + pos.character + ' ' + err.messageText);
                    alert(nextFile + ' ' + errors.length + ' errors:\n' + all.join('\n'));
                  }
                }
              };
            }
            else {
              if (!this._preloadPendingScriptFileNames.length) {
      
                // finished preloading, from now on report all files instead of a subset
                this._preloadScriptFileNames = null;
                this._preloadPendingScriptFileNames = null;
                return; // TODO: call some event to notify it's all clear now
              }
      
              // after default libs are preloaded, get the other ordinary files
              var nextFile = this._preloadPendingScriptFileNames.shift();
              this._preloadScriptFileNames.push(nextFile);
            }
      
            var startPreload = dateNow();
            var errors= this._service.getSyntacticDiagnostics(nextFile);
            var preloadTimeSpent = dateNow() - startPreload;
      
            if (errors && errors.length && reportErrors)
              reportErrors(errors);
      
            var idleQuantum = Math.max(10, Math.min(300, preloadTimeSpent * 2));
      
            this._preloadTimeout = setTimeout(() => {
      
              if (!this._preloadScriptFileNames) return; // preloading stopped in the meantime
      
              var startPreload2 = dateNow();
              var errors = this._service.getSemanticDiagnostics(nextFile);
              var preloadTimeSpent2 = dateNow() - startPreload2;
      
              if (errors && errors.length && reportErrors)
                reportErrors(errors);
      
              var idleQuantum = Math.max(10, Math.min(200, preloadTimeSpent2 * 2));
      
              this._preloadTimeout = setTimeout(() => {
      
                if (!this._preloadScriptFileNames) return; // preloading stopped in the meantime
      
                var startPreload3 = dateNow();
                this._service.getEmitOutput(nextFile);
                var preloadTimeSpent3 = dateNow() - startPreload3;
      
                var idleQuantum = Math.max(10, Math.min(200, preloadTimeSpent3 * 2));
      
                this._preloadTimeout = setTimeout(() => {
      
                  if (!this._preloadScriptFileNames) return; // preloading stopped in the meantime
      
                  if (typeof console !== 'undefined' && typeof console.log === 'function')
                    console.log(
                      'TS preloaded ' + nextFile + ' ' +
                      (preloadTimeSpent + preloadTimeSpent2 + preloadTimeSpent3) / 1000 + ' sec. ' +
                      Math.floor(preloadTimeSpent * 100 / (preloadTimeSpent + preloadTimeSpent2 + preloadTimeSpent3)) + ':' +
                      Math.floor(preloadTimeSpent2 * 100 / (preloadTimeSpent + preloadTimeSpent2 + preloadTimeSpent3)) + '%' +
                      (this._preloadPendingScriptFileNames && this._preloadPendingScriptFileNames.length ? ' (' + this._preloadPendingScriptFileNames.length + ' to go)' : ''));
      
                  this._continuePreload();
      
                }, idleQuantum);
              }, idleQuantum);
            }, idleQuantum);
          }
      
          private _createHost(): ts.LanguageServiceHost {
            var result: ts.LanguageServiceHost = {
              getCompilationSettings: () => this.compilerOptions,
              getScriptFileNames: () => {
                if (this._preloadScriptFileNames) {
                  return this._preloadScriptFileNames;
                }
      
                if (!this._scriptFileNames) {
                  this._scriptFileNames = [];
                  for (var k in this._scripts) if (this._scripts.hasOwnProperty(k) && this._scripts[k])
                    this._scriptFileNames.push(k);
                  for (var i = 0; i < this.defaultLibFilenames.length; i++) {
                    this._scriptFileNames.push(this.defaultLibFilenames[i]);
                  }
                  this._scriptFileNames.sort();
                }
                return this._scriptFileNames;
              },
              getScriptVersion: (file) => {
                if (this.defaultLibFilenames.indexOf(file) >= 0)
                  return 'base';
      
                var script = this._scripts[file];
                return 'v' + script.getScriptVersion();
              },
              getScriptSnapshot: (file) => {
                if (this.defaultLibFilenames.indexOf(file) >= 0) {
                  if (!this._defaultLibSnapshots[file]) {
                    var elementId = file.charAt(0) === '#' ? file.slice(1) : file;
                    var scriptElement = <HTMLScriptElement>document.getElementById(elementId);
                    if (scriptElement == null)
                      return null;
                    this._defaultLibSnapshots[file] = ts.ScriptSnapshot.fromString(scriptElement.text || scriptElement.textContent || scriptElement.innerText);
                  }
                  return this._defaultLibSnapshots[file];
                }
      
                return this._scripts[file].getScriptSnapshot();
              },
              getLocalizedDiagnosticMessages: () => null,
              getCancellationToken: () => this.cancellation,
              getCurrentDirectory: () => this.currentDirectory,
              getNewLine: () => '\n',
              getDefaultLibFileName: () => this.defaultLibFilenames[0],
              log: (text) => {
                if (this.log) {
                  this.log(text);
                }
                else if ((<any>this).debugLog) {
                  if (typeof console != 'undefined') {
                    if (typeof console.groupCollapsed === 'function' && typeof console.groupEnd === 'function') {
                      console.groupCollapsed('TS');
                      if (typeof console.log === 'function')
                        console.log(text);
                      console.groupEnd();
                    }
                    else if (typeof console.info === 'function') {
                      console.info('*** TS ' + text);
                    }
                    else if (typeof console.log === 'function') {
                      console.log('*** TS ' + text);
                    }
                  }
                }
              }
            };
            return result;
      
          }
      
        }
      
      }
  • typings
    • codemirror.addons.d.ts
      interface CodeMirror {
      
        showHint(options: CodeMirror.showHint.Options);
      
      }
      
      declare module CodeMirror {
      
        module showHint {
          
          interface Options {
            
            /**
             * A hinting function. It is possible to set the async property on a hinting function to true,
             * in which case it will be called with arguments (cm, callback, ?options),
             * and the completion interface will only be popped up when the hinting function calls the callback,
             * passing it the object holding the completions.
             */
            hint: Function;
      
            /**
             * Determines whether, when only a single completion is available, it is completed without showing the dialog.
             * Defaults to true.
             */
            completeSingle?: boolean;
      
            /**
             * Whether the pop - up should be horizontally aligned with the start of the word (true, default),
             * or with the cursor (false).
             */
            alignWithWord?: boolean;
      
            /**
             * When enabled (which is the default), the pop - up will close when the editor is unfocused.
             */
            closeOnUnfocus?: boolean;
      
            /**
             * Allows you to provide a custom key map of keys to be active when the pop - up is active.
             * The handlers will be called with an extra argument, a handle to the completion menu,
             * which has moveFocus(n), setFocus(n), pick(), and close() methods (see the source for details),
             * that can be used to change the focused element, pick the current element or close the menu.
             * Additionnaly menuSize() can give you access to the size of the current dropdown menu,
             * length give you the number of availlable completions,
             * and data give you full access to the completion returned by the hinting function.
             */
            customKeys?: any;
      
            /**
             * Like customKeys above, but the bindings will be added to the set of default bindings,
             * instead of replacing them.
             */
            extraKeys?: any;
      
          }
            
          interface CompletionResult {
            list: Completion[];
            from: CodeMirror.Pos;
            to: CodeMirror.Pos;
          }
      
          interface Completion {
            
            /** The completion text. This is the only required property. */
            text: string;
      
            /** The text that should be displayed in the menu. */
            displayText?: string;
      
            /** A CSS class name to apply to the completion's line in the menu. */
            className?: string;
      
            /** A method used to create the DOM structure for showing the completion
             * by appending it to its first argument. */
            render?: (element: HTMLElement, self, data) => void;
      
            /** A method used to actually apply the completion, instead of the default behavior. */
            hint?: (cm: CodeMirror, self, data) => void;
      
            /** Optional from position that will be used by pick()
             * instead of the global one passed with the full list of completions. */
            from?: CodeMirror.Pos;
      
            /** Optional to position that will be used by pick() instead of the global one
             * passed with the full list of completions. */
            to?: CodeMirror.Pos;
      
          }
          
        }
      
        interface CodeMirrorStatic {
          
          /** Fired when the pop-up is shown. */
          on(completion: showHint.Options, eventName: 'shown', handler: (instance: showHint.CompletionResult) => void);
          off(completion: showHint.Options, eventName: 'shown', handler: (instance: showHint.CompletionResult) => void);
      
          /**
           * Fired when a completion is selected.
           * Passed the completion value (string or object) and the DOM node that represents it in the menu.
           */
          on(completion: showHint.Options, eventName: 'select', handler: (instance: showHint.CompletionResult, completion: showHint.Completion, element: HTMLElement) => void);
          off(completion: showHint.Options, eventName: 'select', handler: (instance: showHint.CompletionResult, completion: showHint.Completion, element: HTMLElement) => void);
      
          /**
           * Fired when a completion is picked. Passed the completion value (string or object).
           */
          on(completion: showHint.Options, eventName: 'pick', handler: (instance: showHint.CompletionResult, completion: showHint.Completion) => void);
          off(completion: showHint.Options, eventName: 'pick', handler: (instance: showHint.CompletionResult, completion: showHint.Completion) => void);
      
          /** Fired when the completion is finished. */
          on(completion: showHint.Options, eventName: 'close', handler: (instance: showHint.CompletionResult) => void);
          off(completion: showHint.Options, eventName: 'close', handler: (instance: showHint.CompletionResult) => void);
      
        }
      
      }
    • codemirror.d.ts
      declare var CodeMirror : CodeMirror.CodeMirrorStatic;
      
      interface CodeMirror {
      
        /** Tells you whether the editor currently has focus. */
        hasFocus(): boolean;
      
        /** Used to find the target position for horizontal cursor motion.start is a { line , ch } object,
        amount an integer(may be negative), and unit one of the string "char", "column", or "word".
        Will return a position that is produced by moving amount times the distance specified by unit.
        When visually is true , motion in right - to - left text will be visual rather than logical.
        When the motion was clipped by hitting the end or start of the document, the returned value will have a hitSide property set to true. */
        findPosH(start: CodeMirror.Pos, amount: number, unit: string, visually: boolean): { line: number; ch: number; hitSide?: boolean; };
      
        /** Similar to findPosH , but used for vertical motion.unit may be "line" or "page".
        The other arguments and the returned value have the same interpretation as they have in findPosH. */
        findPosV(start: CodeMirror.Pos, amount: number, unit: string): { line: number; ch: number; hitSide?: boolean; };
      
      
        /** Change the configuration of the editor. option should the name of an option, and value should be a valid value for that option. */
        setOption(option: string, value: any);
      
        /** Retrieves the current value of the given option for this editor instance. */
        getOption(option: string): any;
      
        /** Attach an additional keymap to the editor.
        This is mostly useful for add - ons that need to register some key handlers without trampling on the extraKeys option.
        Maps added in this way have a higher precedence than the extraKeys and keyMap options, and between them,
        the maps added earlier have a lower precedence than those added later, unless the bottom argument was passed,
        in which case they end up below other keymaps added with this method. */
        addKeyMap(map: any, bottom?: boolean);
      
        /** Disable a keymap added with addKeyMap.Either pass in the keymap object itself , or a string,
        which will be compared against the name property of the active keymaps. */
        removeKeyMap(map: any);
      
        /** Enable a highlighting overlay.This is a stateless mini - mode that can be used to add extra highlighting.
        For example, the search add - on uses it to highlight the term that's currently being searched.
        mode can be a mode spec or a mode object (an object with a token method). The options parameter is optional. If given, it should be an object.
        Currently, only the opaque option is recognized. This defaults to off, but can be given to allow the overlay styling, when not null,
        to override the styling of the base mode entirely, instead of the two being applied together. */
        addOverlay(mode: any, options?: any);
      
        /** Pass this the exact argument passed for the mode parameter to addOverlay to remove an overlay again. */
        removeOverlay(mode: any);
      
      
        /** Retrieve the currently active document from an editor. */
        getDoc(): CodeMirror.Doc;
      
        /** Attach a new document to the editor. Returns the old document, which is now no longer associated with an editor. */
        swapDoc(doc: CodeMirror.Doc): CodeMirror.Doc;
      
      
      
        /** Sets the gutter marker for the given gutter (identified by its CSS class, see the gutters option) to the given value.
        Value can be either null, to clear the marker, or a DOM element, to set it. The DOM element will be shown in the specified gutter next to the specified line. */
        setGutterMarker(line: any, gutterID: string, value: HTMLElement): CodeMirror.LineHandle;
      
        /** Remove all gutter markers in the gutter with the given ID. */
        clearGutter(gutterID: string);
      
        /** Set a CSS class name for the given line.line can be a number or a line handle.
        where determines to which element this class should be applied, can can be one of "text" (the text element, which lies in front of the selection),
        "background"(a background element that will be behind the selection),
        or "wrap" (the wrapper node that wraps all of the line's elements, including gutter elements).
        class should be the name of the class to apply. */
        addLineClass(line: any, where: string, _class_: string): CodeMirror.LineHandle;
      
        /** Remove a CSS class from a line.line can be a line handle or number.
        where should be one of "text", "background", or "wrap"(see addLineClass).
        class can be left off to remove all classes for the specified node, or be a string to remove only a specific class. */
        removeLineClass(line: any, where: string, class_: string): CodeMirror.LineHandle;
      
        /** Returns the line number, text content, and marker status of the given line, which can be either a number or a line handle. */
        lineInfo(line: any): {
            line: any;
            handle: any;
            text: string;
            /** Object mapping gutter IDs to marker elements. */
            gutterMarks: any;
            textClass: string;
            bgClass: string;
            wrapClass: string;
            /** Array of line widgets attached to this line. */
            widgets: any;
        };
      
        /** Puts node, which should be an absolutely positioned DOM node, into the editor, positioned right below the given { line , ch } position.
        When scrollIntoView is true, the editor will ensure that the entire node is visible (if possible).
        To remove the widget again, simply use DOM methods (move it somewhere else, or call removeChild on its parent). */
        addWidget(pos: CodeMirror.Pos, node: HTMLElement, scrollIntoView: boolean);
      
        /** Adds a line widget, an element shown below a line, spanning the whole of the editor's width, and moving the lines below it downwards.
        line should be either an integer or a line handle, and node should be a DOM node, which will be displayed below the given line.
        options, when given, should be an object that configures the behavior of the widget.
        Note that the widget node will become a descendant of nodes with CodeMirror-specific CSS classes, and those classes might in some cases affect it. */
        addLineWidget(line: any, node: HTMLElement, options?: {
            /** Whether the widget should cover the gutter. */
            coverGutter: boolean;
            /** Whether the widget should stay fixed in the face of horizontal scrolling. */
            noHScroll: boolean;
            /** Causes the widget to be placed above instead of below the text of the line. */
            above: boolean;
            /** When true, will cause the widget to be rendered even if the line it is associated with is hidden. */
            showIfHidden: boolean;
        }): CodeMirror.LineWidget;
      
      
        /** Programatically set the size of the editor (overriding the applicable CSS rules).
        width and height height can be either numbers(interpreted as pixels) or CSS units ("100%", for example).
        You can pass null for either of them to indicate that that dimension should not be changed. */
        setSize(width: any, height: any);
      
        /** Scroll the editor to a given(pixel) position.Both arguments may be left as null or undefined to have no effect. */
        scrollTo(x: number, y: number);
      
        /** Get an { left , top , width , height , clientWidth , clientHeight } object that represents the current scroll position, the size of the scrollable area,
        and the size of the visible area(minus scrollbars). */
        getScrollInfo(): CodeMirror.ScrollInfo;
      
        /** Scrolls the given element into view. pos is a { line , ch } position, referring to a given character, null, to refer to the cursor.
        The margin parameter is optional. When given, it indicates the amount of pixels around the given area that should be made visible as well. */
        scrollIntoView(pos: CodeMirror.Pos, margin?: number);
      
        /** Scrolls the given element into view. pos is a { left , top , right , bottom } object, in editor-local coordinates.
        The margin parameter is optional. When given, it indicates the amount of pixels around the given area that should be made visible as well. */
        scrollIntoView(pos: { left: number; top: number; right: number; bottom: number; }, margin: number);
      
        /** Returns an { left , top , bottom } object containing the coordinates of the cursor position.
        If mode is "local" , they will be relative to the top-left corner of the editable document.
        If it is "page" or not given, they are relative to the top-left corner of the page.
        where is a boolean indicating whether you want the start(true) or the end(false) of the selection. */
        cursorCoords(where: boolean, mode: string): { left: number; top: number; bottom: number; };
      
        /** Returns an { left , top , bottom } object containing the coordinates of the cursor position.
        If mode is "local" , they will be relative to the top-left corner of the editable document.
        If it is "page" or not given, they are relative to the top-left corner of the page.
        where specifies the precise position at which you want to measure. */
        cursorCoords(where: CodeMirror.Pos, mode: string): { left: number; top: number; bottom: number; };
      
        /** Returns the position and dimensions of an arbitrary character.pos should be a { line , ch } object.
        This differs from cursorCoords in that it'll give the size of the whole character,
        rather than just the position that the cursor would have when it would sit at that position. */
        charCoords(pos: CodeMirror.Pos, mode: string): { left: number; right: number; top: number; bottom: number; };
      
        /** Given an { left , top } object , returns the { line , ch } position that corresponds to it.
        The optional mode parameter determines relative to what the coordinates are interpreted. It may be "window" , "page"(the default) , or "local". */
        coordsChar(object: { left: number; top: number; }, mode?: string): CodeMirror.Pos;
      
        lineAtHeight(height: number, mode?: string): number;
        heightAtLine(line: number, mode?: string): number;
      
        /** Returns the line height of the default font for the editor. */
        defaultTextHeight(): number;
      
        /** Returns the pixel width of an 'x' in the default font for the editor.
        (Note that for non - monospace fonts , this is mostly useless, and even for monospace fonts, non - ascii characters might have a different width). */
        defaultCharWidth(): number;
      
        /** Returns a { from , to } object indicating the start (inclusive) and end (exclusive) of the currently rendered part of the document.
        In big documents, when most content is scrolled out of view, CodeMirror will only render the visible part, and a margin around it.
        See also the viewportChange event. */
        getViewport(): { from: number; to: number };
      
        /** If your code does something to change the size of the editor element (window resizes are already listened for), or unhides it,
        you should probably follow up by calling this method to ensure CodeMirror is still looking as intended. */
        refresh();
      
      
        /** Retrieves information about the token the current mode found before the given position (a {line, ch} object). */
        getTokenAt(pos: CodeMirror.Pos): {
            /** The character(on the given line) at which the token starts. */
            start: number;
            /** The character at which the token ends. */
            end: number;
            /** The token's string. */
            string: string;
            /** The token type the mode assigned to the token, such as "keyword" or "comment" (may also be null). */
            type: string;
            /** The mode's state at the end of this token. */
            state: any;            
        };
      
        /** Returns the mode's parser state, if any, at the end of the given line number.
        If no line number is given, the state at the end of the document is returned.
        This can be useful for storing parsing errors in the state, or getting other kinds of contextual information for a line. */
        getStateAfter(line?: number): any;
      
        /** CodeMirror internally buffers changes and only updates its DOM structure after it has finished performing some operation.
        If you need to perform a lot of operations on a CodeMirror instance, you can call this method with a function argument.
        It will call the function, buffering up all changes, and only doing the expensive update after the function returns.
        This can be a lot faster. The return value from this method will be the return value of your function. */
        operation<T>(fn: ()=> T): T;
      
        /** Adjust the indentation of the given line.
        The second argument (which defaults to "smart") may be one of:
        "prev" Base indentation on the indentation of the previous line.
        "smart" Use the mode's smart indentation if available, behave like "prev" otherwise.
        "add" Increase the indentation of the line by one indent unit.
        "subtract" Reduce the indentation of the line. */
        indentLine(line: number, dir?: string);
      
      
        /** Give the editor focus. */
        focus();
      
        /** Returns the hidden textarea used to read input. */
        getInputField(): HTMLTextAreaElement;
      
        /** Returns the DOM node that represents the editor, and controls its size. Remove this from your tree to delete an editor instance. */
        getWrapperElement(): HTMLElement;
      
        /** Returns the DOM node that is responsible for the scrolling of the editor. */
        getScrollerElement(): HTMLElement;
      
        /** Fetches the DOM node that contains the editor gutters. */
        getGutterElement(): HTMLElement;
      
      
      
        /** Events are registered with the on method (and removed with the off method).
        These are the events that fire on the instance object. The name of the event is followed by the arguments that will be passed to the handler.
        The instance argument always refers to the editor instance. */
        on(eventName: string, handler: (instance: CodeMirror) => void );
        off(eventName: string, handler: (instance: CodeMirror) => void );
      
        /** Fires every time the content of the editor is changed. */
        on(eventName: 'change', handler: (instance: CodeMirror, change: CodeMirror.EditorChange) => void );
        off(eventName: 'change', handler: (instance: CodeMirror, change: CodeMirror.EditorChange) => void );
      
        /** Fires every time the content of the editor is changed. */
        on(eventName: 'changes', handler: (instance: CodeMirror, change: CodeMirror.EditorChange[]) => void );
        off(eventName: 'changes', handler: (instance: CodeMirror, change: CodeMirror.EditorChange[]) => void );
      
        /** This event is fired before a change is applied, and its handler may choose to modify or cancel the change.
        The changeObj never has a next property, since this is fired for each individual change, and not batched per operation.
        Note: you may not do anything from a "beforeChange" handler that would cause changes to the document or its visualization.
        Doing so will, since this handler is called directly from the bowels of the CodeMirror implementation,
        probably cause the editor to become corrupted. */
        on(eventName: 'beforeChange', handler: (instance: CodeMirror, change: CodeMirror.EditorChangeCancellable) => void );
        off(eventName: 'beforeChange', handler: (instance: CodeMirror, change: CodeMirror.EditorChangeCancellable) => void );
      
        /** Will be fired when the cursor or selection moves, or any change is made to the editor content. */
        on(eventName: 'cursorActivity', handler: (instance: CodeMirror) => void );
        off(eventName: 'cursorActivity', handler: (instance: CodeMirror) => void );
      
        /** This event is fired before the selection is moved. Its handler may modify the resulting selection head and anchor.
        Handlers for this event have the same restriction as "beforeChange" handlers: they should not do anything to directly update the state of the editor. */
        on(eventName: 'beforeSelectionChange', handler: (instance: CodeMirror, selection: { head: CodeMirror.Pos; anchor: CodeMirror.Pos; }) => void );
        off(eventName: 'beforeSelectionChange', handler: (instance: CodeMirror, selection: { head: CodeMirror.Pos; anchor: CodeMirror.Pos; }) => void );
      
        /** Fires whenever the view port of the editor changes (due to scrolling, editing, or any other factor).
        The from and to arguments give the new start and end of the viewport. */
        on(eventName: 'viewportChange', handler: (instance: CodeMirror, from: number, to: number) => void );
        off(eventName: 'viewportChange', handler: (instance: CodeMirror, from: number, to: number) => void );
      
        /** Fires when the editor gutter (the line-number area) is clicked. Will pass the editor instance as first argument,
        the (zero-based) number of the line that was clicked as second argument, the CSS class of the gutter that was clicked as third argument,
        and the raw mousedown event object as fourth argument. */
        on(eventName: 'gutterClick', handler: (instance: CodeMirror, line: number, gutter: string, clickEvent: Event) => void );
        off(eventName: 'gutterClick', handler: (instance: CodeMirror, line: number, gutter: string, clickEvent: Event) => void );
      
        /** Fires whenever the editor is focused. */
        on(eventName: 'focus', handler: (instance: CodeMirror) => void );
        off(eventName: 'focus', handler: (instance: CodeMirror) => void );
      
        /** Fires whenever the editor is unfocused. */
        on(eventName: 'blur', handler: (instance: CodeMirror) => void );
        off(eventName: 'blur', handler: (instance: CodeMirror) => void );
      
        /** Fires when the editor is scrolled. */
        on(eventName: 'scroll', handler: (instance: CodeMirror) => void );
        off(eventName: 'scroll', handler: (instance: CodeMirror) => void );
      
        /** Will be fired whenever CodeMirror updates its DOM display. */
        on(eventName: 'update', handler: (instance: CodeMirror) => void );
        off(eventName: 'update', handler: (instance: CodeMirror) => void );
      
        /** Fired whenever a line is (re-)rendered to the DOM. Fired right after the DOM element is built, before it is added to the document.
        The handler may mess with the style of the resulting element, or add event handlers, but should not try to change the state of the editor. */
        on(eventName: 'renderLine', handler: (instance: CodeMirror, line: number, element: HTMLElement) => void );
        off(eventName: 'renderLine', handler: (instance: CodeMirror, line: number, element: HTMLElement) => void );
      }
      
      declare module CodeMirror {
        
        export interface ScrollInfo {
          left: any;
          top: any;
          width: any;
          height: any;
          clientWidth: any;
          clientHeight: any;
        }
        
        export interface CodeMirrorStatic {
          
          Pass: any;
      
          new (host: HTMLElement, options?: CodeMirror.Options): CodeMirror;
          new (callback: (host: HTMLElement) => void , options?: CodeMirror.Options): CodeMirror;
      
          (host: HTMLElement, options?: CodeMirror.Options): CodeMirror;
          (callback: (host: HTMLElement) => void , options?: CodeMirror.Options): CodeMirror;
      
          Doc: {
            (text: string, mode?: any, firstLineNumber?: number): Doc;
            new (text: string, mode?: any, firstLineNumber?: number): Doc;
          };
      
          Pos: {
            (line: number, ch?: number): Pos;
            new (line: number, ch?: number): Pos;
          };
      
          fromTextArea(host: HTMLTextAreaElement, options?: Options): CodeMirror;
      
          version: string;
      
          /** If you want to define extra methods in terms of the CodeMirror API, it is possible to use defineExtension.
          This will cause the given value(usually a method) to be added to all CodeMirror instances created from then on. */
          defineExtension(name: string, value: any);
      
          /** Like defineExtension, but the method will be added to the interface for Doc objects instead. */
          defineDocExtension(name: string, value: any);
      
          /** Similarly, defineOption can be used to define new options for CodeMirror.
          The updateFunc will be called with the editor instance and the new value when an editor is initialized,
          and whenever the option is modified through setOption. */
          defineOption(name: string, default_: any, updateFunc: Function);
      
          /** If your extention just needs to run some code whenever a CodeMirror instance is initialized, use CodeMirror.defineInitHook.
          Give it a function as its only argument, and from then on, that function will be called (with the instance as argument)
          whenever a new CodeMirror instance is initialized. */
          defineInitHook(func: Function);
      
          normalizeKeyMap(keymap: any): any;
      
      
      
          on(element: any, eventName: string, handler: Function);
          off(element: any, eventName: string, handler: Function);
      
          /** Fired whenever a change occurs to the document. changeObj has a similar type as the object passed to the editor's "change" event,
          but it never has a next property, because document change events are not batched (whereas editor change events are). */
          on(doc: Doc, eventName: 'change', handler: (instance: Doc, change: EditorChange) => void);
          off(doc: Doc, eventName: 'change', handler: (instance: Doc, change: EditorChange) => void);
      
          /** See the description of the same event on editor instances. */
          on(doc: Doc, eventName: 'beforeChange', handler: (instance: Doc, change: EditorChangeCancellable) => void);
          off(doc: Doc, eventName: 'beforeChange', handler: (instance: Doc, change: EditorChangeCancellable) => void);
      
          /** Fired whenever the cursor or selection in this document changes. */
          on(doc: Doc, eventName: 'cursorActivity', handler: (instance: CodeMirror) => void);
          off(doc: Doc, eventName: 'cursorActivity', handler: (instance: CodeMirror) => void);
      
          /** Equivalent to the event by the same name as fired on editor instances. */
          on(doc: Doc, eventName: 'beforeSelectionChange', handler: (instance: CodeMirror, selection: { head: Pos; anchor: Pos; }) => void);
          off(doc: Doc, eventName: 'beforeSelectionChange', handler: (instance: CodeMirror, selection: { head: Pos; anchor: Pos; }) => void);
      
          /** Will be fired when the line object is deleted. A line object is associated with the start of the line.
          Mostly useful when you need to find out when your gutter markers on a given line are removed. */
          on(line: LineHandle, eventName: 'delete', handler: () => void);
          off(line: LineHandle, eventName: 'delete', handler: () => void);
      
          /** Fires when the line's text content is changed in any way (but the line is not deleted outright).
          The change object is similar to the one passed to change event on the editor object. */
          on(line: LineHandle, eventName: 'change', handler: (line: LineHandle, change: EditorChange) => void);
          off(line: LineHandle, eventName: 'change', handler: (line: LineHandle, change: EditorChange) => void);
      
          /** Fired when the cursor enters the marked range. From this event handler, the editor state may be inspected but not modified,
          with the exception that the range on which the event fires may be cleared. */
          on(marker: TextMarker, eventName: 'beforeCursorEnter', handler: () => void);
          off(marker: TextMarker, eventName: 'beforeCursorEnter', handler: () => void);
      
          /** Fired when the range is cleared, either through cursor movement in combination with clearOnEnter or through a call to its clear() method.
          Will only be fired once per handle. Note that deleting the range through text editing does not fire this event,
          because an undo action might bring the range back into existence. */
          on(marker: TextMarker, eventName: 'clear', handler: () => void);
          off(marker: TextMarker, eventName: 'clear', handler: () => void);
      
          /** Fired when the last part of the marker is removed from the document by editing operations. */
          on(marker: TextMarker, eventName: 'hide', handler: () => void);
          off(marker: TextMarker, eventName: 'hide', handler: () => void);
      
          /** Fired when, after the marker was removed by editing, a undo operation brought the marker back. */
          on(marker: TextMarker, eventName: 'unhide', handler: () => void);
          off(marker: TextMarker, eventName: 'unhide', handler: () => void);
      
          /** Fired whenever the editor re-adds the widget to the DOM. This will happen once right after the widget is added (if it is scrolled into view),
          and then again whenever it is scrolled out of view and back in again, or when changes to the editor options
          or the line the widget is on require the widget to be redrawn. */
          on(line: LineWidget, eventName: 'redraw', handler: () => void);
          off(line: LineWidget, eventName: 'redraw', handler: () => void);
        }
        
        export interface Doc {
      
          /** Get the current editor content. You can pass it an optional argument to specify the string to be used to separate lines (defaults to "\n"). */
          getValue(seperator?: string): string;
      
          /** Set the editor content. */
          setValue(content: string);
      
          /** Get the text between the given points in the editor, which should be {line, ch} objects.
          An optional third argument can be given to indicate the line separator string to use (defaults to "\n"). */
          getRange(from: Pos, to: CodeMirror.Pos, seperator?: string): string;
      
          /** Replace the part of the document between from and to with the given string.
          from and to must be {line, ch} objects. to can be left off to simply insert the string at position from. */
          replaceRange(replacement: string, from: CodeMirror.Pos, to: CodeMirror.Pos);
      
          /** Get the content of line n. */
          getLine(n: number): string;
      
          /** Set the content of line n. */
          setLine(n: number, text: string);
      
          /** Remove the given line from the document. */
          removeLine(n: number);
      
          /** Get the number of lines in the editor. */
          lineCount(): number;
      
          /** Get the first line of the editor. This will usually be zero but for linked sub-views,
          or documents instantiated with a non-zero first line, it might return other values. */
          firstLine(): number;
      
          /** Get the last line of the editor. This will usually be lineCount() - 1, but for linked sub-views, it might return other values. */
          lastLine(): number;
      
          /** Fetches the line handle for the given line number. */
          getLineHandle(num: number): CodeMirror.LineHandle;
      
          /** Given a line handle, returns the current position of that line (or null when it is no longer in the document). */
          getLineNumber(handle: CodeMirror.LineHandle): number;
      
          /** Iterate over the whole document, and call f for each line, passing the line handle.
          This is a faster way to visit a range of line handlers than calling getLineHandle for each of them.
          Note that line handles have a text property containing the line's content (as a string). */
          eachLine(f: (line: CodeMirror.LineHandle) => void);
      
          /** Iterate over the range from start up to (not including) end, and call f for each line, passing the line handle.
          This is a faster way to visit a range of line handlers than calling getLineHandle for each of them.
          Note that line handles have a text property containing the line's content (as a string). */
          eachLine(start: number, end: number, f: (line: CodeMirror.LineHandle) => void);
      
          /** Set the editor content as 'clean', a flag that it will retain until it is edited, and which will be set again when such an edit is undone again.
          Useful to track whether the content needs to be saved. */
          markClean();
      
          /** Returns whether the document is currently clean (not modified since initialization or the last call to markClean). */
          isClean(): boolean;
      
      
      
          /** Get the currently selected code. */
          getSelection(): string;
      
          /** Replace the selection with the given string. By default, the new selection will span the inserted text.
          The optional collapse argument can be used to change this passing "start" or "end" will collapse the selection to the start or end of the inserted text. */
          replaceSelection(replacement: string, collapse?: string)
      
          /** start is a an optional string indicating which end of the selection to return.
          It may be "start" , "end" , "head"(the side of the selection that moves when you press shift + arrow),
          or "anchor"(the fixed side of the selection).Omitting the argument is the same as passing "head".A { line , ch } object will be returned. */
          getCursor(start?: string): CodeMirror.Pos;
      
          /** Return true if any text is selected. */
          somethingSelected(): boolean;
      
          /** Set the cursor position.You can either pass a single { line , ch } object , or the line and the character as two separate parameters. */
          setCursor(pos: CodeMirror.Pos);
      
          /** Set the selection range.anchor and head should be { line , ch } objects.head defaults to anchor when not given. */
          setSelection(anchor: CodeMirror.Pos, head: CodeMirror.Pos);
      
          /** Similar to setSelection , but will, if shift is held or the extending flag is set,
          move the head of the selection while leaving the anchor at its current place.
          pos2 is optional , and can be passed to ensure a region (for example a word or paragraph) will end up selected
          (in addition to whatever lies between that region and the current anchor). */
          extendSelection(from: CodeMirror.Pos, to?: CodeMirror.Pos);
      
          /** Sets or clears the 'extending' flag , which acts similar to the shift key,
          in that it will cause cursor movement and calls to extendSelection to leave the selection anchor in place. */
          setExtending(value: boolean);
      
      
          /** Retrieve the editor associated with a document. May return null. */
          getEditor(): CodeMirror;
      
      
          /** Create an identical copy of the given doc. When copyHistory is true , the history will also be copied.Can not be called directly on an editor. */
          copy(copyHistory: boolean): CodeMirror.Doc;
      
          /** Create a new document that's linked to the target document. Linked documents will stay in sync (changes to one are also applied to the other) until unlinked. */
          linkedDoc(options: {
            /** When turned on, the linked copy will share an undo history with the original.
            Thus, something done in one of the two can be undone in the other, and vice versa. */
            sharedHist?: boolean;
            from?: number;
            /** Can be given to make the new document a subview of the original. Subviews only show a given range of lines.
            Note that line coordinates inside the subview will be consistent with those of the parent,
            so that for example a subview starting at line 10 will refer to its first line as line 10, not 0. */
            to?: number;
            /** By default, the new document inherits the mode of the parent. This option can be set to a mode spec to give it a different mode. */
            mode: any;
          }): CodeMirror.Doc;
      
          /** Break the link between two documents. After calling this , changes will no longer propagate between the documents,
          and, if they had a shared history, the history will become separate. */
          unlinkDoc(doc: CodeMirror.Doc);
      
          /** Will call the given function for all documents linked to the target document. It will be passed two arguments,
          the linked document and a boolean indicating whether that document shares history with the target. */
          iterLinkedDocs(fn: (doc: CodeMirror.Doc, sharedHist: boolean) => void);
      
          /** Undo one edit (if any undo events are stored). */
          undo();
      
          /** Redo one undone edit. */
          redo();
      
          /** Returns an object with {undo, redo } properties , both of which hold integers , indicating the amount of stored undo and redo operations. */
          historySize(): { undo: number; redo: number; };
      
          /** Clears the editor's undo history. */
          clearHistory();
      
          /** Get a(JSON - serializeable) representation of the undo history. */
          getHistory(): any;
      
          /** Replace the editor's undo history with the one provided, which must be a value as returned by getHistory.
          Note that this will have entirely undefined results if the editor content isn't also the same as it was when getHistory was called. */
          setHistory(history: any);
      
      
          /** Can be used to mark a range of text with a specific CSS class name. from and to should be { line , ch } objects. */
          markText(from: CodeMirror.Pos, to: CodeMirror.Pos, options?: CodeMirror.TextMarkerOptions): TextMarker;
      
          /** Inserts a bookmark, a handle that follows the text around it as it is being edited, at the given position.
          A bookmark has two methods find() and clear(). The first returns the current position of the bookmark, if it is still in the document,
          and the second explicitly removes the bookmark. */
          setBookmark(pos: CodeMirror.Pos, options?: {
            /** Can be used to display a DOM node at the current location of the bookmark (analogous to the replacedWith option to markText). */
            widget?: HTMLElement;
      
            /** By default, text typed when the cursor is on top of the bookmark will end up to the right of the bookmark.
            Set this option to true to make it go to the left instead. */
            insertLeft?: boolean;
          }): CodeMirror.TextMarker;
      
          /** Returns an array of all the bookmarks and marked ranges present at the given position. */
          findMarksAt(pos: CodeMirror.Pos): TextMarker[];
      
          /** Returns an array containing all marked ranges in the document. */
          getAllMarks(): CodeMirror.TextMarker[];
      
      
          /** Gets the mode object for the editor. Note that this is distinct from getOption("mode"), which gives you the mode specification,
          rather than the resolved, instantiated mode object. */
          getMode(): any;
      
          /** Calculates and returns a { line , ch } object for a zero-based index whose value is relative to the start of the editor's text.
          If the index is out of range of the text then the returned object is clipped to start or end of the text respectively. */
          posFromIndex(index: number): CodeMirror.Pos;
      
          /** The reverse of posFromIndex. */
          indexFromPos(object: CodeMirror.Pos): number;
      
        }
      
        export interface LineHandle {
          text: string;
        }
      
        export interface TextMarker {
          /** Remove the mark. */
          clear();
      
          /** Returns a {from, to} object (both holding document positions), indicating the current position of the marked range,
          or undefined if the marker is no longer in the document. */
          find(): { from: CodeMirror.Pos; to: CodeMirror.Pos; };
      
          /**  Returns an object representing the options for the marker. If copyWidget is given true, it will clone the value of the replacedWith option, if any. */
          getOptions(copyWidget: boolean): CodeMirror.TextMarkerOptions;
        }
      
        export interface LineWidget {
          /** Removes the widget. */
          clear(): void;
      
          /** Call this if you made some change to the widget's DOM node that might affect its height.
          It'll force CodeMirror to update the height of the line that contains the widget. */
          changed();
        }
      
        export interface EditorChange {
          /** Position (in the pre-change coordinate system) where the change started. */
          from: CodeMirror.Pos;
          /** Position (in the pre-change coordinate system) where the change ended. */
          to: CodeMirror.Pos;
          /** Array of strings representing the text that replaced the changed range (split by line). */
          text: string[];
          /**  Text that used to be between from and to, which is overwritten by this change. */
          removed: string[];
        }
      
        export interface EditorChangeCancellable extends CodeMirror.EditorChange {
          /** may be used to modify the change. All three arguments to update are optional, and can be left off to leave the existing value for that field intact. */
          update(from?: CodeMirror.Pos, to?: CodeMirror.Pos, text?: string);
      
          cancel();
        }
      
        export interface Pos {
          ch: number;
          line: number;
        }
      
        export interface Options {
          /** string| The starting value of the editor. Can be a string, or a document object. */
          value?: any;
      
          /** string|object. The mode to use. When not given, this will default to the first mode that was loaded.
          It may be a string, which either simply names the mode or is a MIME type associated with the mode.
          Alternatively, it may be an object containing configuration options for the mode,
          with a name property that names the mode (for example {name: "javascript", json: true}). */
          mode?: any;
      
          /** The theme to style the editor with. You must make sure the CSS file defining the corresponding .cm-s-[name] styles is loaded.
          The default is "default". */
          theme?: string;
      
          /** How many spaces a block (whatever that means in the edited language) should be indented. The default is 2. */
          indentUnit?: number;
      
          /** Whether to use the context-sensitive indentation that the mode provides (or just indent the same as the line before). Defaults to true. */
          smartIndent?: boolean;
      
          /** The width of a tab character. Defaults to 4. */
          tabSize?: number;
      
          /** Whether, when indenting, the first N*tabSize spaces should be replaced by N tabs. Default is false. */
          indentWithTabs?: boolean;
      
          /** Configures whether the editor should re-indent the current line when a character is typed
          that might change its proper indentation (only works if the mode supports indentation). Default is true. */
          electricChars?: boolean;
      
          /** Determines whether horizontal cursor movement through right-to-left (Arabic, Hebrew) text
          is visual (pressing the left arrow moves the cursor left)
          or logical (pressing the left arrow moves to the next lower index in the string, which is visually right in right-to-left text).
          The default is false on Windows, and true on other platforms. */
          rtlMoveVisually?: boolean;
      
          /** Configures the keymap to use. The default is "default", which is the only keymap defined in codemirror.js itself.
          Extra keymaps are found in the keymap directory. See the section on keymaps for more information. */
          keyMap?: string;
      
          /** Can be used to specify extra keybindings for the editor, alongside the ones defined by keyMap. Should be either null, or a valid keymap value. */
          extraKeys?: any;
      
          /** Whether CodeMirror should scroll or wrap for long lines. Defaults to false (scroll). */
          lineWrapping?: boolean;
      
          /** Whether to show line numbers to the left of the editor. */
          lineNumbers?: boolean;
      
          /** At which number to start counting lines. Default is 1. */
          firstLineNumber?: number;
      
          /** A function used to format line numbers. The function is passed the line number, and should return a string that will be shown in the gutter. */
          lineNumberFormatter?: (line: number) => string;
      
          /** Can be used to add extra gutters (beyond or instead of the line number gutter).
          Should be an array of CSS class names, each of which defines a width (and optionally a background),
          and which will be used to draw the background of the gutters.
          May include the CodeMirror-linenumbers class, in order to explicitly set the position of the line number gutter
          (it will default to be to the right of all other gutters). These class names are the keys passed to setGutterMarker. */
          gutters?: string[];
      
          /** Determines whether the gutter scrolls along with the content horizontally (false)
          or whether it stays fixed during horizontal scrolling (true, the default). */
          fixedGutter?: boolean;
      
          /** boolean|string. This disables editing of the editor content by the user. If the special value "nocursor" is given (instead of simply true), focusing of the editor is also disallowed. */
          readOnly?: any;
      
          /**Whether the cursor should be drawn when a selection is active. Defaults to false. */
          showCursorWhenSelecting?: boolean;
      
          /** The maximum number of undo levels that the editor stores. Defaults to 40. */
          undoDepth?: number;
      
          /** The period of inactivity (in milliseconds) that will cause a new history event to be started when typing or deleting. Defaults to 500. */
          historyEventDelay?: number;
      
          /** The tab index to assign to the editor. If not given, no tab index will be assigned. */
          tabindex?: number;
      
          /** Can be used to make CodeMirror focus itself on initialization. Defaults to off.
          When fromTextArea is used, and no explicit value is given for this option, it will be set to true when either the source textarea is focused,
          or it has an autofocus attribute and no other element is focused. */
          autofocus?: boolean;
      
          /** Controls whether drag-and - drop is enabled. On by default. */
          dragDrop?: boolean;
      
          /** When given , this will be called when the editor is handling a dragenter , dragover , or drop event.
          It will be passed the editor instance and the event object as arguments.
          The callback can choose to handle the event itself , in which case it should return true to indicate that CodeMirror should not do anything further. */
          onDragEvent?: (instance: CodeMirror, event: Event) => boolean;
      
          /** This provides a rather low - level hook into CodeMirror's key handling.
          If provided, this function will be called on every keydown, keyup, and keypress event that CodeMirror captures.
          It will be passed two arguments, the editor instance and the key event.
          This key event is pretty much the raw key event, except that a stop() method is always added to it.
          You could feed it to, for example, jQuery.Event to further normalize it.
          This function can inspect the key event, and handle it if it wants to.
          It may return true to tell CodeMirror to ignore the event.
          Be wary that, on some browsers, stopping a keydown does not stop the keypress from firing, whereas on others it does.
          If you respond to an event, you should probably inspect its type property and only do something when it is keydown
          (or keypress for actions that need character data). */
          onKeyEvent?: (instance: CodeMirror, event: Event) => boolean;
      
          /** Half - period in milliseconds used for cursor blinking. The default blink rate is 530ms. */
          cursorBlinkRate?: number;
      
          /** Determines the height of the cursor. Default is 1 , meaning it spans the whole height of the line.
          For some fonts (and by some tastes) a smaller height (for example 0.85),
          which causes the cursor to not reach all the way to the bottom of the line, looks better */
          cursorHeight?: number;
      
          /** Highlighting is done by a pseudo background - thread that will work for workTime milliseconds,
          and then use timeout to sleep for workDelay milliseconds.
          The defaults are 200 and 300, you can change these options to make the highlighting more or less aggressive. */
          workTime?: number;
      
          /** See workTime. */
          workDelay?: number;
      
          /** Indicates how quickly CodeMirror should poll its input textarea for changes(when focused).
          Most input is captured by events, but some things, like IME input on some browsers, don't generate events that allow CodeMirror to properly detect it.
          Thus, it polls. Default is 100 milliseconds. */
          pollInterval?: number
      
              /** By default, CodeMirror will combine adjacent tokens into a single span if they have the same class.
              This will result in a simpler DOM tree, and thus perform better. With some kinds of styling(such as rounded corners),
              this will change the way the document looks. You can set this option to false to disable this behavior. */
              flattenSpans?: boolean;
      
          /** When highlighting long lines, in order to stay responsive, the editor will give up and simply style
          the rest of the line as plain text when it reaches a certain position. The default is 10000.
          You can set this to Infinity to turn off this behavior. */
          maxHighlightLength?: number;
      
          /** Specifies the amount of lines that are rendered above and below the part of the document that's currently scrolled into view.
          This affects the amount of updates needed when scrolling, and the amount of work that such an update does.
          You should usually leave it at its default, 10. Can be set to Infinity to make sure the whole document is always rendered,
          and thus the browser's text search works on it. This will have bad effects on performance of big documents. */
          viewportMargin?: number;
        }
      
        export interface TextMarkerOptions {
          /** Assigns a CSS class to the marked stretch of text. */
          className?: string;
      
          /** Determines whether text inserted on the left of the marker will end up inside or outside of it. */
          inclusiveLeft?: boolean;
      
          /** Like inclusiveLeft , but for the right side. */
          inclusiveRight?: boolean;
      
          /** Atomic ranges act as a single unit when cursor movement is concerned i.e. it is impossible to place the cursor inside of them.
          In atomic ranges, inclusiveLeft and inclusiveRight have a different meaning they will prevent the cursor from being placed
          respectively directly before and directly after the range. */
          atomic?: boolean;
      
          /** Collapsed ranges do not show up in the display.Setting a range to be collapsed will automatically make it atomic. */
          collapsed?: boolean;
      
          /** When enabled, will cause the mark to clear itself whenever the cursor enters its range.
          This is mostly useful for text - replacement widgets that need to 'snap open' when the user tries to edit them.
          The "clear" event fired on the range handle can be used to be notified when this happens. */
          clearOnEnter?: boolean;
      
          /** Use a given node to display this range.Implies both collapsed and atomic.
          The given DOM node must be an inline element(as opposed to a block element). */
          replacedWith?: HTMLElement;
      
          /** A read - only span can, as long as it is not cleared, not be modified except by calling setValue to reset the whole document.
          Note: adding a read - only span currently clears the undo history of the editor,
          because existing undo events being partially nullified by read - only spans would corrupt the history (in the current implementation). */
          readOnly?: boolean;
      
          /** When set to true (default is false), adding this marker will create an event in the undo history that can be individually undone(clearing the marker). */
          addToHistory?: boolean;
      
          /** Can be used to specify an extra CSS class to be applied to the leftmost span that is part of the marker. */
          startStyle?: string;
      
          /** Equivalent to startStyle, but for the rightmost span. */
          endStyle?: string;
      
          /** When the target document is linked to other documents, you can set shared to true to make the marker appear in all documents.
          By default, a marker appears only in its target document. */
          shared?: boolean;
        }
      }
    • github.d.ts
      /**
       * See https://github.com/michael/github
       */
      declare class Github {
      
        constructor(config: {
          username?: string;
          password?: string;
          token?: string;
          auth?: string;
        });
      
        constructor(config: {
          token?: string;
          auth?: string;
        });
      
        getRepo(username?: string, password?: string): Github.Repo;
      
      }
      
      declare module Github {
      
        export interface Repo {
      
          show(callback: (error: Error, repo: any) => void): void;
      
          deleteRepo(callback: (error: Error, res: any) => void): void;
      
          contents(branch: string, pathToDir: string, callback: (err: Error, contents: any) => void, sync?: boolean);
      
          fork(callback: (err: Error) => void): void;
          
          branch(oldBranchName: string, newBranchName: string, callback: (err: Error) => void);
      
        	createPullRequest(pull: PullRequest, callback: (err: Error, pullRequest: any) => void);
      
          listBranches(callback: (error: Error, braches: any) => void);
      
          write(branch: string, pathToFile: string, contents: string, commitMessage: string, callback: (err: Error) => void);
          
          read(master: string, pathToFile: string, callback: (err, data) => void);
          
          move(branch: string, pathToFile: string, pathToNewFile: string, callback: (err: Error) => void);
      
          remove(branch: string, pathToFile: string, callback: (err: Error) => void);
          
          /** also try branch like master?recursive=true */
          getTree(branch: string, callback: (err: Error, tree: any) => void);
          
          getSha(branch: string, pathToFile: string, callback: (err, sha) => void);
          
      
        }
        
        export interface PullRequest {
          title: string;
          body: string;
          base: string;
          head: string;
        }
      
      }
    • knockout.d.ts
      // Type definitions for Knockout 2.3
      // Project: http://knockoutjs.com
      // Definitions by: Boris Yankov <https://github.com/borisyankov/>
      // Definitions: https://github.com/borisyankov/DefinitelyTyped
      
      
      declare module ko {
      
        export module utils {
      
          //////////////////////////////////
          // utils.domManipulation.js
          //////////////////////////////////
      
          export function simpleHtmlParse(html: string): any[];
      
          export function jQueryHtmlParse(html: string): any[];
      
          export function parseHtmlFragment(html: string): any[];
      
          export function setHtml(node: Element, html: string): void;
      
          export function setHtml(node: Element, html: () => string): void;
      
          //////////////////////////////////
          // utils.domData.js
          //////////////////////////////////
      
          export module domData {
            export function get(node: Element, key: string): any;
      
            export function set(node: Element, key: string, value: any): void;
      
            export function getAll(node: Element, createIfNotFound: boolean): any;
      
            export function clear(node: Element): boolean;
          }
      
          //////////////////////////////////
          // utils.domNodeDisposal.js
          //////////////////////////////////
      
          export module domNodeDisposal {
            export function addDisposeCallback(node: Element, callback: Function): void;
      
            export function removeDisposeCallback(node: Element, callback: Function): void;
      
            export function cleanNode(node: Element): Element;
      
            export function removeNode(node: Element): void;
          }
      
          //////////////////////////////////
          // utils.js
          //////////////////////////////////
      
          export var fieldsIncludedWithJsonPost: any[];
      
          export function compareArrays<T>(a: T[], b: T[]): Array<KnockoutArrayChange<T>>;
      
          export function arrayForEach<T>(array: T[], action: (item: T) => void): void;
      
          export function arrayIndexOf<T>(array: T[], item: T): number;
      
          export function arrayFirst<T>(array: T[], predicate: (item: T) => boolean, predicateOwner?: any): T;
      
          export function arrayRemoveItem(array: any[], itemToRemove: any): void;
      
          export function arrayGetDistinctValues<T>(array: T[]): T[];
      
          export function arrayMap<T, U>(array: T[], mapping: (item: T) => U): U[];
      
          export function arrayFilter<T>(array: T[], predicate: (item: T) => boolean): T[];
      
          export function arrayPushAll<T>(array: T[], valuesToPush: T[]): T[];
      
          export function arrayPushAll<T>(array: ObservableArray<T>, valuesToPush: T[]): T[];
      
          export function extend(target: Object, source: Object): Object;
      
          export function emptyDomNode(domNode: HTMLElement): void;
      
          export function moveCleanedNodesToContainerElement(nodes: any[]): HTMLElement;
      
          export function cloneNodes(nodesArray: any[], shouldCleanNodes: boolean): any[];
      
          export function setDomNodeChildren(domNode: any, childNodes: any[]): void;
      
          export function replaceDomNodes(nodeToReplaceOrNodeArray: any, newNodesArray: any[]): void;
      
          export function setOptionNodeSelectionState(optionNode: any, isSelected: boolean): void;
      
          export function stringTrim(str: string): string;
      
          export function stringTokenize(str: string, delimiter: string): string;
      
          export function stringStartsWith(str: string, startsWith: string): string;
      
          export function domNodeIsContainedBy(node: any, containedByNode: any): boolean;
      
          export function domNodeIsAttachedToDocument(node: any): boolean;
      
          export function tagNameLower(element: any): string;
      
          export function registerEventHandler(element: any, eventType: any, handler: Function): void;
      
          export function triggerEvent(element: any, eventType: any): void;
      
          export function unwrapObservable<T>(value: Observable<T>): T;
      
          export function peekObservable<T>(value: Observable<T>): T;
      
          export function toggleDomNodeCssClass(node: any, className: string, shouldHaveClass: boolean): void;
      
          //setTextContent(element: any, textContent: string): void; // NOT PART OF THE MINIFIED API SURFACE (ONLY IN knockout-{version}.debug.js) https://github.com/SteveSanderson/knockout/issues/670
      
          export function setElementName(element: any, name: string): void;
      
          export function forceRefresh(node: any): void;
      
          export function ensureSelectElementIsRenderedCorrectly(selectElement: any): void;
      
          export function range(min: any, max: any): any;
      
          export function makeArray(arrayLikeObject: any): any[];
      
          export function getFormFields(form: any, fieldName: string): any[];
      
          export function parseJson(jsonString: string): any;
      
          export function stringifyJson(data: any, replacer: Function, space: string): string;
      
          export function postJson(urlOrForm: any, data: any, options: any): void;
      
          export var ieVersion: number;
      
          export var isIe6: boolean;
      
          export var isIe7: boolean;
        }
      
        export module memoization {
      
        }
      
        export module bindingHandlers {
      
          // Controlling text and appearance
          export var visible: BindingHandler;
          export var text: BindingHandler;
          export var html: BindingHandler;
          export var css: BindingHandler;
          export var style: BindingHandler;
          export var attr: BindingHandler;
      
          // Control Flow
          export var foreach: BindingHandler;
          export var ifnot: BindingHandler;
      
          /*export var if: BindingHandler;*/
          /*export var with: BindingHandler;*/
      
          // Working with form fields
          export var click: BindingHandler;
          export var event: BindingHandler;
          export var submit: BindingHandler;
          export var enable: BindingHandler;
          export var disable: BindingHandler;
          export var value: BindingHandler;
          export var hasfocus: BindingHandler;
          export var checked: BindingHandler;
          export var options: BindingHandler;
          export var selectedOptions: BindingHandler;
          export var uniqueName: BindingHandler;
      
          // Rendering templates
          export var template: BindingHandler;
        }
      
        export module virtualElements {
        }
      
        export module extenders {
          export function throttle(target: any, timeout: number): ko.Computed<any>;
          export function notify(target: any, notifyWhen: string): any;
        }
      
        export function applyBindings(viewModel: any, rootNode?: any): void;
        export function applyBindingsToDescendants(viewModel: any, rootNode: any): void;
        export function applyBindingsToNode(node: Element, options: any, viewModel: any): void;
      
        export interface subscribable<T> extends subscribable.CustomFunctions<T> {
          subscribe(callback: (newValue: T) => void, target?: any, event?: string): Disposable;
          subscribe<TEvent>(callback: (newValue: TEvent) => void, target: any, event: string): Disposable;
          extend(requestedExtenders: { [key: string]: any; }): subscribable<T>;
          getSubscriptionsCount(): number;
        }
      
        export module subscribable {
      
          export var fn: CustomFunctions<any>;
      
          export interface CustomFunctions<T> {
            notifySubscribers(valueToWrite: T, event?: string): void;
          }
      
        }
      
        export interface Disposable {
          dispose(): void;
        }
      
        export function observable<T>(value?: T): Observable<T>;
      
        export interface Observable<T> extends observable.CustomFunctions, subscribable<T> {
      
          (): T;
          (value: T): void;
      
          peek(): T;
          valueHasMutated(): void;
          valueWillMutate(): void;
          extend(requestedExtenders: { [key: string]: any; }): Observable<T>;
        }
      
        export module observable {
      
          export var fn: CustomFunctions;
      
          export interface CustomFunctions {
            equalityComparer(a: any, b: any): boolean;
          }
        }
      
      
      
        export function computed<T>(): Computed<T>;
        export function computed<T>(read: () => T, context?: any, options?: any): Computed<T>;
        export function computed<T>(definition: computed.Definition<T>): Computed<T>;
        export function computed(options?: any): Computed<any>;
      
        export interface Computed<T> extends subscribable<T> {
          (): T;
          (value: T): void;
      
          peek(): T;
          dispose(): void;
          isActive(): boolean;
          getDependenciesCount(): number;
          extend(requestedExtenders: { [key: string]: any; }): Computed<T>;
        }
      
        export module computed {
      
          export var fn: CustomFunctions;
      
          export interface CustomFunctions {
          }
      
          export interface Definition<T> {
            read(): T;
            write? (value: T): void;
            disposeWhenNodeIsRemoved?: Node;
            disposeWhen? (): boolean;
            owner?: any;
            deferEvaluation?: boolean;
          }
        }
      
      
      
        export function observableArray<T>(value?: T[]): ObservableArray<T>;
      
        export interface ObservableArray<T> extends Observable<T[]>, observableArray.CustomFunctions<T> {
        }
      
        export module observableArray {
      
          export var fn: CustomFunctions<any>;
      
          export interface CustomFunctions<T> {
            indexOf(searchElement: T, fromIndex?: number): number;
            slice(start: number, end?: number): T[];
            splice(start: number): T[];
            splice(start: number, deleteCount: number, ...items: T[]): T[];
            pop(): T;
            push(...items: T[]): void;
            shift(): T;
            unshift(...items: T[]): number;
            reverse(): T[];
            sort(): void;
            sort(compareFunction: (left: T, right: T) => number): void;
      
            // Ko specific
            replace(oldItem: T, newItem: T): void;
      
            remove(item: T): T[];
            remove(removeFunction: (item: T) => boolean): T[];
            removeAll(items: T[]): T[];
            removeAll(): T[];
      
            destroy(item: T): void;
            destroyAll(items: T[]): void;
            destroyAll(): void;
          }
        }
      
        export function contextFor(node: any): any;
        export function isSubscribable(instance: any): boolean;
        export function toJSON(viewModel: any, replacer?: Function, space?: any): string;
        export function toJS(viewModel: any): any;
        export function isObservable(instance: any): boolean;
        export function isWriteableObservable(instance: any): boolean;
        export function isComputed(instance: any): boolean;
        export function dataFor(node: any): any;
        export function removeNode(node: Element): void;
        export function cleanNode(node: Element): Element;
        export function renderTemplate(template: Function, viewModel: any, options?: any, target?: any, renderMode?: any): any;
        export function renderTemplate(template: string, viewModel: any, options?: any, target?: any, renderMode?: any): any;
        export function unwrap(value: any): any;
      
        export module templateSources /* KnockoutTemplateSources */ {
      
        }
      
      
        export class templateEngine extends nativeTemplateEngine {
      
          createJavaScriptEvaluatorBlock(script: string): string;
      
          makeTemplateSource(template: any, templateDocument?: Document): any;
      
          renderTemplate(template: any, bindingContext: BindingContext, options: Object, templateDocument: Document): any;
      
          isTemplateRewritten(template: any, templateDocument: Document): boolean;
      
          rewriteTemplate(template: any, rewriterCallback: Function, templateDocument: Document): void;
      
        }
      
        //////////////////////////////////
        // templateRewriting.js
        //////////////////////////////////
      
        export module templateRewriting {
      
          export function ensureTemplateIsRewritten(template: Node, templateEngine: templateEngine, templateDocument: Document): any;
          export function ensureTemplateIsRewritten(template: string, templateEngine: templateEngine, templateDocument: Document): any;
      
          export function memoizeBindingAttributeSyntax(htmlString: string, templateEngine: templateEngine): any;
      
          export function applyMemoizedBindingsToNextSibling(bindings: any, nodeName: string): string;
        }
      
        //////////////////////////////////
        // nativeTemplateEngine.js
        //////////////////////////////////
      
        export class nativeTemplateEngine {
          renderTemplateSource(templateSource: Object, bindingContext?: BindingContext, options?: Object): any[];
        }
      
        //////////////////////////////////
        // jqueryTmplTemplateEngine.js
        //////////////////////////////////
      
        export class jqueryTmplTemplateEngine extends templateEngine {
      
          renderTemplateSource(templateSource: Object, bindingContext: BindingContext, options: Object): Node[];
      
          createJavaScriptEvaluatorBlock(script: string): string;
      
          addTemplate(templateName: string, templateMarkup: string): void;
      
        }
      
        //////////////////////////////////
        // templating.js
        //////////////////////////////////
      
        export function setTemplateEngine(templateEngine: nativeTemplateEngine): void;
      
        export function renderTemplate(template: Function, dataOrBindingContext: BindingContext, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
        export function renderTemplate(template: any, dataOrBindingContext: BindingContext, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
        export function renderTemplate(template: Function, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
        export function renderTemplate(template: any, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
        export function renderTemplate(template: Function, dataOrBindingContext: BindingContext, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
        export function renderTemplate(template: any, dataOrBindingContext: BindingContext, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
        export function renderTemplate(template: Function, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
        export function renderTemplate(template: any, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
      
        export function renderTemplateForEach(template: Function, arrayOrObservableArray: any[], options: Object, targetNode: Node, parentBindingContext: BindingContext): any;
        export function renderTemplateForEach(template: any, arrayOrObservableArray: any[], options: Object, targetNode: Node, parentBindingContext: BindingContext): any;
        export function renderTemplateForEach(template: Function, arrayOrObservableArray: Observable<any>, options: Object, targetNode: Node, parentBindingContext: BindingContext): any;
        export function renderTemplateForEach(template: any, arrayOrObservableArray: Observable<any>, options: Object, targetNode: Node, parentBindingContext: BindingContext): any;
      
        export module expressionRewriting {
          export var bindingRewriteValidators: any;
        }
      
        /////////////////////////////////
      
        export module bindingProvider {
      
        }
      
        /////////////////////////////////
        // selectExtensions.js
        /////////////////////////////////
      
        export module selectExtensions {
      
          export function readValue(element: HTMLElement): any;
      
          export function writeValue(element: HTMLElement, value: any): void;
        }
      
        export interface BindingContext {
          $parent: any;
          $parents: any[];
          $root: any;
          $data: any;
          $index?: number;
          $parentContext?: BindingContext;
      
          extend(properties: any): any;
          createChildContext(dataItemOrAccessor: any, dataItemAlias?: any, extendCallback?: Function): any;
        }
      
        export interface BindingHandler {
          init? (element: any, valueAccessor: () => any, allBindingsAccessor: () => any, viewModel: any, bindingContext: BindingContext): void;
          update? (element: any, valueAccessor: () => any, allBindingsAccessor: () => any, viewModel: any, bindingContext: BindingContext): void;
          options?: any;
        }
      
      }
      
      
      
      interface KnockoutMemoization {
          memoize(callback: () => string): string;
          unmemoize(memoId: string, callbackParams: any[]): boolean;
          unmemoizeDomNodeAndDescendants(domNode: any, extraCallbackParamsArray: any[]): boolean;
          parseMemoText(memoText: string): string;
      }
      
      interface KnockoutVirtualElement {}
      
      interface KnockoutVirtualElements {
      	allowedBindings: { [bindingName: string]: boolean; };
          emptyNode(node: KnockoutVirtualElement ): void;
          firstChild(node: KnockoutVirtualElement ): KnockoutVirtualElement;
      	insertAfter( container: KnockoutVirtualElement, nodeToInsert: HTMLElement, insertAfter: HTMLElement ): void;
          nextSibling(node: KnockoutVirtualElement): HTMLElement;
          prepend(node: KnockoutVirtualElement, toInsert: HTMLElement ): void;
          setDomNodeChildren(node: KnockoutVirtualElement, newChildren: { length: number;[index: number]: HTMLElement; } ): void;
          childNodes(node: KnockoutVirtualElement ): HTMLElement[];
      }
      
      
      
      interface KnockoutArrayChange<T> {
          status: string;
          value: T;
          index: number;
      }
      
      //////////////////////////////////
      // templateSources.js
      //////////////////////////////////
      
      interface KnockoutTemplateSourcesDomElement {
      
          text(valueToWrite?: any): any;
      
          data(key: string, valueToWrite?: any): any;
      }
      
      
      interface KnockoutTemplateSources {
      
        domElement: KnockoutTemplateSourcesDomElement;
      
        anonymousTemplate: {
      
          prototype: KnockoutTemplateSourcesDomElement;
      
          new (element: Element): KnockoutTemplateSourcesDomElement;
        };
      }
      
      
      
      declare module "knockout" {
      	export = ko;
      }
      
    • marked.d.ts
      declare var marked;
    • typescriptServices.d.ts
      /*! *****************************************************************************
      Copyright (c) Microsoft Corporation. All rights reserved. 
      Licensed under the Apache License, Version 2.0 (the "License"); you may not use
      this file except in compliance with the License. You may obtain a copy of the
      License at http://www.apache.org/licenses/LICENSE-2.0  
       
      THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
      KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
      WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
      MERCHANTABLITY OR NON-INFRINGEMENT. 
       
      See the Apache Version 2.0 License for specific language governing permissions
      and limitations under the License.
      ***************************************************************************** */
      
      declare module ts {
          interface Map<T> {
              [index: string]: T;
          }
          interface TextRange {
              pos: number;
              end: number;
          }
          const enum SyntaxKind {
              Unknown = 0,
              EndOfFileToken = 1,
              SingleLineCommentTrivia = 2,
              MultiLineCommentTrivia = 3,
              NewLineTrivia = 4,
              WhitespaceTrivia = 5,
              ConflictMarkerTrivia = 6,
              NumericLiteral = 7,
              StringLiteral = 8,
              RegularExpressionLiteral = 9,
              NoSubstitutionTemplateLiteral = 10,
              TemplateHead = 11,
              TemplateMiddle = 12,
              TemplateTail = 13,
              OpenBraceToken = 14,
              CloseBraceToken = 15,
              OpenParenToken = 16,
              CloseParenToken = 17,
              OpenBracketToken = 18,
              CloseBracketToken = 19,
              DotToken = 20,
              DotDotDotToken = 21,
              SemicolonToken = 22,
              CommaToken = 23,
              LessThanToken = 24,
              GreaterThanToken = 25,
              LessThanEqualsToken = 26,
              GreaterThanEqualsToken = 27,
              EqualsEqualsToken = 28,
              ExclamationEqualsToken = 29,
              EqualsEqualsEqualsToken = 30,
              ExclamationEqualsEqualsToken = 31,
              EqualsGreaterThanToken = 32,
              PlusToken = 33,
              MinusToken = 34,
              AsteriskToken = 35,
              SlashToken = 36,
              PercentToken = 37,
              PlusPlusToken = 38,
              MinusMinusToken = 39,
              LessThanLessThanToken = 40,
              GreaterThanGreaterThanToken = 41,
              GreaterThanGreaterThanGreaterThanToken = 42,
              AmpersandToken = 43,
              BarToken = 44,
              CaretToken = 45,
              ExclamationToken = 46,
              TildeToken = 47,
              AmpersandAmpersandToken = 48,
              BarBarToken = 49,
              QuestionToken = 50,
              ColonToken = 51,
              AtToken = 52,
              EqualsToken = 53,
              PlusEqualsToken = 54,
              MinusEqualsToken = 55,
              AsteriskEqualsToken = 56,
              SlashEqualsToken = 57,
              PercentEqualsToken = 58,
              LessThanLessThanEqualsToken = 59,
              GreaterThanGreaterThanEqualsToken = 60,
              GreaterThanGreaterThanGreaterThanEqualsToken = 61,
              AmpersandEqualsToken = 62,
              BarEqualsToken = 63,
              CaretEqualsToken = 64,
              Identifier = 65,
              BreakKeyword = 66,
              CaseKeyword = 67,
              CatchKeyword = 68,
              ClassKeyword = 69,
              ConstKeyword = 70,
              ContinueKeyword = 71,
              DebuggerKeyword = 72,
              DefaultKeyword = 73,
              DeleteKeyword = 74,
              DoKeyword = 75,
              ElseKeyword = 76,
              EnumKeyword = 77,
              ExportKeyword = 78,
              ExtendsKeyword = 79,
              FalseKeyword = 80,
              FinallyKeyword = 81,
              ForKeyword = 82,
              FunctionKeyword = 83,
              IfKeyword = 84,
              ImportKeyword = 85,
              InKeyword = 86,
              InstanceOfKeyword = 87,
              NewKeyword = 88,
              NullKeyword = 89,
              ReturnKeyword = 90,
              SuperKeyword = 91,
              SwitchKeyword = 92,
              ThisKeyword = 93,
              ThrowKeyword = 94,
              TrueKeyword = 95,
              TryKeyword = 96,
              TypeOfKeyword = 97,
              VarKeyword = 98,
              VoidKeyword = 99,
              WhileKeyword = 100,
              WithKeyword = 101,
              ImplementsKeyword = 102,
              InterfaceKeyword = 103,
              LetKeyword = 104,
              PackageKeyword = 105,
              PrivateKeyword = 106,
              ProtectedKeyword = 107,
              PublicKeyword = 108,
              StaticKeyword = 109,
              YieldKeyword = 110,
              AsKeyword = 111,
              AnyKeyword = 112,
              BooleanKeyword = 113,
              ConstructorKeyword = 114,
              DeclareKeyword = 115,
              GetKeyword = 116,
              ModuleKeyword = 117,
              RequireKeyword = 118,
              NumberKeyword = 119,
              SetKeyword = 120,
              StringKeyword = 121,
              SymbolKeyword = 122,
              TypeKeyword = 123,
              FromKeyword = 124,
              OfKeyword = 125,
              QualifiedName = 126,
              ComputedPropertyName = 127,
              TypeParameter = 128,
              Parameter = 129,
              Decorator = 130,
              PropertySignature = 131,
              PropertyDeclaration = 132,
              MethodSignature = 133,
              MethodDeclaration = 134,
              Constructor = 135,
              GetAccessor = 136,
              SetAccessor = 137,
              CallSignature = 138,
              ConstructSignature = 139,
              IndexSignature = 140,
              TypeReference = 141,
              FunctionType = 142,
              ConstructorType = 143,
              TypeQuery = 144,
              TypeLiteral = 145,
              ArrayType = 146,
              TupleType = 147,
              UnionType = 148,
              ParenthesizedType = 149,
              ObjectBindingPattern = 150,
              ArrayBindingPattern = 151,
              BindingElement = 152,
              ArrayLiteralExpression = 153,
              ObjectLiteralExpression = 154,
              PropertyAccessExpression = 155,
              ElementAccessExpression = 156,
              CallExpression = 157,
              NewExpression = 158,
              TaggedTemplateExpression = 159,
              TypeAssertionExpression = 160,
              ParenthesizedExpression = 161,
              FunctionExpression = 162,
              ArrowFunction = 163,
              DeleteExpression = 164,
              TypeOfExpression = 165,
              VoidExpression = 166,
              PrefixUnaryExpression = 167,
              PostfixUnaryExpression = 168,
              BinaryExpression = 169,
              ConditionalExpression = 170,
              TemplateExpression = 171,
              YieldExpression = 172,
              SpreadElementExpression = 173,
              ClassExpression = 174,
              OmittedExpression = 175,
              TemplateSpan = 176,
              HeritageClauseElement = 177,
              SemicolonClassElement = 178,
              Block = 179,
              VariableStatement = 180,
              EmptyStatement = 181,
              ExpressionStatement = 182,
              IfStatement = 183,
              DoStatement = 184,
              WhileStatement = 185,
              ForStatement = 186,
              ForInStatement = 187,
              ForOfStatement = 188,
              ContinueStatement = 189,
              BreakStatement = 190,
              ReturnStatement = 191,
              WithStatement = 192,
              SwitchStatement = 193,
              LabeledStatement = 194,
              ThrowStatement = 195,
              TryStatement = 196,
              DebuggerStatement = 197,
              VariableDeclaration = 198,
              VariableDeclarationList = 199,
              FunctionDeclaration = 200,
              ClassDeclaration = 201,
              InterfaceDeclaration = 202,
              TypeAliasDeclaration = 203,
              EnumDeclaration = 204,
              ModuleDeclaration = 205,
              ModuleBlock = 206,
              CaseBlock = 207,
              ImportEqualsDeclaration = 208,
              ImportDeclaration = 209,
              ImportClause = 210,
              NamespaceImport = 211,
              NamedImports = 212,
              ImportSpecifier = 213,
              ExportAssignment = 214,
              ExportDeclaration = 215,
              NamedExports = 216,
              ExportSpecifier = 217,
              MissingDeclaration = 218,
              ExternalModuleReference = 219,
              CaseClause = 220,
              DefaultClause = 221,
              HeritageClause = 222,
              CatchClause = 223,
              PropertyAssignment = 224,
              ShorthandPropertyAssignment = 225,
              EnumMember = 226,
              SourceFile = 227,
              SyntaxList = 228,
              Count = 229,
              FirstAssignment = 53,
              LastAssignment = 64,
              FirstReservedWord = 66,
              LastReservedWord = 101,
              FirstKeyword = 66,
              LastKeyword = 125,
              FirstFutureReservedWord = 102,
              LastFutureReservedWord = 110,
              FirstTypeNode = 141,
              LastTypeNode = 149,
              FirstPunctuation = 14,
              LastPunctuation = 64,
              FirstToken = 0,
              LastToken = 125,
              FirstTriviaToken = 2,
              LastTriviaToken = 6,
              FirstLiteralToken = 7,
              LastLiteralToken = 10,
              FirstTemplateToken = 10,
              LastTemplateToken = 13,
              FirstBinaryOperator = 24,
              LastBinaryOperator = 64,
              FirstNode = 126,
          }
          const enum NodeFlags {
              Export = 1,
              Ambient = 2,
              Public = 16,
              Private = 32,
              Protected = 64,
              Static = 128,
              Default = 256,
              MultiLine = 512,
              Synthetic = 1024,
              DeclarationFile = 2048,
              Let = 4096,
              Const = 8192,
              OctalLiteral = 16384,
              ExportContext = 32768,
              Modifier = 499,
              AccessibilityModifier = 112,
              BlockScoped = 12288,
          }
          interface Node extends TextRange {
              kind: SyntaxKind;
              flags: NodeFlags;
              decorators?: NodeArray<Decorator>;
              modifiers?: ModifiersArray;
              parent?: Node;
          }
          interface NodeArray<T> extends Array<T>, TextRange {
              hasTrailingComma?: boolean;
          }
          interface ModifiersArray extends NodeArray<Node> {
              flags: number;
          }
          interface Identifier extends PrimaryExpression {
              text: string;
              originalKeywordKind?: SyntaxKind;
          }
          interface QualifiedName extends Node {
              left: EntityName;
              right: Identifier;
          }
          type EntityName = Identifier | QualifiedName;
          type DeclarationName = Identifier | LiteralExpression | ComputedPropertyName | BindingPattern;
          interface Declaration extends Node {
              _declarationBrand: any;
              name?: DeclarationName;
          }
          interface ComputedPropertyName extends Node {
              expression: Expression;
          }
          interface Decorator extends Node {
              expression: LeftHandSideExpression;
          }
          interface TypeParameterDeclaration extends Declaration {
              name: Identifier;
              constraint?: TypeNode;
              expression?: Expression;
          }
          interface SignatureDeclaration extends Declaration {
              typeParameters?: NodeArray<TypeParameterDeclaration>;
              parameters: NodeArray<ParameterDeclaration>;
              type?: TypeNode;
          }
          interface VariableDeclaration extends Declaration {
              parent?: VariableDeclarationList;
              name: Identifier | BindingPattern;
              type?: TypeNode;
              initializer?: Expression;
          }
          interface VariableDeclarationList extends Node {
              declarations: NodeArray<VariableDeclaration>;
          }
          interface ParameterDeclaration extends Declaration {
              dotDotDotToken?: Node;
              name: Identifier | BindingPattern;
              questionToken?: Node;
              type?: TypeNode;
              initializer?: Expression;
          }
          interface BindingElement extends Declaration {
              propertyName?: Identifier;
              dotDotDotToken?: Node;
              name: Identifier | BindingPattern;
              initializer?: Expression;
          }
          interface PropertyDeclaration extends Declaration, ClassElement {
              name: DeclarationName;
              questionToken?: Node;
              type?: TypeNode;
              initializer?: Expression;
          }
          interface ObjectLiteralElement extends Declaration {
              _objectLiteralBrandBrand: any;
          }
          interface PropertyAssignment extends ObjectLiteralElement {
              _propertyAssignmentBrand: any;
              name: DeclarationName;
              questionToken?: Node;
              initializer: Expression;
          }
          interface ShorthandPropertyAssignment extends ObjectLiteralElement {
              name: Identifier;
              questionToken?: Node;
          }
          interface VariableLikeDeclaration extends Declaration {
              propertyName?: Identifier;
              dotDotDotToken?: Node;
              name: DeclarationName;
              questionToken?: Node;
              type?: TypeNode;
              initializer?: Expression;
          }
          interface BindingPattern extends Node {
              elements: NodeArray<BindingElement>;
          }
          /**
           * Several node kinds share function-like features such as a signature,
           * a name, and a body. These nodes should extend FunctionLikeDeclaration.
           * Examples:
           *  FunctionDeclaration
           *  MethodDeclaration
           *  AccessorDeclaration
           */
          interface FunctionLikeDeclaration extends SignatureDeclaration {
              _functionLikeDeclarationBrand: any;
              asteriskToken?: Node;
              questionToken?: Node;
              body?: Block | Expression;
          }
          interface FunctionDeclaration extends FunctionLikeDeclaration, Statement {
              name?: Identifier;
              body?: Block;
          }
          interface MethodDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement {
              body?: Block;
          }
          interface ConstructorDeclaration extends FunctionLikeDeclaration, ClassElement {
              body?: Block;
          }
          interface SemicolonClassElement extends ClassElement {
              _semicolonClassElementBrand: any;
          }
          interface AccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement {
              _accessorDeclarationBrand: any;
              body: Block;
          }
          interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement {
              _indexSignatureDeclarationBrand: any;
          }
          interface TypeNode extends Node {
              _typeNodeBrand: any;
          }
          interface FunctionOrConstructorTypeNode extends TypeNode, SignatureDeclaration {
              _functionOrConstructorTypeNodeBrand: any;
          }
          interface TypeReferenceNode extends TypeNode {
              typeName: EntityName;
              typeArguments?: NodeArray<TypeNode>;
          }
          interface TypeQueryNode extends TypeNode {
              exprName: EntityName;
          }
          interface TypeLiteralNode extends TypeNode, Declaration {
              members: NodeArray<Node>;
          }
          interface ArrayTypeNode extends TypeNode {
              elementType: TypeNode;
          }
          interface TupleTypeNode extends TypeNode {
              elementTypes: NodeArray<TypeNode>;
          }
          interface UnionTypeNode extends TypeNode {
              types: NodeArray<TypeNode>;
          }
          interface ParenthesizedTypeNode extends TypeNode {
              type: TypeNode;
          }
          interface StringLiteral extends LiteralExpression, TypeNode {
              _stringLiteralBrand: any;
          }
          interface Expression extends Node {
              _expressionBrand: any;
              contextualType?: Type;
          }
          interface UnaryExpression extends Expression {
              _unaryExpressionBrand: any;
          }
          interface PrefixUnaryExpression extends UnaryExpression {
              operator: SyntaxKind;
              operand: UnaryExpression;
          }
          interface PostfixUnaryExpression extends PostfixExpression {
              operand: LeftHandSideExpression;
              operator: SyntaxKind;
          }
          interface PostfixExpression extends UnaryExpression {
              _postfixExpressionBrand: any;
          }
          interface LeftHandSideExpression extends PostfixExpression {
              _leftHandSideExpressionBrand: any;
          }
          interface MemberExpression extends LeftHandSideExpression {
              _memberExpressionBrand: any;
          }
          interface PrimaryExpression extends MemberExpression {
              _primaryExpressionBrand: any;
          }
          interface DeleteExpression extends UnaryExpression {
              expression: UnaryExpression;
          }
          interface TypeOfExpression extends UnaryExpression {
              expression: UnaryExpression;
          }
          interface VoidExpression extends UnaryExpression {
              expression: UnaryExpression;
          }
          interface YieldExpression extends Expression {
              asteriskToken?: Node;
              expression: Expression;
          }
          interface BinaryExpression extends Expression {
              left: Expression;
              operatorToken: Node;
              right: Expression;
          }
          interface ConditionalExpression extends Expression {
              condition: Expression;
              questionToken: Node;
              whenTrue: Expression;
              colonToken: Node;
              whenFalse: Expression;
          }
          interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclaration {
              name?: Identifier;
              body: Block | Expression;
          }
          interface ArrowFunction extends Expression, FunctionLikeDeclaration {
              equalsGreaterThanToken: Node;
          }
          interface LiteralExpression extends PrimaryExpression {
              text: string;
              isUnterminated?: boolean;
              hasExtendedUnicodeEscape?: boolean;
          }
          interface TemplateExpression extends PrimaryExpression {
              head: LiteralExpression;
              templateSpans: NodeArray<TemplateSpan>;
          }
          interface TemplateSpan extends Node {
              expression: Expression;
              literal: LiteralExpression;
          }
          interface ParenthesizedExpression extends PrimaryExpression {
              expression: Expression;
          }
          interface ArrayLiteralExpression extends PrimaryExpression {
              elements: NodeArray<Expression>;
          }
          interface SpreadElementExpression extends Expression {
              expression: Expression;
          }
          interface ObjectLiteralExpression extends PrimaryExpression, Declaration {
              properties: NodeArray<ObjectLiteralElement>;
          }
          interface PropertyAccessExpression extends MemberExpression {
              expression: LeftHandSideExpression;
              dotToken: Node;
              name: Identifier;
          }
          interface ElementAccessExpression extends MemberExpression {
              expression: LeftHandSideExpression;
              argumentExpression?: Expression;
          }
          interface CallExpression extends LeftHandSideExpression {
              expression: LeftHandSideExpression;
              typeArguments?: NodeArray<TypeNode>;
              arguments: NodeArray<Expression>;
          }
          interface HeritageClauseElement extends TypeNode {
              expression: LeftHandSideExpression;
              typeArguments?: NodeArray<TypeNode>;
          }
          interface NewExpression extends CallExpression, PrimaryExpression {
          }
          interface TaggedTemplateExpression extends MemberExpression {
              tag: LeftHandSideExpression;
              template: LiteralExpression | TemplateExpression;
          }
          type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression;
          interface TypeAssertion extends UnaryExpression {
              type: TypeNode;
              expression: UnaryExpression;
          }
          interface Statement extends Node, ModuleElement {
              _statementBrand: any;
          }
          interface Block extends Statement {
              statements: NodeArray<Statement>;
          }
          interface VariableStatement extends Statement {
              declarationList: VariableDeclarationList;
          }
          interface ExpressionStatement extends Statement {
              expression: Expression;
          }
          interface IfStatement extends Statement {
              expression: Expression;
              thenStatement: Statement;
              elseStatement?: Statement;
          }
          interface IterationStatement extends Statement {
              statement: Statement;
          }
          interface DoStatement extends IterationStatement {
              expression: Expression;
          }
          interface WhileStatement extends IterationStatement {
              expression: Expression;
          }
          interface ForStatement extends IterationStatement {
              initializer?: VariableDeclarationList | Expression;
              condition?: Expression;
              incrementor?: Expression;
          }
          interface ForInStatement extends IterationStatement {
              initializer: VariableDeclarationList | Expression;
              expression: Expression;
          }
          interface ForOfStatement extends IterationStatement {
              initializer: VariableDeclarationList | Expression;
              expression: Expression;
          }
          interface BreakOrContinueStatement extends Statement {
              label?: Identifier;
          }
          interface ReturnStatement extends Statement {
              expression?: Expression;
          }
          interface WithStatement extends Statement {
              expression: Expression;
              statement: Statement;
          }
          interface SwitchStatement extends Statement {
              expression: Expression;
              caseBlock: CaseBlock;
          }
          interface CaseBlock extends Node {
              clauses: NodeArray<CaseOrDefaultClause>;
          }
          interface CaseClause extends Node {
              expression?: Expression;
              statements: NodeArray<Statement>;
          }
          interface DefaultClause extends Node {
              statements: NodeArray<Statement>;
          }
          type CaseOrDefaultClause = CaseClause | DefaultClause;
          interface LabeledStatement extends Statement {
              label: Identifier;
              statement: Statement;
          }
          interface ThrowStatement extends Statement {
              expression: Expression;
          }
          interface TryStatement extends Statement {
              tryBlock: Block;
              catchClause?: CatchClause;
              finallyBlock?: Block;
          }
          interface CatchClause extends Node {
              variableDeclaration: VariableDeclaration;
              block: Block;
          }
          interface ModuleElement extends Node {
              _moduleElementBrand: any;
          }
          interface ClassLikeDeclaration extends Declaration {
              name?: Identifier;
              typeParameters?: NodeArray<TypeParameterDeclaration>;
              heritageClauses?: NodeArray<HeritageClause>;
              members: NodeArray<ClassElement>;
          }
          interface ClassDeclaration extends ClassLikeDeclaration, Statement {
          }
          interface ClassExpression extends ClassLikeDeclaration, PrimaryExpression {
          }
          interface ClassElement extends Declaration {
              _classElementBrand: any;
          }
          interface InterfaceDeclaration extends Declaration, ModuleElement {
              name: Identifier;
              typeParameters?: NodeArray<TypeParameterDeclaration>;
              heritageClauses?: NodeArray<HeritageClause>;
              members: NodeArray<Declaration>;
          }
          interface HeritageClause extends Node {
              token: SyntaxKind;
              types?: NodeArray<HeritageClauseElement>;
          }
          interface TypeAliasDeclaration extends Declaration, ModuleElement {
              name: Identifier;
              type: TypeNode;
          }
          interface EnumMember extends Declaration {
              name: DeclarationName;
              initializer?: Expression;
          }
          interface EnumDeclaration extends Declaration, ModuleElement {
              name: Identifier;
              members: NodeArray<EnumMember>;
          }
          interface ModuleDeclaration extends Declaration, ModuleElement {
              name: Identifier | LiteralExpression;
              body: ModuleBlock | ModuleDeclaration;
          }
          interface ModuleBlock extends Node, ModuleElement {
              statements: NodeArray<ModuleElement>;
          }
          interface ImportEqualsDeclaration extends Declaration, ModuleElement {
              name: Identifier;
              moduleReference: EntityName | ExternalModuleReference;
          }
          interface ExternalModuleReference extends Node {
              expression?: Expression;
          }
          interface ImportDeclaration extends ModuleElement {
              importClause?: ImportClause;
              moduleSpecifier: Expression;
          }
          interface ImportClause extends Declaration {
              name?: Identifier;
              namedBindings?: NamespaceImport | NamedImports;
          }
          interface NamespaceImport extends Declaration {
              name: Identifier;
          }
          interface ExportDeclaration extends Declaration, ModuleElement {
              exportClause?: NamedExports;
              moduleSpecifier?: Expression;
          }
          interface NamedImportsOrExports extends Node {
              elements: NodeArray<ImportOrExportSpecifier>;
          }
          type NamedImports = NamedImportsOrExports;
          type NamedExports = NamedImportsOrExports;
          interface ImportOrExportSpecifier extends Declaration {
              propertyName?: Identifier;
              name: Identifier;
          }
          type ImportSpecifier = ImportOrExportSpecifier;
          type ExportSpecifier = ImportOrExportSpecifier;
          interface ExportAssignment extends Declaration, ModuleElement {
              isExportEquals?: boolean;
              expression: Expression;
          }
          interface FileReference extends TextRange {
              fileName: string;
          }
          interface CommentRange extends TextRange {
              hasTrailingNewLine?: boolean;
              kind: SyntaxKind;
          }
          interface SourceFile extends Declaration {
              statements: NodeArray<ModuleElement>;
              endOfFileToken: Node;
              fileName: string;
              text: string;
              amdDependencies: {
                  path: string;
                  name: string;
              }[];
              amdModuleName: string;
              referencedFiles: FileReference[];
              hasNoDefaultLib: boolean;
              languageVersion: ScriptTarget;
          }
          interface ScriptReferenceHost {
              getCompilerOptions(): CompilerOptions;
              getSourceFile(fileName: string): SourceFile;
              getCurrentDirectory(): string;
          }
          interface WriteFileCallback {
              (fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void): void;
          }
          interface Program extends ScriptReferenceHost {
              /**
               * Get a list of files in the program
               */
              getSourceFiles(): SourceFile[];
              /**
               * Emits the JavaScript and declaration files.  If targetSourceFile is not specified, then
               * the JavaScript and declaration files will be produced for all the files in this program.
               * If targetSourceFile is specified, then only the JavaScript and declaration for that
               * specific file will be generated.
               *
               * If writeFile is not specified then the writeFile callback from the compiler host will be
               * used for writing the JavaScript and declaration files.  Otherwise, the writeFile parameter
               * will be invoked when writing the JavaScript and declaration files.
               */
              emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult;
              getSyntacticDiagnostics(sourceFile?: SourceFile): Diagnostic[];
              getGlobalDiagnostics(): Diagnostic[];
              getSemanticDiagnostics(sourceFile?: SourceFile): Diagnostic[];
              getDeclarationDiagnostics(sourceFile?: SourceFile): Diagnostic[];
              /**
               * Gets a type checker that can be used to semantically analyze source fils in the program.
               */
              getTypeChecker(): TypeChecker;
          }
          interface SourceMapSpan {
              /** Line number in the .js file. */
              emittedLine: number;
              /** Column number in the .js file. */
              emittedColumn: number;
              /** Line number in the .ts file. */
              sourceLine: number;
              /** Column number in the .ts file. */
              sourceColumn: number;
              /** Optional name (index into names array) associated with this span. */
              nameIndex?: number;
              /** .ts file (index into sources array) associated with this span */
              sourceIndex: number;
          }
          interface SourceMapData {
              sourceMapFilePath: string;
              jsSourceMappingURL: string;
              sourceMapFile: string;
              sourceMapSourceRoot: string;
              sourceMapSources: string[];
              inputSourceFileNames: string[];
              sourceMapNames?: string[];
              sourceMapMappings: string;
              sourceMapDecodedMappings: SourceMapSpan[];
          }
          /** Return code used by getEmitOutput function to indicate status of the function */
          enum ExitStatus {
              Success = 0,
              DiagnosticsPresent_OutputsSkipped = 1,
              DiagnosticsPresent_OutputsGenerated = 2,
          }
          interface EmitResult {
              emitSkipped: boolean;
              diagnostics: Diagnostic[];
          }
          interface TypeCheckerHost {
              getCompilerOptions(): CompilerOptions;
              getSourceFiles(): SourceFile[];
              getSourceFile(fileName: string): SourceFile;
          }
          interface TypeChecker {
              getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type;
              getDeclaredTypeOfSymbol(symbol: Symbol): Type;
              getPropertiesOfType(type: Type): Symbol[];
              getPropertyOfType(type: Type, propertyName: string): Symbol;
              getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];
              getIndexTypeOfType(type: Type, kind: IndexKind): Type;
              getReturnTypeOfSignature(signature: Signature): Type;
              getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
              getSymbolAtLocation(node: Node): Symbol;
              getShorthandAssignmentValueSymbol(location: Node): Symbol;
              getTypeAtLocation(node: Node): Type;
              typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
              symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
              getSymbolDisplayBuilder(): SymbolDisplayBuilder;
              getFullyQualifiedName(symbol: Symbol): string;
              getAugmentedPropertiesOfType(type: Type): Symbol[];
              getRootSymbols(symbol: Symbol): Symbol[];
              getContextualType(node: Expression): Type;
              getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature;
              getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature;
              isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
              isUndefinedSymbol(symbol: Symbol): boolean;
              isArgumentsSymbol(symbol: Symbol): boolean;
              getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
              isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean;
              getAliasedSymbol(symbol: Symbol): Symbol;
              getExportsOfModule(moduleSymbol: Symbol): Symbol[];
          }
          interface SymbolDisplayBuilder {
              buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
              buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
              buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
              buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
              buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
              buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void;
              buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
              buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
              buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
          }
          interface SymbolWriter {
              writeKeyword(text: string): void;
              writeOperator(text: string): void;
              writePunctuation(text: string): void;
              writeSpace(text: string): void;
              writeStringLiteral(text: string): void;
              writeParameter(text: string): void;
              writeSymbol(text: string, symbol: Symbol): void;
              writeLine(): void;
              increaseIndent(): void;
              decreaseIndent(): void;
              clear(): void;
              trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
          }
          const enum TypeFormatFlags {
              None = 0,
              WriteArrayAsGenericType = 1,
              UseTypeOfFunction = 2,
              NoTruncation = 4,
              WriteArrowStyleSignature = 8,
              WriteOwnNameForAnyLike = 16,
              WriteTypeArgumentsOfSignature = 32,
              InElementType = 64,
              UseFullyQualifiedType = 128,
          }
          const enum SymbolFormatFlags {
              None = 0,
              WriteTypeParametersOrArguments = 1,
              UseOnlyExternalAliasing = 2,
          }
          const enum SymbolFlags {
              FunctionScopedVariable = 1,
              BlockScopedVariable = 2,
              Property = 4,
              EnumMember = 8,
              Function = 16,
              Class = 32,
              Interface = 64,
              ConstEnum = 128,
              RegularEnum = 256,
              ValueModule = 512,
              NamespaceModule = 1024,
              TypeLiteral = 2048,
              ObjectLiteral = 4096,
              Method = 8192,
              Constructor = 16384,
              GetAccessor = 32768,
              SetAccessor = 65536,
              Signature = 131072,
              TypeParameter = 262144,
              TypeAlias = 524288,
              ExportValue = 1048576,
              ExportType = 2097152,
              ExportNamespace = 4194304,
              Alias = 8388608,
              Instantiated = 16777216,
              Merged = 33554432,
              Transient = 67108864,
              Prototype = 134217728,
              UnionProperty = 268435456,
              Optional = 536870912,
              ExportStar = 1073741824,
              Enum = 384,
              Variable = 3,
              Value = 107455,
              Type = 793056,
              Namespace = 1536,
              Module = 1536,
              Accessor = 98304,
              FunctionScopedVariableExcludes = 107454,
              BlockScopedVariableExcludes = 107455,
              ParameterExcludes = 107455,
              PropertyExcludes = 107455,
              EnumMemberExcludes = 107455,
              FunctionExcludes = 106927,
              ClassExcludes = 899583,
              InterfaceExcludes = 792992,
              RegularEnumExcludes = 899327,
              ConstEnumExcludes = 899967,
              ValueModuleExcludes = 106639,
              NamespaceModuleExcludes = 0,
              MethodExcludes = 99263,
              GetAccessorExcludes = 41919,
              SetAccessorExcludes = 74687,
              TypeParameterExcludes = 530912,
              TypeAliasExcludes = 793056,
              AliasExcludes = 8388608,
              ModuleMember = 8914931,
              ExportHasLocal = 944,
              HasLocals = 255504,
              HasExports = 1952,
              HasMembers = 6240,
              IsContainer = 262128,
              PropertyOrAccessor = 98308,
              Export = 7340032,
          }
          interface Symbol {
              flags: SymbolFlags;
              name: string;
              declarations?: Declaration[];
              members?: SymbolTable;
              exports?: SymbolTable;
              valueDeclaration?: Declaration;
          }
          interface SymbolTable {
              [index: string]: Symbol;
          }
          const enum TypeFlags {
              Any = 1,
              String = 2,
              Number = 4,
              Boolean = 8,
              Void = 16,
              Undefined = 32,
              Null = 64,
              Enum = 128,
              StringLiteral = 256,
              TypeParameter = 512,
              Class = 1024,
              Interface = 2048,
              Reference = 4096,
              Tuple = 8192,
              Union = 16384,
              Anonymous = 32768,
              ObjectLiteral = 131072,
              ESSymbol = 1048576,
              StringLike = 258,
              NumberLike = 132,
              ObjectType = 48128,
          }
          interface Type {
              flags: TypeFlags;
              symbol?: Symbol;
          }
          interface StringLiteralType extends Type {
              text: string;
          }
          interface ObjectType extends Type {
          }
          interface InterfaceType extends ObjectType {
              typeParameters: TypeParameter[];
          }
          interface InterfaceTypeWithBaseTypes extends InterfaceType {
              baseTypes: ObjectType[];
          }
          interface InterfaceTypeWithDeclaredMembers extends InterfaceType {
              declaredProperties: Symbol[];
              declaredCallSignatures: Signature[];
              declaredConstructSignatures: Signature[];
              declaredStringIndexType: Type;
              declaredNumberIndexType: Type;
          }
          interface TypeReference extends ObjectType {
              target: GenericType;
              typeArguments: Type[];
          }
          interface GenericType extends InterfaceType, TypeReference {
          }
          interface TupleType extends ObjectType {
              elementTypes: Type[];
              baseArrayType: TypeReference;
          }
          interface UnionType extends Type {
              types: Type[];
          }
          interface TypeParameter extends Type {
              constraint: Type;
          }
          const enum SignatureKind {
              Call = 0,
              Construct = 1,
          }
          interface Signature {
              declaration: SignatureDeclaration;
              typeParameters: TypeParameter[];
              parameters: Symbol[];
          }
          const enum IndexKind {
              String = 0,
              Number = 1,
          }
          interface DiagnosticMessage {
              key: string;
              category: DiagnosticCategory;
              code: number;
          }
          /**
           * A linked list of formatted diagnostic messages to be used as part of a multiline message.
           * It is built from the bottom up, leaving the head to be the "main" diagnostic.
           * While it seems that DiagnosticMessageChain is structurally similar to DiagnosticMessage,
           * the difference is that messages are all preformatted in DMC.
           */
          interface DiagnosticMessageChain {
              messageText: string;
              category: DiagnosticCategory;
              code: number;
              next?: DiagnosticMessageChain;
          }
          interface Diagnostic {
              file: SourceFile;
              start: number;
              length: number;
              messageText: string | DiagnosticMessageChain;
              category: DiagnosticCategory;
              code: number;
          }
          enum DiagnosticCategory {
              Warning = 0,
              Error = 1,
              Message = 2,
          }
          interface CompilerOptions {
              allowNonTsExtensions?: boolean;
              charset?: string;
              declaration?: boolean;
              diagnostics?: boolean;
              emitBOM?: boolean;
              help?: boolean;
              listFiles?: boolean;
              locale?: string;
              mapRoot?: string;
              module?: ModuleKind;
              noEmit?: boolean;
              noEmitOnError?: boolean;
              noErrorTruncation?: boolean;
              noImplicitAny?: boolean;
              noLib?: boolean;
              noResolve?: boolean;
              out?: string;
              outDir?: string;
              preserveConstEnums?: boolean;
              project?: string;
              removeComments?: boolean;
              rootDir?: string;
              sourceMap?: boolean;
              sourceRoot?: string;
              suppressImplicitAnyIndexErrors?: boolean;
              target?: ScriptTarget;
              version?: boolean;
              watch?: boolean;
              separateCompilation?: boolean;
              emitDecoratorMetadata?: boolean;
              [option: string]: string | number | boolean;
          }
          const enum ModuleKind {
              None = 0,
              CommonJS = 1,
              AMD = 2,
              UMD = 3,
          }
          interface LineAndCharacter {
              line: number;
              character: number;
          }
          const enum ScriptTarget {
              ES3 = 0,
              ES5 = 1,
              ES6 = 2,
              Latest = 2,
          }
          interface ParsedCommandLine {
              options: CompilerOptions;
              fileNames: string[];
              errors: Diagnostic[];
          }
          interface CancellationToken {
              isCancellationRequested(): boolean;
          }
          interface CompilerHost {
              getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
              getDefaultLibFileName(options: CompilerOptions): string;
              getCancellationToken?(): CancellationToken;
              writeFile: WriteFileCallback;
              getCurrentDirectory(): string;
              getCanonicalFileName(fileName: string): string;
              useCaseSensitiveFileNames(): boolean;
              getNewLine(): string;
          }
          interface TextSpan {
              start: number;
              length: number;
          }
          interface TextChangeRange {
              span: TextSpan;
              newLength: number;
          }
      }
      declare module ts {
          interface System {
              args: string[];
              newLine: string;
              useCaseSensitiveFileNames: boolean;
              write(s: string): void;
              readFile(path: string, encoding?: string): string;
              writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
              watchFile?(path: string, callback: (path: string) => void): FileWatcher;
              resolvePath(path: string): string;
              fileExists(path: string): boolean;
              directoryExists(path: string): boolean;
              createDirectory(path: string): void;
              getExecutingFilePath(): string;
              getCurrentDirectory(): string;
              readDirectory(path: string, extension?: string): string[];
              getMemoryUsage?(): number;
              exit(exitCode?: number): void;
          }
          interface FileWatcher {
              close(): void;
          }
          var sys: System;
      }
      declare module ts {
          function tokenToString(t: SyntaxKind): string;
          function getPositionOfLineAndCharacter(sourceFile: SourceFile, line: number, character: number): number;
          function getLineAndCharacterOfPosition(sourceFile: SourceFile, position: number): LineAndCharacter;
          function isWhiteSpace(ch: number): boolean;
          function isLineBreak(ch: number): boolean;
          function getLeadingCommentRanges(text: string, pos: number): CommentRange[];
          function getTrailingCommentRanges(text: string, pos: number): CommentRange[];
          function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean;
          function isIdentifierPart(ch: number, languageVersion: ScriptTarget): boolean;
      }
      declare module ts {
          function getDefaultLibFileName(options: CompilerOptions): string;
          function textSpanEnd(span: TextSpan): number;
          function textSpanIsEmpty(span: TextSpan): boolean;
          function textSpanContainsPosition(span: TextSpan, position: number): boolean;
          function textSpanContainsTextSpan(span: TextSpan, other: TextSpan): boolean;
          function textSpanOverlapsWith(span: TextSpan, other: TextSpan): boolean;
          function textSpanOverlap(span1: TextSpan, span2: TextSpan): TextSpan;
          function textSpanIntersectsWithTextSpan(span: TextSpan, other: TextSpan): boolean;
          function textSpanIntersectsWith(span: TextSpan, start: number, length: number): boolean;
          function textSpanIntersectsWithPosition(span: TextSpan, position: number): boolean;
          function textSpanIntersection(span1: TextSpan, span2: TextSpan): TextSpan;
          function createTextSpan(start: number, length: number): TextSpan;
          function createTextSpanFromBounds(start: number, end: number): TextSpan;
          function textChangeRangeNewSpan(range: TextChangeRange): TextSpan;
          function textChangeRangeIsUnchanged(range: TextChangeRange): boolean;
          function createTextChangeRange(span: TextSpan, newLength: number): TextChangeRange;
          let unchangedTextChangeRange: TextChangeRange;
          /**
           * Called to merge all the changes that occurred across several versions of a script snapshot
           * into a single change.  i.e. if a user keeps making successive edits to a script we will
           * have a text change from V1 to V2, V2 to V3, ..., Vn.
           *
           * This function will then merge those changes into a single change range valid between V1 and
           * Vn.
           */
          function collapseTextChangeRangesAcrossMultipleVersions(changes: TextChangeRange[]): TextChangeRange;
      }
      declare module ts {
          function getNodeConstructor(kind: SyntaxKind): new () => Node;
          function createNode(kind: SyntaxKind): Node;
          function forEachChild<T>(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T;
          function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean): SourceFile;
          function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile;
      }
      declare module ts {
          /** The version of the TypeScript compiler release */
          const version: string;
          function findConfigFile(searchPath: string): string;
          function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost;
          function getPreEmitDiagnostics(program: Program): Diagnostic[];
          function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string;
          function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost): Program;
      }
      declare module ts {
          function parseCommandLine(commandLine: string[]): ParsedCommandLine;
          /**
            * Read tsconfig.json file
            * @param fileName The path to the config file
            */
          function readConfigFile(fileName: string): any;
          /**
            * Parse the contents of a config file (tsconfig.json).
            * @param json The contents of the config file to parse
            * @param basePath A root directory to resolve relative path entries in the config
            *    file to. e.g. outDir
            */
          function parseConfigFile(json: any, basePath?: string): ParsedCommandLine;
      }
      declare module ts {
          /** The version of the language service API */
          let servicesVersion: string;
          interface Node {
              getSourceFile(): SourceFile;
              getChildCount(sourceFile?: SourceFile): number;
              getChildAt(index: number, sourceFile?: SourceFile): Node;
              getChildren(sourceFile?: SourceFile): Node[];
              getStart(sourceFile?: SourceFile): number;
              getFullStart(): number;
              getEnd(): number;
              getWidth(sourceFile?: SourceFile): number;
              getFullWidth(): number;
              getLeadingTriviaWidth(sourceFile?: SourceFile): number;
              getFullText(sourceFile?: SourceFile): string;
              getText(sourceFile?: SourceFile): string;
              getFirstToken(sourceFile?: SourceFile): Node;
              getLastToken(sourceFile?: SourceFile): Node;
          }
          interface Symbol {
              getFlags(): SymbolFlags;
              getName(): string;
              getDeclarations(): Declaration[];
              getDocumentationComment(): SymbolDisplayPart[];
          }
          interface Type {
              getFlags(): TypeFlags;
              getSymbol(): Symbol;
              getProperties(): Symbol[];
              getProperty(propertyName: string): Symbol;
              getApparentProperties(): Symbol[];
              getCallSignatures(): Signature[];
              getConstructSignatures(): Signature[];
              getStringIndexType(): Type;
              getNumberIndexType(): Type;
          }
          interface Signature {
              getDeclaration(): SignatureDeclaration;
              getTypeParameters(): Type[];
              getParameters(): Symbol[];
              getReturnType(): Type;
              getDocumentationComment(): SymbolDisplayPart[];
          }
          interface SourceFile {
              getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
              getLineStarts(): number[];
              getPositionOfLineAndCharacter(line: number, character: number): number;
              update(newText: string, textChangeRange: TextChangeRange): SourceFile;
          }
          /**
           * Represents an immutable snapshot of a script at a specified time.Once acquired, the
           * snapshot is observably immutable. i.e. the same calls with the same parameters will return
           * the same values.
           */
          interface IScriptSnapshot {
              /** Gets a portion of the script snapshot specified by [start, end). */
              getText(start: number, end: number): string;
              /** Gets the length of this script snapshot. */
              getLength(): number;
              /**
               * Gets the TextChangeRange that describe how the text changed between this text and
               * an older version.  This information is used by the incremental parser to determine
               * what sections of the script need to be re-parsed.  'undefined' can be returned if the
               * change range cannot be determined.  However, in that case, incremental parsing will
               * not happen and the entire document will be re - parsed.
               */
              getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange;
          }
          module ScriptSnapshot {
              function fromString(text: string): IScriptSnapshot;
          }
          interface PreProcessedFileInfo {
              referencedFiles: FileReference[];
              importedFiles: FileReference[];
              isLibFile: boolean;
          }
          interface LanguageServiceHost {
              getCompilationSettings(): CompilerOptions;
              getNewLine?(): string;
              getScriptFileNames(): string[];
              getScriptVersion(fileName: string): string;
              getScriptSnapshot(fileName: string): IScriptSnapshot;
              getLocalizedDiagnosticMessages?(): any;
              getCancellationToken?(): CancellationToken;
              getCurrentDirectory(): string;
              getDefaultLibFileName(options: CompilerOptions): string;
              log?(s: string): void;
              trace?(s: string): void;
              error?(s: string): void;
          }
          interface LanguageService {
              cleanupSemanticCache(): void;
              getSyntacticDiagnostics(fileName: string): Diagnostic[];
              getSemanticDiagnostics(fileName: string): Diagnostic[];
              getCompilerOptionsDiagnostics(): Diagnostic[];
              getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[];
              getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[];
              getCompletionsAtPosition(fileName: string, position: number): CompletionInfo;
              getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails;
              getQuickInfoAtPosition(fileName: string, position: number): QuickInfo;
              getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan;
              getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan;
              getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems;
              getRenameInfo(fileName: string, position: number): RenameInfo;
              findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[];
              getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
              getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[];
              findReferences(fileName: string, position: number): ReferencedSymbol[];
              getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[];
              /** @deprecated */
              getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[];
              getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[];
              getNavigationBarItems(fileName: string): NavigationBarItem[];
              getOutliningSpans(fileName: string): OutliningSpan[];
              getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[];
              getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[];
              getIndentationAtPosition(fileName: string, position: number, options: EditorOptions): number;
              getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[];
              getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[];
              getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[];
              getEmitOutput(fileName: string): EmitOutput;
              getProgram(): Program;
              getSourceFile(fileName: string): SourceFile;
              dispose(): void;
          }
          interface ClassifiedSpan {
              textSpan: TextSpan;
              classificationType: string;
          }
          interface NavigationBarItem {
              text: string;
              kind: string;
              kindModifiers: string;
              spans: TextSpan[];
              childItems: NavigationBarItem[];
              indent: number;
              bolded: boolean;
              grayed: boolean;
          }
          interface TodoCommentDescriptor {
              text: string;
              priority: number;
          }
          interface TodoComment {
              descriptor: TodoCommentDescriptor;
              message: string;
              position: number;
          }
          class TextChange {
              span: TextSpan;
              newText: string;
          }
          interface RenameLocation {
              textSpan: TextSpan;
              fileName: string;
          }
          interface ReferenceEntry {
              textSpan: TextSpan;
              fileName: string;
              isWriteAccess: boolean;
          }
          interface DocumentHighlights {
              fileName: string;
              highlightSpans: HighlightSpan[];
          }
          module HighlightSpanKind {
              const none: string;
              const definition: string;
              const reference: string;
              const writtenReference: string;
          }
          interface HighlightSpan {
              textSpan: TextSpan;
              kind: string;
          }
          interface NavigateToItem {
              name: string;
              kind: string;
              kindModifiers: string;
              matchKind: string;
              isCaseSensitive: boolean;
              fileName: string;
              textSpan: TextSpan;
              containerName: string;
              containerKind: string;
          }
          interface EditorOptions {
              IndentSize: number;
              TabSize: number;
              NewLineCharacter: string;
              ConvertTabsToSpaces: boolean;
          }
          interface FormatCodeOptions extends EditorOptions {
              InsertSpaceAfterCommaDelimiter: boolean;
              InsertSpaceAfterSemicolonInForStatements: boolean;
              InsertSpaceBeforeAndAfterBinaryOperators: boolean;
              InsertSpaceAfterKeywordsInControlFlowStatements: boolean;
              InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean;
              InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean;
              PlaceOpenBraceOnNewLineForFunctions: boolean;
              PlaceOpenBraceOnNewLineForControlBlocks: boolean;
              [s: string]: boolean | number | string;
          }
          interface DefinitionInfo {
              fileName: string;
              textSpan: TextSpan;
              kind: string;
              name: string;
              containerKind: string;
              containerName: string;
          }
          interface ReferencedSymbol {
              definition: DefinitionInfo;
              references: ReferenceEntry[];
          }
          enum SymbolDisplayPartKind {
              aliasName = 0,
              className = 1,
              enumName = 2,
              fieldName = 3,
              interfaceName = 4,
              keyword = 5,
              lineBreak = 6,
              numericLiteral = 7,
              stringLiteral = 8,
              localName = 9,
              methodName = 10,
              moduleName = 11,
              operator = 12,
              parameterName = 13,
              propertyName = 14,
              punctuation = 15,
              space = 16,
              text = 17,
              typeParameterName = 18,
              enumMemberName = 19,
              functionName = 20,
              regularExpressionLiteral = 21,
          }
          interface SymbolDisplayPart {
              text: string;
              kind: string;
          }
          interface QuickInfo {
              kind: string;
              kindModifiers: string;
              textSpan: TextSpan;
              displayParts: SymbolDisplayPart[];
              documentation: SymbolDisplayPart[];
          }
          interface RenameInfo {
              canRename: boolean;
              localizedErrorMessage: string;
              displayName: string;
              fullDisplayName: string;
              kind: string;
              kindModifiers: string;
              triggerSpan: TextSpan;
          }
          interface SignatureHelpParameter {
              name: string;
              documentation: SymbolDisplayPart[];
              displayParts: SymbolDisplayPart[];
              isOptional: boolean;
          }
          /**
           * Represents a single signature to show in signature help.
           * The id is used for subsequent calls into the language service to ask questions about the
           * signature help item in the context of any documents that have been updated.  i.e. after
           * an edit has happened, while signature help is still active, the host can ask important
           * questions like 'what parameter is the user currently contained within?'.
           */
          interface SignatureHelpItem {
              isVariadic: boolean;
              prefixDisplayParts: SymbolDisplayPart[];
              suffixDisplayParts: SymbolDisplayPart[];
              separatorDisplayParts: SymbolDisplayPart[];
              parameters: SignatureHelpParameter[];
              documentation: SymbolDisplayPart[];
          }
          /**
           * Represents a set of signature help items, and the preferred item that should be selected.
           */
          interface SignatureHelpItems {
              items: SignatureHelpItem[];
              applicableSpan: TextSpan;
              selectedItemIndex: number;
              argumentIndex: number;
              argumentCount: number;
          }
          interface CompletionInfo {
              isMemberCompletion: boolean;
              isNewIdentifierLocation: boolean;
              entries: CompletionEntry[];
          }
          interface CompletionEntry {
              name: string;
              kind: string;
              kindModifiers: string;
              sortText: string;
          }
          interface CompletionEntryDetails {
              name: string;
              kind: string;
              kindModifiers: string;
              displayParts: SymbolDisplayPart[];
              documentation: SymbolDisplayPart[];
          }
          interface OutliningSpan {
              /** The span of the document to actually collapse. */
              textSpan: TextSpan;
              /** The span of the document to display when the user hovers over the collapsed span. */
              hintSpan: TextSpan;
              /** The text to display in the editor for the collapsed region. */
              bannerText: string;
              /**
                * Whether or not this region should be automatically collapsed when
                * the 'Collapse to Definitions' command is invoked.
                */
              autoCollapse: boolean;
          }
          interface EmitOutput {
              outputFiles: OutputFile[];
              emitSkipped: boolean;
          }
          const enum OutputFileType {
              JavaScript = 0,
              SourceMap = 1,
              Declaration = 2,
          }
          interface OutputFile {
              name: string;
              writeByteOrderMark: boolean;
              text: string;
          }
          const enum EndOfLineState {
              Start = 0,
              InMultiLineCommentTrivia = 1,
              InSingleQuoteStringLiteral = 2,
              InDoubleQuoteStringLiteral = 3,
              InTemplateHeadOrNoSubstitutionTemplate = 4,
              InTemplateMiddleOrTail = 5,
              InTemplateSubstitutionPosition = 6,
          }
          enum TokenClass {
              Punctuation = 0,
              Keyword = 1,
              Operator = 2,
              Comment = 3,
              Whitespace = 4,
              Identifier = 5,
              NumberLiteral = 6,
              StringLiteral = 7,
              RegExpLiteral = 8,
          }
          interface ClassificationResult {
              finalLexState: EndOfLineState;
              entries: ClassificationInfo[];
          }
          interface ClassificationInfo {
              length: number;
              classification: TokenClass;
          }
          interface Classifier {
              /**
               * Gives lexical classifications of tokens on a line without any syntactic context.
               * For instance, a token consisting of the text 'string' can be either an identifier
               * named 'string' or the keyword 'string', however, because this classifier is not aware,
               * it relies on certain heuristics to give acceptable results. For classifications where
               * speed trumps accuracy, this function is preferable; however, for true accuracy, the
               * syntactic classifier is ideal. In fact, in certain editing scenarios, combining the
               * lexical, syntactic, and semantic classifiers may issue the best user experience.
               *
               * @param text                      The text of a line to classify.
               * @param lexState                  The state of the lexical classifier at the end of the previous line.
               * @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier.
               *                                  If there is no syntactic classifier (syntacticClassifierAbsent=true),
               *                                  certain heuristics may be used in its place; however, if there is a
               *                                  syntactic classifier (syntacticClassifierAbsent=false), certain
               *                                  classifications which may be incorrectly categorized will be given
               *                                  back as Identifiers in order to allow the syntactic classifier to
               *                                  subsume the classification.
               */
              getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult;
          }
          /**
            * The document registry represents a store of SourceFile objects that can be shared between
            * multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST)
            * of files in the context.
            * SourceFile objects account for most of the memory usage by the language service. Sharing
            * the same DocumentRegistry instance between different instances of LanguageService allow
            * for more efficient memory utilization since all projects will share at least the library
            * file (lib.d.ts).
            *
            * A more advanced use of the document registry is to serialize sourceFile objects to disk
            * and re-hydrate them when needed.
            *
            * To create a default DocumentRegistry, use createDocumentRegistry to create one, and pass it
            * to all subsequent createLanguageService calls.
            */
          interface DocumentRegistry {
              /**
                * Request a stored SourceFile with a given fileName and compilationSettings.
                * The first call to acquire will call createLanguageServiceSourceFile to generate
                * the SourceFile if was not found in the registry.
                *
                * @param fileName The name of the file requested
                * @param compilationSettings Some compilation settings like target affects the
                * shape of a the resulting SourceFile. This allows the DocumentRegistry to store
                * multiple copies of the same file for different compilation settings.
                * @parm scriptSnapshot Text of the file. Only used if the file was not found
                * in the registry and a new one was created.
                * @parm version Current version of the file. Only used if the file was not found
                * in the registry and a new one was created.
                */
              acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile;
              /**
                * Request an updated version of an already existing SourceFile with a given fileName
                * and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile
                * to get an updated SourceFile.
                *
                * @param fileName The name of the file requested
                * @param compilationSettings Some compilation settings like target affects the
                * shape of a the resulting SourceFile. This allows the DocumentRegistry to store
                * multiple copies of the same file for different compilation settings.
                * @param scriptSnapshot Text of the file.
                * @param version Current version of the file.
                */
              updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile;
              /**
                * Informs the DocumentRegistry that a file is not needed any longer.
                *
                * Note: It is not allowed to call release on a SourceFile that was not acquired from
                * this registry originally.
                *
                * @param fileName The name of the file to be released
                * @param compilationSettings The compilation settings used to acquire the file
                */
              releaseDocument(fileName: string, compilationSettings: CompilerOptions): void;
          }
          module ScriptElementKind {
              const unknown: string;
              const warning: string;
              const keyword: string;
              const scriptElement: string;
              const moduleElement: string;
              const classElement: string;
              const interfaceElement: string;
              const typeElement: string;
              const enumElement: string;
              const variableElement: string;
              const localVariableElement: string;
              const functionElement: string;
              const localFunctionElement: string;
              const memberFunctionElement: string;
              const memberGetAccessorElement: string;
              const memberSetAccessorElement: string;
              const memberVariableElement: string;
              const constructorImplementationElement: string;
              const callSignatureElement: string;
              const indexSignatureElement: string;
              const constructSignatureElement: string;
              const parameterElement: string;
              const typeParameterElement: string;
              const primitiveType: string;
              const label: string;
              const alias: string;
              const constElement: string;
              const letElement: string;
          }
          module ScriptElementKindModifier {
              const none: string;
              const publicMemberModifier: string;
              const privateMemberModifier: string;
              const protectedMemberModifier: string;
              const exportedModifier: string;
              const ambientModifier: string;
              const staticModifier: string;
          }
          class ClassificationTypeNames {
              static comment: string;
              static identifier: string;
              static keyword: string;
              static numericLiteral: string;
              static operator: string;
              static stringLiteral: string;
              static whiteSpace: string;
              static text: string;
              static punctuation: string;
              static className: string;
              static enumName: string;
              static interfaceName: string;
              static moduleName: string;
              static typeParameterName: string;
              static typeAlias: string;
          }
          interface DisplayPartsSymbolWriter extends SymbolWriter {
              displayParts(): SymbolDisplayPart[];
          }
          function displayPartsToString(displayParts: SymbolDisplayPart[]): string;
          function getDefaultCompilerOptions(): CompilerOptions;
          class OperationCanceledException {
          }
          class CancellationTokenObject {
              private cancellationToken;
              static None: CancellationTokenObject;
              constructor(cancellationToken: CancellationToken);
              isCancellationRequested(): boolean;
              throwIfCancellationRequested(): void;
          }
          function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[]): string;
          function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean): SourceFile;
          let disableIncrementalParsing: boolean;
          function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile;
          function createDocumentRegistry(): DocumentRegistry;
          function preProcessFile(sourceText: string, readImportFiles?: boolean): PreProcessedFileInfo;
          function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry): LanguageService;
          function createClassifier(): Classifier;
          /**
            * Get the path of the default library file (lib.d.ts) as distributed with the typescript
            * node package.
            * The functionality is not supported if the ts module is consumed outside of a node module.
            */
          function getDefaultLibFilePath(options: CompilerOptions): string;
      }
      
    • websql.d.ts
      declare function openDatabase(
        name: string,
        version: any,
        displayName: string,
        size: number,
        upgrade?: DatabaseCallback): Database;
      
      interface DatabaseCallback {
        (database: Database): void;
      }
      
      interface Database {
        transaction(
          callback: (transaction: SQLTransaction) => void,
          errorCallback?: (error: SQLError) => void,
          successCallback?: () => void);
      
        readTransaction(
          callback: (transaction: SQLTransaction) => void,
          errorCallback?: (error: SQLError) => void,
          successCallback?: () => void);
      
        version: string;
      
        changeVersion(
          oldVersion: string,
          newVersion: string,
          callback: (transaction: SQLTransaction) => void,
          errorCallback?: (error: SQLError) => void,
          successCallback?: () => void);
      }
      
      interface SQLTransaction {
        executeSql(
          sqlStatement: string,
          arguments?: any[],
          callback?: (transaction: SQLTransaction, result: SQLResultSet) => void,
          errorCallback?: (transaction: SQLTransaction, error: SQLError) => void): void;
      }
      
      interface SQLError {
        /**
         * UNKNOWN_ERR = 0;
         * DATABASE_ERR = 1;
         * VERSION_ERR = 2;
         * TOO_LARGE_ERR = 3;
         * QUOTA_ERR = 4;
         * SYNTAX_ERR = 5;
         * CONSTRAINT_ERR = 6;
        * TIMEOUT_ERR = 7;
         */
        code: number;
        message: string
      }
      
      interface SQLResultSet {
        insertId: number;
        rowsAffected: number;
        rows: SQLResultSetRowList;
      }
      
      interface SQLResultSetRowList {
        length: number;
        item(index: number): any;
      }
    • zip.d.ts
      declare module zip {
      
        export var useWebWorkers: boolean;
      
        export function createReader(reader: Reader, callback: (reader: ZipReader) => void, onerror?);
        export function createWriter(writer: Writer, callback: (writer: ZipWriter) => void, onerror?);
      
        export interface Reader {
        }
      
        export interface Writer {
        }
      
        export interface ZipReader {
          getEntries(callback: (entries: Entry[]) => void);
          close(callback: () => void);
        }
      
        export interface ZipWriter {
          add(
            name: string,
            reader: Reader,
            onend,
            onprogress?: (index: number, max: number) => void,
            options?: { directory?: boolean; level?: number; comment?: string; lastModDate?: Date; version?: number; });
      
          close(callback);
        }
      
        export interface Entry {
          filename: string;
          directory: boolean;
          compressedSize: number;
          uncompressedSize: number;
          lastModDate: number;
          lastModDateRaw: number;
          comment: string;
          crc32: number;
      
          getData(writer: Writer, onend?, onprogress?: (index: number, maxValue: number) => void, checkCrc32?: boolean);
        }
      
        export class BlobWriter implements Writer {
          constructor(contentType: string);
        }
          
        export class TextWriter implements Writer {
        }
      
        export class TextReader implements Reader {
          constructor(text: string);
        }
      
        export class BlobReader implements Reader {
          constructor(arg: any);
        }
      }
  • errors.js
    var _errorCache = [];
    _errorCache.byText = {};
    
    window.onerror = function(errObj, file, line, ch, err) {
    
      var txt = err ? err.stack || err.message || err + '' : errObj;
    
      var firstTrigger = _errorCache.length === 0;
      if (_errorCache.byText[txt]) {
        _errorCache.byText[txt]++;
      }
      else {
        _errorCache.byText[txt]=1;
        _errorCache.push(txt);
      }
    
      if (firstTrigger)
        setTimeout(function() {
          var errorText = _errorCache.map(function(txt){return _errorCache.byText[txt]+' - '+txt}).join('\n');
          _errorCache = [];
          _errorCache.byText = {};
          alert(errorText);
        }, 100);
    };
    
  • functions.ts
    module portabled {
    
      /** Stoppable timer with methods specifically targeting debouncing. */
      export class Timer {
    
        private _timeout = 0;
        private _maxTimeout = 0;
        private _tickClosure = () => this._tick();
    
        constructor() {
        }
    
        interval = 300;
        maxInterval = 1000;
    
        ontick: () => void = null;
    
        reset() {
          if (this._timeout)
            clearTimeout(this._timeout);
    
          if (!this._maxTimeout && this.maxInterval)
            this._maxTimeout = setTimeout(this._tickClosure, this.maxInterval);
    
          if (this.interval)
            this._timeout = setTimeout(this._tickClosure, this.interval);
        }
    
        stop() {
          if (this._timeout)
            clearTimeout(this._timeout);
          if (this._maxTimeout)
            clearTimeout(this._maxTimeout);
          this._timeout = 0;
          this._maxTimeout = 0;
        }
    
        endWaiting() {
          if (this.isWaiting())
            this._tick();
        }
    
        isWaiting() {
          return this._timeout || this._maxTimeout ? true : false;
        }
    
        private _tick() {
          this.stop();
          if (this.ontick) {
            var t = this.ontick;
            t();
          }
        }
    
      }
    
      export function asyncForEach<T, TResult>(
        array: T[],
        handleElement: (element: T, index: number, callback: (error: Error, res: TResult) => void) => void,
        callback: (error: Error, res: TResult[]) => void) {
    
        if (!array || !array.length) {
          callback(null, []);
          return;
        }
    
        var res: TResult[] = [];
        var stop = false;
        var completeCount = 0;
        forEach(array, (element, index) => {
          if (stop) return;
          handleElement(element[index], index, (error, resElement) => {
            if (stop) return;
            if (error) {
              stop = true;
              callback(error, null);
              return;
            }
            res[index] = resElement;
            completeCount++;
            if (completeCount === array.length) {
              stop = true;
              callback(null, res);
            }
          });
        });
      }
    
      export function forEach<T>(array: T[], callback: (x: T, index: number) => void) {
        if (array.forEach) {
          array.forEach(callback);
        }
        else {
          for (var i = 0; i < array.length; i++) {
            callback(array[i], i);
          }
        }
      }
    
      export function find<T, R>(array: T[], predicate: (x: T, index: number) => R): R {
        var result = null;
        for (var i = 0; i < array.length; i++) {
          var x = array[i];
          var p = predicate(x, i);
          if (p) return p;
        }
      }
    
      /**
     * Escape unsafe character sequences like a closing script tag.
     */
      export function encodeForInnerHTML(content: string): string {
        // matching script closing tag with *one* or more consequtive slashes
        return content.replace(/<\/+script/g, (match) => {
          return '</' + match.slice(1); // skip angle bracket, inject bracket and extra slash
        });
      }
    
      /**
       * Unescape character sequences wrapped with encodeForInnerHTML for safety.
       */
      export function decodeFromInnerHTML(innerHTML: string): string {
        // matching script closing tag with *t*wo or more consequtive slashes
        return innerHTML.replace(/<\/\/+script/g, (match) => {
          return '<' + match.slice(2); // skip angle bracket and one slash, inject bracket
        });
      }
    
      export function encodeForAttributeName(value: string): string {
        var codes: number[] = [];
        var passableOnly = true;
    
        for (var i = 0; i < value.length; i++) {
          var c = value.charAt(i);
          var cc = value.charCodeAt(i);
          codes.push(cc);
          if (passableOnly)
            passableOnly = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z' || c === '_' || c === '-');
        }
    
        if (passableOnly)
          return 's-' + value;
        else
          return 'n-' + codes.join('-');
      }
    
      export function decodeFromAttributeName(attributeNamePart: string): string {
        if (attributeNamePart.slice(0, 2) === 's-')
          return attributeNamePart.slice(2);
    
        var codes = attributeNamePart.slice(2).split('-');
        var result: string[] = [];
        for (var i = 0; i < codes.length; i++) {
          try {
            result[i] = String.fromCharCode(parseInt(codes[i]));
          }
          catch (error) {
            console.log('Parsing attribute name error: ' + attributeNamePart + ' has non-numeric chunk ' + i + ' (' + codes[i] + ').');
            return null;
          }
        }
        return result.join('');
      }
    
      export function startsWith(str: string, prefix: string) {
        if (!str) return !prefix;
        if (!prefix) return false;
        if (str.length < prefix.length) return false;
        if (str.charCodeAt(0) !== prefix.charCodeAt(0)) return false;
        if (str.slice(0, prefix.length) !== prefix) return false;
        else return true;
      }
    
      export function dateNow(): number {
        if (Date.now)
          return Date.now();
        else
          return new Date().valueOf();
      }
    
      export var objectKeys = (obj: any): string[]=> {
        if (typeof Object.keys === 'function')
          objectKeys = Object.keys;
        else
          objectKeys = (obj: any): string[]=> {
            var result: string[] = [];
            for (var k in obj) if (obj.hasOwnProperty(k)) {
              result.push(k);
            }
            return result;
          };
    
        return objectKeys(obj);
      };
    
      export function addEventListener(element: any, type: string, listener: (event: Event) => void) {
        if (element.addEventListener) {
          element.addEventListener(type, listener, true);
        }
        else {
          var ontype = 'on' + type;
    
          if (element.attachEvent) {
            element.attachEvent('on' + type, listener);
          }
          else if (ontype in element) {
            element[ontype] = listener;
          }
        }
      }
    
      export function removeEventListener(element: any, type: string, listener: (event: Event) => void) {
        if (element.addEventListener) {
          element.removeEventListener(type, listener, true);
        }
        else {
          var ontype = 'on' + type;
    
          if (element.detachEvent) {
            element.detachEvent('on' + type, listener);
          }
          else if (ontype in element) {
            element[ontype] = null;
          }
        }
      }
    
      export function setTextContent(element: HTMLElement, textContent: string) {
        if (!_useTextContent)
          _useTextContent = detectTextContent(element);
        if (_useTextContent === 1)
          element.textContent = textContent;
        else
          element.innerText = textContent;
      }
    
      var _useTextContent = 0;
      function detectTextContent(element: HTMLElement) {
        if ('textContent' in element)
          return 1;
        else
          return 2;
      }
    
      export function element(tag: string, style?: any, parent?: HTMLElement): HTMLElement {
        var el = document.createElement(tag);
        if (style) {
          if (typeof style === 'string') {
            setTextContent(el, style);
          }
          else if (!parent && typeof style.scrollIntoView === 'function') {
            parent = style;
          }
          else {
            for (var k in style) if (style.hasOwnProperty(k)) {
              if (k === 'text')
                setTextContent(el, style.text);
              else
                el.style[k] = style[k];
            }
          }
        }
    
        if (parent)
          parent.appendChild(el);
    
        return el;
      }
      
      /**
       * JS Implementation of MurmurHash2
       * 
       * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
       * @see http://github.com/garycourt/murmurhash-js
       * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
       * @see http://sites.google.com/site/murmurhash/
       * 
       * @param {string} str ASCII only
       * @param {number} seed Positive integer only
       * @return {number} 32-bit positive integer hash
       */
      export function murmurhash2_32_gc(str, seed) {
        var
          l = str.length,
          h = seed ^ l,
          i = 0,
          k;
    
        while (l >= 4) {
          k =
          ((str.charCodeAt(i) & 0xff)) |
          ((str.charCodeAt(++i) & 0xff) << 8) |
          ((str.charCodeAt(++i) & 0xff) << 16) |
          ((str.charCodeAt(++i) & 0xff) << 24);
    
          k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
          k ^= k >>> 24;
          k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
    
          h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
    
          l -= 4;
          ++i;
        }
    
        switch (l) {
          case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
          case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
          case 1: h ^= (str.charCodeAt(i) & 0xff);
            h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
        }
    
        h ^= h >>> 13;
        h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
        h ^= h >>> 15;
    
        return h >>> 0;
      }
    }
  • index.html
    <!doctype html><html><head>
    <meta charset="utf-8">
    <title>portabled - [portabled v0.6.1a]</title>
    
    <style>
      <%/*uglifyJS.skip = true*/%>
      <%=uglifyCSS(
    
      	// CodeMirror CSS
      	'imports/codemirror/lib/codemirror.css',
      	'imports/codemirror/addon/hint/show-hint.css',
      	'imports/codemirror/addon/lint/lint.css',
      	'imports/codemirror/addon/dialog/dialog.css',
      	'imports/codemirror/addon/merge/merge.css',
      	'imports/codemirror/addon/fold/foldgutter.css',
    
        // portabled CSS
      	'app/body.css',
      	'app/flyout.css',
      	'app/flyout-branding.css',
      	'app/tree-and-bar.css',
      	'app/status.css',
    
      	'files/FileTree.css',
      	'docs/types/text/CodeMirror-ext.css',
      	'app/moreDialog/style.css',
      	'docs/types/text/scrollerView/style.css',
      
      	'docs/types/text/ts/style.css',
      
      	'app/loading.css')
    	%>
    </style>
    
    <% /* embedFile('imports/codemirror/addon/tern/tern.css') */ %>
    
    
    </head>
    <body
        data-bind="event: {keydown:keydown}">
    
    
    <!-- ES5 shim/sham, JSON3 -->
    <script data-legit=portabled>
      <%=embedFile('imports/es5-shim/es5-shim.min.js', 'imports/es5-shim/es5-sham.min.js', 'imports/json3/json3.min.js')%>
    </script>
    
    
    <!-- Error handling script -->
    <script data-legit=portabled><%=embedFile('errors.js')%></script>
    
    <!-- Main portabled JS code -->
    <script data-legit=portabled><%=function(){ var ts = typescriptBuild(); var tsstr = ts(); var ug = uglifyJS(tsstr); return typeof ug === 'function' ? ug() : ug; }%></script>
    
    <div id=portabled-loading-host>
      <div id=portabled-loading-title>
        Booting...
      </div>
      <div id=portabled-loading-progress>
      </div>
    </div>
    
    <script data-legit=portabled>
    
      // Detect JS syntax error in compiled script (resulting in no top-level module),
      // report early to avoid complicated debugging when things are trivially wrong.
    
      if (typeof portabled === 'undefined') {
        alert('Syntax error in the compiled script.');
      }
      else {
      	try { portabled.app.loading('Page layout...'); } catch (err) { alert(err+' '+err.stack); }
      }
    
    </script>
    
    <div class=portabled-flyout-scroller
       data-bind="load: flyoutScroller = $element">
      <div class=portabled-flyout-scroller-bg>
    
        <div class=portabled-main-content
           data-bind="loadRaw: docHostRegions.content = $element"></div>
    
        <div class=portabled-flyout>
    
          <div class=portabled-thick-bar-host>
            <button class=portabled-more-button data-bind="click: moreClick"> ... </button>
            <div class=portabled-thick-bar-bg>
              <div class=portabled-thick-bar
                   data-bind="event: { mousedown: thickbarMouseDown }, loadRaw: docHostRegions.scroller = $element">
              </div>
            </div>
          </div>
    
    <script data-legit=portabled>
      if (typeof portabled !== 'undefined')
        try { portabled.app.loading('Files...'); } catch (err) { alert(err+' '+err.stack); }
    </script>
    
          <div class=portabled-file-tree
             timestamp="<%=new Date().getTime()%>"
             data-bind="loadRaw: fileTreeHost = $element">
    
            <ul>
    
              <%=embedTree()%>
    
            </ul>
          </div>
    
    <script data-legit=portabled>
      if (typeof portabled !== 'undefined')
      	try { portabled.app.loading('Controls...'); } catch (err) { alert(err+' '+err.stack); }
    </script>
    
          <div class=portabled-extra-content>
    
            <div class=portabled-branding-area
                 data-bind="loadRaw: brandingArea=$element "></div>
    
    
           <div class=portabled-scrollable-bottom>
    
              <div class=portabled-links>
                <button data-bind="click: deleteClick" style="min-width: 7em; margin-bottom: 0.3em;"> Delete </button> <br>
                <button data-bind="click: buildClick" style="min-width: 7em;"> Build </button> <br>
                <br>
                <a href=# data-bind="click: exportAllHTML"> Save whole page </a><br>
                <a href=# data-bind="click: commitToGitHub"> Commit to GitHub </a><br>
                <a href=# data-bind="click: exportAllZIP"> Export to ZIP </a><br>
                <a href=# data-bind="click: exportCurrentFile"> Save current file </a><br>
                <br>
                <a href=# data-bind="click: importText"> Add file </a><br>
                <a href=# data-bind="click: importBase64"> Add binary (base64) </a><br>
                <a href=# data-bind="click: importZIP"> Import files from ZIP </a><br>
                <a href=# data-bind="click: importPortabledHTML"> Import files from portabled </a><br>
    
              </div>
    
              <div class=portabled-credits>
    
                portabled v0.6.1a by Oleg Mihailik<br><span style="font-size:80%;">built <%=new Date()%></span><br>
                <br>
    
                <div style="font-size: 90%;">
                  Used Open Source libraries:<br>
                  <a href="https://github.com/Microsoft/TypeScript">TypeScript</a> (Microsoft, with Apache 2.0 license) <br>
                  <a href="https://github.com/codemirror/CodeMirror">CodeMirror</a> (Marijn Haverbeke, with MIT license) <br>
                  <a href="https://github.com/knockout/knockout">Knockout.js</a> (Ryan Niemeyer, with MIT license) <br>
                  <a href="https://github.com/gildas-lormeau/zip.js">Zip.js</a> (Gildas Lormeau, with BSD license) <br>
                  <a href="https://github.com/chjj/marked">Marked</a> (Christopher Jeffrey, with MIT license) <br>
                  <a href="https://github.com/es-shims/es5-shim">ES5-shims<a/> (with MIT license)<br>
                  <a href="https://github.com/michael/github">GitHub API wrapper</a> (Michael Aufreiter with BSD2 license)<br>
                  <a href="https://github.com/garycourt/murmurhash-js">JS Murmur hasher</a> (Gary Court with MIT license)<br>
                  <a href="https://code.google.com/p/google-diff-match-patch/">google-diff-match-patch</a> (Google with Apache 2.0 license)<br>
                  <a href="https://github.com/mishoo/UglifyJS2">UglifyJS2</a> (Mihai Bazon with BSD license)<br>
                  <a href="https://github.com/mishoo/UglifyCSS">UglifyCSS</a> (Franck Marcia with MIT license)<br>
                  <a href="https://github.com/bestiejs/json3">JSON3</a> (Kit Cambridge with MIT license)<br>
                  - main contributors mentioned where applicable.
                </div>
    
              </div>
    
            </div>
    
          </div>
    
          
          
        </div>
    
      </div>
    </div>
    
    <div class=portabled-status-bar
       data-bind="loadRaw: docHostRegions.status = $element">
    </div>
    
    <script data-legit=portabled>try { portabled.app.loading('Libraries...'); } catch (err) { alert(err+' '+err.stack); }</script>
    
    
    <% /* embedFile(
       'imports/acorn/acorn.js',
       'imports/acorn/acorn_loose.js',
       'imports/acorn/walk.js',
       'imports/tern/signal.js',
       'imports/tern/tern.js',
       'imports/tern/def.js'
       'imports/tern/comment.js',
       'imports/tern/infer.js',
       'imports/tern/doc_comment.js') */%>
    
    <!-- Google diff/merge algorithm (used for a CodeMirror addon needed for the neat file import dialog) -->
    <script data-legit=portabled><%=embedFile('imports/google-diff-match-patch/diff_match_patch.js')%></script>
    
    <!-- CodeMirror -->
    <script data-legit=portabled>
      <%=uglifyJS([
      	'imports/codemirror/lib/codemirror.js',
      	'imports/codemirror/addon/dialog/dialog.js',
      	'imports/codemirror/addon/search/search.js',
      	'imports/codemirror/addon/search/searchcursor.js',
      	'imports/codemirror/addon/hint/show-hint.js',
      	'imports/codemirror/addon/lint/lint.js',
      	'imports/codemirror/mode/javascript/javascript.js',
      	'imports/codemirror/addon/tern/tern.js',
      	'imports/codemirror/addon/hint/javascript-hint.js',
      	'imports/codemirror/mode/css/css.js',
      	'imports/codemirror/addon/hint/css-hint.js',
      	'imports/codemirror/mode/sass/sass.js',
      	'imports/codemirror/mode/xml/xml.js',
      	'imports/codemirror/addon/hint/xml-hint.js',
      	'imports/codemirror/mode/htmlmixed/htmlmixed.js',
      	'imports/codemirror/mode/htmlembedded/htmlembedded.js',
      	'imports/codemirror/addon/hint/html-hint.js',
      	'imports/codemirror/mode/markdown/markdown.js',
      	'imports/codemirror/addon/edit/matchbrackets.js',
      	'imports/codemirror/addon/selection/active-line.js',
      	'imports/codemirror/addon/edit/trailingspace.js',
      	'imports/codemirror/addon/fold/foldcode.js',
      	'imports/codemirror/addon/fold/foldgutter.js',
      	'imports/codemirror/addon/fold/brace-fold.js',
      	'imports/codemirror/addon/fold/comment-fold.js',
      	'imports/codemirror/addon/fold/markdown-fold.js',
      	'imports/codemirror/addon/fold/xml-fold.js',
      	'imports/codemirror/addon/merge/merge.js'])%></script>
    
    <!-- Knockout -->
    <script data-legit=portabled>
      <%=uglifyJS(['imports/knockout/knockout-3.2.0.js'])%>
    </script>
    
    <!-- Zip.js -->
    <script data-legit=portabled>
      <%=uglifyJS([
        'imports/zip.js/zip.js',
        'imports/zip.js/deflate.js',
        'imports/zip.js/inflate.js'])%>
    </script>
    
    <!-- Marked -->
    <script data-legit=portabled>
      <%=uglifyJS(['imports/marked/marked.js'])%>
    </script>
    
    <!-- Uglify2 -->
    <script data-legit=portabled>
    var Uglify2;
    (function(Uglify2) {
      <%=uglifyJS([
        'imports/uglify2/utils.js',
        'imports/uglify2/ast.js',
        'imports/uglify2/parse.js',
        'imports/uglify2/transform.js',
        'imports/uglify2/scope.js',
        'imports/uglify2/output.js',
        'imports/uglify2/compress.js'
      ])%>
      Uglify2.Compressor = Compressor;
      Uglify2.parse = parse
      
    })(Uglify2 || (Uglify2={}))
    </script>
    
    <!-- UglifyCSS -->
    <script data-legit=portabled>
    var UglifyCSS;
    (function(UglifyCSS) {
      function require() { return {}; }
      var module = { exports: { }};
      <%=embedFile('imports/uglifyCSS/uglifycss-lib.js')%>
      for (var k in module.exports) {
        if (module.exports.hasOwnProperty(k))
        	UglifyCSS[k] = module.exports[k];
      }
    })(UglifyCSS || (UglifyCSS={}))
    </script>
        
    
    
    <script type=text/html id=MoreDialogView data-legit=portabled><%=embedFile('app/moreDialog/layout.html')%></script>
    <script type=text/html id=ScrollerView data-legit=portabled><%=embedFile('docs/types/text/scrollerView/ScrollerView.html')%></script>
    
    <script data-legit=portabled><%=uglifyJS('imports/typescript/typescriptServices.js')%></script>
    <script data-legit=portabled id=core.d.ts type=text/typescriptdefinition><%=embedFile('imports/typescript/core.d.ts.text')%></script>
    <script data-legit=portabled id=dom.generated.d.ts type=text/typescriptdefinition><%=embedFile('imports/typescript/dom.generated.d.ts.text')%></script>
    <script data-legit=portabled id=extensions.d.ts type=text/typescriptdefinition><%=embedFile('imports/typescript/extensions.d.ts.text')%></script>
    
    
    <!--
    <script data-legit=portabled type="text/javascript" src="https://getfirebug.com/firebug-lite.js">
    {
        overrideConsole: true,
        startInNewWindow: false,
        startOpened: true
    }
    </script>
    -->
    
    <script data-legit=portabled>
      if (typeof portabled !== 'undefined')
      	try { portabled.app.start(); } catch (err) { alert(err+' '+err.stack); }
    </script>
    
    <div id=portabled-last-element></div>
    
    </body>
    </html>
    
  • readme.md
    # portabled v0.6.1a
    
    Self-editing filesystem embedded in a single HTML file.
    
    The idea, all of the painstaking implementation and the vision by [Oleg Mihailik](mailto:mihailik@gmail.com).
    See the credits section for the used libraries and respective licences.
    
    ### Outstanding tasks:
     * Unifying of all import/export into 'moreDialog'.
     * Download/upload for GitHub, GDrive, Dropbox etc.
     * Extra power in Chrome app, node-webkit, HTMLA-ie7: I/O to the actual filesystem.
     * Delete folder.
     * Rename file/folder.
     * Saving current position in documents.
     * TypeScript extra features: navigate to, search integration, tooltips.
     * Sub-domains for TypeScript/JavaScript completion/build contexts.
     * Doc handlers in plugins, plugin API and isolation (using iframes with their own 'global' and 'require').
     * node.js emulation for plugins and dependencies, allowing non-doc plugins.
     * Highlight of **changes** in files.
     * Styles and colours (planning for pale seaside 'Whitstable' blue, maybe black theme too).
     * Scrollbar to use syntax-highlighted document lines.
     * Toast popup/fadeout messages for key events: opening, building, import-export completion.
     * Add whole raw TypeScript repository sample.
  • try.js
    var __resizeTimer = 0;
    if (false)
    window.onresize = function() {
      if (!__resizeTimer)
        clearTimeout(__resizeTimer);
      __resizeTimer = setTimeout(function(){
        alert('Resize!')
      }, 700);
    }
    
    var doss = document.createElement('pre');
    doss.textContent = '<pre>abcdef    1\n2      2\n\n </pre>';
    alert(doss.innerHTML)
    alert(doss.textContent)

portabled v0.6.1a

Self-editing filesystem embedded in a single HTML file.

The idea, all of the painstaking implementation and the vision by Oleg Mihailik. See the credits section for the used libraries and respective licences.

Outstanding tasks:

  • Unifying of all import/export into 'moreDialog'.
  • Download/upload for GitHub, GDrive, Dropbox etc.
  • Extra power in Chrome app, node-webkit, HTMLA-ie7: I/O to the actual filesystem.
  • Delete folder.
  • Rename file/folder.
  • Saving current position in documents.
  • TypeScript extra features: navigate to, search integration, tooltips.
  • Sub-domains for TypeScript/JavaScript completion/build contexts.
  • Doc handlers in plugins, plugin API and isolation (using iframes with their own 'global' and 'require').
  • node.js emulation for plugins and dependencies, allowing non-doc plugins.
  • Highlight of changes in files.
  • Styles and colours (planning for pale seaside 'Whitstable' blue, maybe black theme too).
  • Scrollbar to use syntax-highlighted document lines.
  • Toast popup/fadeout messages for key events: opening, building, import-export completion.
  • Add whole raw TypeScript repository sample.
portabled v0.6.1a by Oleg Mihailik
built Tue May 05 2015 23:13:55 GMT+0100 (GMT Summer Time)

Used Open Source libraries:
TypeScript (Microsoft, with Apache 2.0 license)
CodeMirror (Marijn Haverbeke, with MIT license)
Knockout.js (Ryan Niemeyer, with MIT license)
Zip.js (Gildas Lormeau, with BSD license)
Marked (Christopher Jeffrey, with MIT license)
ES5-shims (with MIT license)
GitHub API wrapper (Michael Aufreiter with BSD2 license)
JS Murmur hasher (Gary Court with MIT license)
google-diff-match-patch (Google with Apache 2.0 license)
UglifyJS2 (Mihai Bazon with BSD license)
UglifyCSS (Franck Marcia with MIT license)
JSON3 (Kit Cambridge with MIT license)
- main contributors mentioned where applicable.
/index.html